From e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 22:34:10 +0200 Subject: Adding upstream version 4.2.2. Signed-off-by: Daniel Baumann --- plugins/codecs/G711/CMakeLists.txt | 64 + plugins/codecs/G711/G711decode.c | 202 + plugins/codecs/G722/CMakeLists.txt | 66 + plugins/codecs/G722/G722decode.c | 99 + plugins/codecs/G726/CMakeLists.txt | 66 + plugins/codecs/G726/G726decode.c | 135 + plugins/codecs/G729/CMakeLists.txt | 66 + plugins/codecs/G729/G729decode.c | 109 + plugins/codecs/amrnb/CMakeLists.txt | 66 + plugins/codecs/amrnb/amrdecode.c | 274 + plugins/codecs/iLBC/CMakeLists.txt | 66 + plugins/codecs/iLBC/iLBCdecode.c | 141 + plugins/codecs/l16_mono/AUTHORS | 2 + plugins/codecs/l16_mono/CMakeLists.txt | 64 + plugins/codecs/l16_mono/README | 3 + plugins/codecs/l16_mono/l16decode.c | 122 + plugins/codecs/opus_dec/CMakeLists.txt | 66 + plugins/codecs/opus_dec/opusdecode.c | 107 + plugins/codecs/sbc/CMakeLists.txt | 66 + plugins/codecs/sbc/sbc.c | 142 + plugins/epan/ethercat/AUTHORS | 5 + plugins/epan/ethercat/CMakeLists.txt | 70 + plugins/epan/ethercat/packet-ams.c | 1245 ++ plugins/epan/ethercat/packet-ams.h | 1153 ++ plugins/epan/ethercat/packet-ecatmb.c | 1995 +++ plugins/epan/ethercat/packet-ecatmb.h | 469 + plugins/epan/ethercat/packet-esl.c | 372 + plugins/epan/ethercat/packet-ethercat-datagram.c | 3745 ++++ plugins/epan/ethercat/packet-ethercat-datagram.h | 36 + plugins/epan/ethercat/packet-ethercat-frame.c | 153 + plugins/epan/ethercat/packet-ethercat-frame.h | 33 + plugins/epan/ethercat/packet-ioraw.c | 119 + plugins/epan/ethercat/packet-ioraw.h | 21 + plugins/epan/ethercat/packet-nv.c | 240 + plugins/epan/ethercat/packet-nv.h | 34 + plugins/epan/falco_bridge/AUTHORS | 2 + plugins/epan/falco_bridge/CMakeLists.txt | 82 + plugins/epan/falco_bridge/README.md | 56 + plugins/epan/falco_bridge/packet-falco-bridge.c | 676 + plugins/epan/falco_bridge/sinsp-span.cpp | 239 + plugins/epan/falco_bridge/sinsp-span.h | 80 + plugins/epan/gryphon/AUTHORS | 8 + plugins/epan/gryphon/CMakeLists.txt | 64 + plugins/epan/gryphon/README | 11 + plugins/epan/gryphon/packet-gryphon.c | 5332 ++++++ plugins/epan/gryphon/packet-gryphon.h | 592 + plugins/epan/irda/CMakeLists.txt | 66 + plugins/epan/irda/irda-appl.h | 87 + plugins/epan/irda/packet-ircomm.c | 428 + plugins/epan/irda/packet-irda.c | 2327 +++ plugins/epan/irda/packet-sir.c | 236 + plugins/epan/mate/.editorconfig | 3 + plugins/epan/mate/AUTHORS | 3 + plugins/epan/mate/CMakeLists.txt | 85 + plugins/epan/mate/examples/call.mate | 34 + plugins/epan/mate/examples/mms.mate | 40 + plugins/epan/mate/examples/pasv_ftp.mate | 18 + plugins/epan/mate/examples/tcp.mate | 7 + plugins/epan/mate/examples/web.mate | 27 + plugins/epan/mate/mate.h | 373 + plugins/epan/mate/mate_grammar.lemon | 729 + plugins/epan/mate/mate_parser.l | 409 + plugins/epan/mate/mate_runtime.c | 930 + plugins/epan/mate/mate_setup.c | 667 + plugins/epan/mate/mate_util.c | 1690 ++ plugins/epan/mate/mate_util.h | 249 + plugins/epan/mate/matelib/dns.mate | 6 + plugins/epan/mate/matelib/h225_ras.mate | 9 + plugins/epan/mate/matelib/isup.mate | 23 + plugins/epan/mate/matelib/megaco.mate | 8 + plugins/epan/mate/matelib/q931.mate | 6 + plugins/epan/mate/matelib/radius.mate | 12 + plugins/epan/mate/matelib/rtsp.mate | 10 + plugins/epan/mate/matelib/sip.mate | 12 + plugins/epan/mate/packet-mate.c | 453 + plugins/epan/opcua/AUTHORS | 7 + plugins/epan/opcua/CMakeLists.txt | 81 + plugins/epan/opcua/ChangeLog | 19 + plugins/epan/opcua/Doxyfile | 275 + plugins/epan/opcua/README | 86 + plugins/epan/opcua/opcua.c | 457 + plugins/epan/opcua/opcua_application_layer.c | 112 + plugins/epan/opcua/opcua_application_layer.h | 20 + plugins/epan/opcua/opcua_complextypeparser.c | 2264 +++ plugins/epan/opcua/opcua_complextypeparser.h | 445 + plugins/epan/opcua/opcua_enumparser.c | 675 + plugins/epan/opcua/opcua_enumparser.h | 81 + plugins/epan/opcua/opcua_extensionobjectids.h | 159 + plugins/epan/opcua/opcua_extensionobjecttable.c | 215 + plugins/epan/opcua/opcua_hfindeces.c | 630 + plugins/epan/opcua/opcua_hfindeces.h | 322 + plugins/epan/opcua/opcua_identifiers.h | 43 + plugins/epan/opcua/opcua_security_layer.c | 60 + plugins/epan/opcua/opcua_security_layer.h | 18 + plugins/epan/opcua/opcua_serviceids.h | 187 + plugins/epan/opcua/opcua_serviceparser.c | 1317 ++ plugins/epan/opcua/opcua_serviceparser.h | 273 + plugins/epan/opcua/opcua_servicetable.c | 300 + plugins/epan/opcua/opcua_servicetable.h | 17 + plugins/epan/opcua/opcua_simpletypes.c | 1398 ++ plugins/epan/opcua/opcua_simpletypes.h | 105 + plugins/epan/opcua/opcua_statuscode.c | 267 + plugins/epan/opcua/opcua_statuscode.h | 16 + plugins/epan/opcua/opcua_transport_layer.c | 245 + plugins/epan/opcua/opcua_transport_layer.h | 27 + plugins/epan/pluginifdemo/AUTHORS | 2 + plugins/epan/pluginifdemo/CMakeLists.txt | 75 + plugins/epan/pluginifdemo/README | 2 + plugins/epan/pluginifdemo/pluginifdemo.c | 156 + plugins/epan/pluginifdemo/pluginifdemo.h | 11 + .../epan/pluginifdemo/ui/pluginifdemo_about.cpp | 49 + plugins/epan/pluginifdemo/ui/pluginifdemo_about.h | 53 + plugins/epan/pluginifdemo/ui/pluginifdemo_about.ui | 156 + plugins/epan/pluginifdemo/ui/pluginifdemo_main.cpp | 382 + plugins/epan/pluginifdemo/ui/pluginifdemo_main.h | 124 + plugins/epan/pluginifdemo/ui/pluginifdemo_main.ui | 369 + plugins/epan/pluginifdemo/ui/uiclasshandler.cpp | 116 + plugins/epan/pluginifdemo/ui/uihandler.cpp | 74 + plugins/epan/pluginifdemo/ui/uihandler.h | 89 + plugins/epan/profinet/AUTHORS | 4 + plugins/epan/profinet/CMakeLists.txt | 80 + plugins/epan/profinet/ChangeLog | 33 + plugins/epan/profinet/packet-dcerpc-pn-io.c | 17887 +++++++++++++++++++ plugins/epan/profinet/packet-dcom-cba-acco.c | 5158 ++++++ plugins/epan/profinet/packet-dcom-cba-acco.h | 59 + plugins/epan/profinet/packet-dcom-cba.c | 1730 ++ plugins/epan/profinet/packet-pn-dcp.c | 2096 +++ plugins/epan/profinet/packet-pn-mrp.c | 675 + plugins/epan/profinet/packet-pn-mrrt.c | 247 + plugins/epan/profinet/packet-pn-ptcp.c | 1093 ++ plugins/epan/profinet/packet-pn-rsi.c | 1087 ++ plugins/epan/profinet/packet-pn-rt.c | 1204 ++ plugins/epan/profinet/packet-pn-rtc-one.c | 1356 ++ plugins/epan/profinet/packet-pn.c | 1518 ++ plugins/epan/profinet/packet-pn.h | 204 + plugins/epan/stats_tree/AUTHORS | 3 + plugins/epan/stats_tree/CMakeLists.txt | 62 + plugins/epan/stats_tree/pinfo_stats_tree.c | 371 + plugins/epan/stats_tree/pinfo_stats_tree.h | 13 + plugins/epan/transum/AUTHORS | 2 + plugins/epan/transum/CMakeLists.txt | 72 + plugins/epan/transum/README | 6 + plugins/epan/transum/decoders.c | 335 + plugins/epan/transum/decoders.h | 31 + plugins/epan/transum/extractors.c | 165 + plugins/epan/transum/extractors.h | 21 + plugins/epan/transum/packet-transum.c | 1366 ++ plugins/epan/transum/packet-transum.h | 189 + plugins/epan/transum/preferences.h | 41 + plugins/epan/unistim/AUTHORS | 4 + plugins/epan/unistim/CMakeLists.txt | 64 + plugins/epan/unistim/ChangeLog | 5 + plugins/epan/unistim/TODO | 7 + plugins/epan/unistim/audio.h | 560 + plugins/epan/unistim/basic.h | 71 + plugins/epan/unistim/broadcast.h | 88 + plugins/epan/unistim/defines.h | 228 + plugins/epan/unistim/display.h | 261 + plugins/epan/unistim/expansion.h | 27 + plugins/epan/unistim/key.h | 152 + plugins/epan/unistim/network.h | 221 + plugins/epan/unistim/packet-unistim.c | 3866 ++++ plugins/epan/unistim/packet-unistim.h | 37 + plugins/epan/unistim/uftp.h | 34 + plugins/epan/wimax/.editorconfig | 10 + plugins/epan/wimax/AUTHORS | 5 + plugins/epan/wimax/CMakeLists.txt | 112 + plugins/epan/wimax/README.wimax | 86 + plugins/epan/wimax/crc.c | 198 + plugins/epan/wimax/crc.h | 33 + plugins/epan/wimax/crc_data.c | 171 + plugins/epan/wimax/mac_hd_generic_decoder.c | 2300 +++ plugins/epan/wimax/mac_hd_type1_decoder.c | 560 + plugins/epan/wimax/mac_hd_type2_decoder.c | 1370 ++ plugins/epan/wimax/mac_mgmt_msg_decoder.c | 367 + plugins/epan/wimax/msg_aas_beam.c | 340 + plugins/epan/wimax/msg_aas_fbck.c | 349 + plugins/epan/wimax/msg_arq.c | 446 + plugins/epan/wimax/msg_clk_cmp.c | 150 + plugins/epan/wimax/msg_dcd.c | 1257 ++ plugins/epan/wimax/msg_dlmap.c | 3482 ++++ plugins/epan/wimax/msg_dreg.c | 529 + plugins/epan/wimax/msg_dsa.c | 184 + plugins/epan/wimax/msg_dsc.c | 185 + plugins/epan/wimax/msg_dsd.c | 279 + plugins/epan/wimax/msg_dsx_rvd.c | 107 + plugins/epan/wimax/msg_fpc.c | 166 + plugins/epan/wimax/msg_pkm.c | 178 + plugins/epan/wimax/msg_pmc.c | 248 + plugins/epan/wimax/msg_prc_lt_ctrl.c | 136 + plugins/epan/wimax/msg_reg_req.c | 1440 ++ plugins/epan/wimax/msg_reg_rsp.c | 365 + plugins/epan/wimax/msg_rep.c | 1564 ++ plugins/epan/wimax/msg_res_cmd.c | 154 + plugins/epan/wimax/msg_rng_req.c | 631 + plugins/epan/wimax/msg_rng_rsp.c | 963 + plugins/epan/wimax/msg_sbc.c | 2836 +++ plugins/epan/wimax/msg_ucd.c | 1243 ++ plugins/epan/wimax/msg_ulmap.c | 2942 +++ plugins/epan/wimax/packet-m2m.c | 809 + plugins/epan/wimax/packet-wmx.c | 366 + plugins/epan/wimax/wimax-int.h | 30 + plugins/epan/wimax/wimax_bits.h | 194 + plugins/epan/wimax/wimax_cdma_code_decoder.c | 116 + .../epan/wimax/wimax_compact_dlmap_ie_decoder.c | 2111 +++ .../epan/wimax/wimax_compact_dlmap_ie_decoder.h | 20 + .../epan/wimax/wimax_compact_ulmap_ie_decoder.c | 2125 +++ .../epan/wimax/wimax_compact_ulmap_ie_decoder.h | 20 + plugins/epan/wimax/wimax_fch_decoder.c | 246 + plugins/epan/wimax/wimax_ffb_decoder.c | 129 + plugins/epan/wimax/wimax_hack_decoder.c | 141 + plugins/epan/wimax/wimax_harq_map_decoder.c | 233 + plugins/epan/wimax/wimax_mac.h | 689 + plugins/epan/wimax/wimax_pdu_decoder.c | 255 + plugins/epan/wimax/wimax_phy_attributes_decoder.c | 178 + plugins/epan/wimax/wimax_tlv.c | 175 + plugins/epan/wimax/wimax_tlv.h | 45 + plugins/epan/wimax/wimax_utils.c | 3385 ++++ plugins/epan/wimax/wimax_utils.h | 58 + plugins/epan/wimaxasncp/AUTHORS | 5 + plugins/epan/wimaxasncp/CMakeLists.txt | 70 + plugins/epan/wimaxasncp/ChangeLog | 16 + plugins/epan/wimaxasncp/packet-wimaxasncp.c | 3468 ++++ plugins/epan/wimaxasncp/wimaxasncp_dict.h | 114 + plugins/epan/wimaxasncp/wimaxasncp_dict.l | 867 + plugins/epan/wimaxmacphy/AUTHORS | 5 + plugins/epan/wimaxmacphy/CMakeLists.txt | 64 + plugins/epan/wimaxmacphy/ChangeLog | 5 + plugins/epan/wimaxmacphy/packet-wimaxmacphy.c | 5434 ++++++ plugins/epan/wimaxmacphy/packet-wimaxmacphy.h | 18 + plugins/plugin.rc.in | 35 + plugins/wiretap/usbdump/AUTHORS | 2 + plugins/wiretap/usbdump/CMakeLists.txt | 64 + plugins/wiretap/usbdump/README | 3 + plugins/wiretap/usbdump/usbdump.c | 355 + 235 files changed, 129453 insertions(+) create mode 100644 plugins/codecs/G711/CMakeLists.txt create mode 100644 plugins/codecs/G711/G711decode.c create mode 100644 plugins/codecs/G722/CMakeLists.txt create mode 100644 plugins/codecs/G722/G722decode.c create mode 100644 plugins/codecs/G726/CMakeLists.txt create mode 100644 plugins/codecs/G726/G726decode.c create mode 100644 plugins/codecs/G729/CMakeLists.txt create mode 100644 plugins/codecs/G729/G729decode.c create mode 100644 plugins/codecs/amrnb/CMakeLists.txt create mode 100644 plugins/codecs/amrnb/amrdecode.c create mode 100644 plugins/codecs/iLBC/CMakeLists.txt create mode 100644 plugins/codecs/iLBC/iLBCdecode.c create mode 100644 plugins/codecs/l16_mono/AUTHORS create mode 100644 plugins/codecs/l16_mono/CMakeLists.txt create mode 100644 plugins/codecs/l16_mono/README create mode 100644 plugins/codecs/l16_mono/l16decode.c create mode 100644 plugins/codecs/opus_dec/CMakeLists.txt create mode 100644 plugins/codecs/opus_dec/opusdecode.c create mode 100644 plugins/codecs/sbc/CMakeLists.txt create mode 100644 plugins/codecs/sbc/sbc.c create mode 100644 plugins/epan/ethercat/AUTHORS create mode 100644 plugins/epan/ethercat/CMakeLists.txt create mode 100644 plugins/epan/ethercat/packet-ams.c create mode 100644 plugins/epan/ethercat/packet-ams.h create mode 100644 plugins/epan/ethercat/packet-ecatmb.c create mode 100644 plugins/epan/ethercat/packet-ecatmb.h create mode 100644 plugins/epan/ethercat/packet-esl.c create mode 100644 plugins/epan/ethercat/packet-ethercat-datagram.c create mode 100644 plugins/epan/ethercat/packet-ethercat-datagram.h create mode 100644 plugins/epan/ethercat/packet-ethercat-frame.c create mode 100644 plugins/epan/ethercat/packet-ethercat-frame.h create mode 100644 plugins/epan/ethercat/packet-ioraw.c create mode 100644 plugins/epan/ethercat/packet-ioraw.h create mode 100644 plugins/epan/ethercat/packet-nv.c create mode 100644 plugins/epan/ethercat/packet-nv.h create mode 100644 plugins/epan/falco_bridge/AUTHORS create mode 100644 plugins/epan/falco_bridge/CMakeLists.txt create mode 100644 plugins/epan/falco_bridge/README.md create mode 100644 plugins/epan/falco_bridge/packet-falco-bridge.c create mode 100644 plugins/epan/falco_bridge/sinsp-span.cpp create mode 100644 plugins/epan/falco_bridge/sinsp-span.h create mode 100644 plugins/epan/gryphon/AUTHORS create mode 100644 plugins/epan/gryphon/CMakeLists.txt create mode 100644 plugins/epan/gryphon/README create mode 100644 plugins/epan/gryphon/packet-gryphon.c create mode 100644 plugins/epan/gryphon/packet-gryphon.h create mode 100644 plugins/epan/irda/CMakeLists.txt create mode 100644 plugins/epan/irda/irda-appl.h create mode 100644 plugins/epan/irda/packet-ircomm.c create mode 100644 plugins/epan/irda/packet-irda.c create mode 100644 plugins/epan/irda/packet-sir.c create mode 100644 plugins/epan/mate/.editorconfig create mode 100644 plugins/epan/mate/AUTHORS create mode 100644 plugins/epan/mate/CMakeLists.txt create mode 100644 plugins/epan/mate/examples/call.mate create mode 100644 plugins/epan/mate/examples/mms.mate create mode 100644 plugins/epan/mate/examples/pasv_ftp.mate create mode 100644 plugins/epan/mate/examples/tcp.mate create mode 100644 plugins/epan/mate/examples/web.mate create mode 100644 plugins/epan/mate/mate.h create mode 100644 plugins/epan/mate/mate_grammar.lemon create mode 100644 plugins/epan/mate/mate_parser.l create mode 100644 plugins/epan/mate/mate_runtime.c create mode 100644 plugins/epan/mate/mate_setup.c create mode 100644 plugins/epan/mate/mate_util.c create mode 100644 plugins/epan/mate/mate_util.h create mode 100644 plugins/epan/mate/matelib/dns.mate create mode 100644 plugins/epan/mate/matelib/h225_ras.mate create mode 100644 plugins/epan/mate/matelib/isup.mate create mode 100644 plugins/epan/mate/matelib/megaco.mate create mode 100644 plugins/epan/mate/matelib/q931.mate create mode 100644 plugins/epan/mate/matelib/radius.mate create mode 100644 plugins/epan/mate/matelib/rtsp.mate create mode 100644 plugins/epan/mate/matelib/sip.mate create mode 100644 plugins/epan/mate/packet-mate.c create mode 100644 plugins/epan/opcua/AUTHORS create mode 100644 plugins/epan/opcua/CMakeLists.txt create mode 100644 plugins/epan/opcua/ChangeLog create mode 100644 plugins/epan/opcua/Doxyfile create mode 100644 plugins/epan/opcua/README create mode 100644 plugins/epan/opcua/opcua.c create mode 100644 plugins/epan/opcua/opcua_application_layer.c create mode 100644 plugins/epan/opcua/opcua_application_layer.h create mode 100644 plugins/epan/opcua/opcua_complextypeparser.c create mode 100644 plugins/epan/opcua/opcua_complextypeparser.h create mode 100644 plugins/epan/opcua/opcua_enumparser.c create mode 100644 plugins/epan/opcua/opcua_enumparser.h create mode 100644 plugins/epan/opcua/opcua_extensionobjectids.h create mode 100644 plugins/epan/opcua/opcua_extensionobjecttable.c create mode 100644 plugins/epan/opcua/opcua_hfindeces.c create mode 100644 plugins/epan/opcua/opcua_hfindeces.h create mode 100644 plugins/epan/opcua/opcua_identifiers.h create mode 100644 plugins/epan/opcua/opcua_security_layer.c create mode 100644 plugins/epan/opcua/opcua_security_layer.h create mode 100644 plugins/epan/opcua/opcua_serviceids.h create mode 100644 plugins/epan/opcua/opcua_serviceparser.c create mode 100644 plugins/epan/opcua/opcua_serviceparser.h create mode 100644 plugins/epan/opcua/opcua_servicetable.c create mode 100644 plugins/epan/opcua/opcua_servicetable.h create mode 100644 plugins/epan/opcua/opcua_simpletypes.c create mode 100644 plugins/epan/opcua/opcua_simpletypes.h create mode 100644 plugins/epan/opcua/opcua_statuscode.c create mode 100644 plugins/epan/opcua/opcua_statuscode.h create mode 100644 plugins/epan/opcua/opcua_transport_layer.c create mode 100644 plugins/epan/opcua/opcua_transport_layer.h create mode 100644 plugins/epan/pluginifdemo/AUTHORS create mode 100644 plugins/epan/pluginifdemo/CMakeLists.txt create mode 100644 plugins/epan/pluginifdemo/README create mode 100644 plugins/epan/pluginifdemo/pluginifdemo.c create mode 100644 plugins/epan/pluginifdemo/pluginifdemo.h create mode 100644 plugins/epan/pluginifdemo/ui/pluginifdemo_about.cpp create mode 100644 plugins/epan/pluginifdemo/ui/pluginifdemo_about.h create mode 100644 plugins/epan/pluginifdemo/ui/pluginifdemo_about.ui create mode 100644 plugins/epan/pluginifdemo/ui/pluginifdemo_main.cpp create mode 100644 plugins/epan/pluginifdemo/ui/pluginifdemo_main.h create mode 100644 plugins/epan/pluginifdemo/ui/pluginifdemo_main.ui create mode 100644 plugins/epan/pluginifdemo/ui/uiclasshandler.cpp create mode 100644 plugins/epan/pluginifdemo/ui/uihandler.cpp create mode 100644 plugins/epan/pluginifdemo/ui/uihandler.h create mode 100644 plugins/epan/profinet/AUTHORS create mode 100644 plugins/epan/profinet/CMakeLists.txt create mode 100644 plugins/epan/profinet/ChangeLog create mode 100644 plugins/epan/profinet/packet-dcerpc-pn-io.c create mode 100644 plugins/epan/profinet/packet-dcom-cba-acco.c create mode 100644 plugins/epan/profinet/packet-dcom-cba-acco.h create mode 100644 plugins/epan/profinet/packet-dcom-cba.c create mode 100644 plugins/epan/profinet/packet-pn-dcp.c create mode 100644 plugins/epan/profinet/packet-pn-mrp.c create mode 100644 plugins/epan/profinet/packet-pn-mrrt.c create mode 100644 plugins/epan/profinet/packet-pn-ptcp.c create mode 100644 plugins/epan/profinet/packet-pn-rsi.c create mode 100644 plugins/epan/profinet/packet-pn-rt.c create mode 100644 plugins/epan/profinet/packet-pn-rtc-one.c create mode 100644 plugins/epan/profinet/packet-pn.c create mode 100644 plugins/epan/profinet/packet-pn.h create mode 100644 plugins/epan/stats_tree/AUTHORS create mode 100644 plugins/epan/stats_tree/CMakeLists.txt create mode 100644 plugins/epan/stats_tree/pinfo_stats_tree.c create mode 100644 plugins/epan/stats_tree/pinfo_stats_tree.h create mode 100644 plugins/epan/transum/AUTHORS create mode 100644 plugins/epan/transum/CMakeLists.txt create mode 100644 plugins/epan/transum/README create mode 100644 plugins/epan/transum/decoders.c create mode 100644 plugins/epan/transum/decoders.h create mode 100644 plugins/epan/transum/extractors.c create mode 100644 plugins/epan/transum/extractors.h create mode 100644 plugins/epan/transum/packet-transum.c create mode 100644 plugins/epan/transum/packet-transum.h create mode 100644 plugins/epan/transum/preferences.h create mode 100644 plugins/epan/unistim/AUTHORS create mode 100644 plugins/epan/unistim/CMakeLists.txt create mode 100644 plugins/epan/unistim/ChangeLog create mode 100644 plugins/epan/unistim/TODO create mode 100644 plugins/epan/unistim/audio.h create mode 100644 plugins/epan/unistim/basic.h create mode 100644 plugins/epan/unistim/broadcast.h create mode 100644 plugins/epan/unistim/defines.h create mode 100644 plugins/epan/unistim/display.h create mode 100644 plugins/epan/unistim/expansion.h create mode 100644 plugins/epan/unistim/key.h create mode 100644 plugins/epan/unistim/network.h create mode 100644 plugins/epan/unistim/packet-unistim.c create mode 100644 plugins/epan/unistim/packet-unistim.h create mode 100644 plugins/epan/unistim/uftp.h create mode 100644 plugins/epan/wimax/.editorconfig create mode 100644 plugins/epan/wimax/AUTHORS create mode 100644 plugins/epan/wimax/CMakeLists.txt create mode 100644 plugins/epan/wimax/README.wimax create mode 100644 plugins/epan/wimax/crc.c create mode 100644 plugins/epan/wimax/crc.h create mode 100644 plugins/epan/wimax/crc_data.c create mode 100644 plugins/epan/wimax/mac_hd_generic_decoder.c create mode 100644 plugins/epan/wimax/mac_hd_type1_decoder.c create mode 100644 plugins/epan/wimax/mac_hd_type2_decoder.c create mode 100644 plugins/epan/wimax/mac_mgmt_msg_decoder.c create mode 100644 plugins/epan/wimax/msg_aas_beam.c create mode 100644 plugins/epan/wimax/msg_aas_fbck.c create mode 100644 plugins/epan/wimax/msg_arq.c create mode 100644 plugins/epan/wimax/msg_clk_cmp.c create mode 100644 plugins/epan/wimax/msg_dcd.c create mode 100644 plugins/epan/wimax/msg_dlmap.c create mode 100644 plugins/epan/wimax/msg_dreg.c create mode 100644 plugins/epan/wimax/msg_dsa.c create mode 100644 plugins/epan/wimax/msg_dsc.c create mode 100644 plugins/epan/wimax/msg_dsd.c create mode 100644 plugins/epan/wimax/msg_dsx_rvd.c create mode 100644 plugins/epan/wimax/msg_fpc.c create mode 100644 plugins/epan/wimax/msg_pkm.c create mode 100644 plugins/epan/wimax/msg_pmc.c create mode 100644 plugins/epan/wimax/msg_prc_lt_ctrl.c create mode 100644 plugins/epan/wimax/msg_reg_req.c create mode 100644 plugins/epan/wimax/msg_reg_rsp.c create mode 100644 plugins/epan/wimax/msg_rep.c create mode 100644 plugins/epan/wimax/msg_res_cmd.c create mode 100644 plugins/epan/wimax/msg_rng_req.c create mode 100644 plugins/epan/wimax/msg_rng_rsp.c create mode 100644 plugins/epan/wimax/msg_sbc.c create mode 100644 plugins/epan/wimax/msg_ucd.c create mode 100644 plugins/epan/wimax/msg_ulmap.c create mode 100644 plugins/epan/wimax/packet-m2m.c create mode 100644 plugins/epan/wimax/packet-wmx.c create mode 100644 plugins/epan/wimax/wimax-int.h create mode 100644 plugins/epan/wimax/wimax_bits.h create mode 100644 plugins/epan/wimax/wimax_cdma_code_decoder.c create mode 100644 plugins/epan/wimax/wimax_compact_dlmap_ie_decoder.c create mode 100644 plugins/epan/wimax/wimax_compact_dlmap_ie_decoder.h create mode 100644 plugins/epan/wimax/wimax_compact_ulmap_ie_decoder.c create mode 100644 plugins/epan/wimax/wimax_compact_ulmap_ie_decoder.h create mode 100644 plugins/epan/wimax/wimax_fch_decoder.c create mode 100644 plugins/epan/wimax/wimax_ffb_decoder.c create mode 100644 plugins/epan/wimax/wimax_hack_decoder.c create mode 100644 plugins/epan/wimax/wimax_harq_map_decoder.c create mode 100644 plugins/epan/wimax/wimax_mac.h create mode 100644 plugins/epan/wimax/wimax_pdu_decoder.c create mode 100644 plugins/epan/wimax/wimax_phy_attributes_decoder.c create mode 100644 plugins/epan/wimax/wimax_tlv.c create mode 100644 plugins/epan/wimax/wimax_tlv.h create mode 100644 plugins/epan/wimax/wimax_utils.c create mode 100644 plugins/epan/wimax/wimax_utils.h create mode 100644 plugins/epan/wimaxasncp/AUTHORS create mode 100644 plugins/epan/wimaxasncp/CMakeLists.txt create mode 100644 plugins/epan/wimaxasncp/ChangeLog create mode 100644 plugins/epan/wimaxasncp/packet-wimaxasncp.c create mode 100644 plugins/epan/wimaxasncp/wimaxasncp_dict.h create mode 100644 plugins/epan/wimaxasncp/wimaxasncp_dict.l create mode 100644 plugins/epan/wimaxmacphy/AUTHORS create mode 100644 plugins/epan/wimaxmacphy/CMakeLists.txt create mode 100644 plugins/epan/wimaxmacphy/ChangeLog create mode 100644 plugins/epan/wimaxmacphy/packet-wimaxmacphy.c create mode 100644 plugins/epan/wimaxmacphy/packet-wimaxmacphy.h create mode 100644 plugins/plugin.rc.in create mode 100644 plugins/wiretap/usbdump/AUTHORS create mode 100644 plugins/wiretap/usbdump/CMakeLists.txt create mode 100644 plugins/wiretap/usbdump/README create mode 100644 plugins/wiretap/usbdump/usbdump.c (limited to 'plugins') diff --git a/plugins/codecs/G711/CMakeLists.txt b/plugins/codecs/G711/CMakeLists.txt new file mode 100644 index 00000000..cc9ff0f1 --- /dev/null +++ b/plugins/codecs/G711/CMakeLists.txt @@ -0,0 +1,64 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(g711 0 1 0 0) + +set(CODEC_SRC + G711decode.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(g711 codecs) + +target_include_directories(g711 PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(g711 wsutil) + +install_plugin(g711 codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + g711 + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/G711/G711decode.c b/plugins/codecs/G711/G711decode.c new file mode 100644 index 00000000..e15c4076 --- /dev/null +++ b/plugins/codecs/G711/G711decode.c @@ -0,0 +1,202 @@ +/* G711adecode.c + * A-law G.711 codec + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include "wsutil/codecs.h" +#include "ws_attributes.h" + +static gint16 ulaw_exp_table[256] = { + -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956, + -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764, + -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412, + -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316, + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, + -876, -844, -812, -780, -748, -716, -684, -652, + -620, -588, -556, -524, -492, -460, -428, -396, + -372, -356, -340, -324, -308, -292, -276, -260, + -244, -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, -64, + -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, + 876, 844, 812, 780, 748, 716, 684, 652, + 620, 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, 260, + 244, 228, 212, 196, 180, 164, 148, 132, + 120, 112, 104, 96, 88, 80, 72, 64, + 56, 48, 40, 32, 24, 16, 8, 0 +}; + +static gint16 alaw_exp_table[256] = { + -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944, + -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136, + -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472, + -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848, + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848 +}; + +void codec_register_g711(void); + +static void * +codec_g711u_init(codec_context_t *ctx _U_) +{ + return NULL; +} + +static void +codec_g711u_release(codec_context_t *ctx _U_) +{ + +} + +static unsigned +codec_g711u_get_channels(codec_context_t *ctx _U_) +{ + return 1; +} + +static unsigned +codec_g711u_get_frequency(codec_context_t *ctx _U_) +{ + return 8000; +} + +static size_t +codec_g711u_decode(codec_context_t *ctx _U_, + const void *inputBytes, size_t inputBytesSize, + void *outputSamples, size_t *outputSamplesSize) +{ + const guint8 *dataIn = (const guint8 *) inputBytes; + gint16 *dataOut = (gint16 *) outputSamples; + size_t i; + + if (!outputSamples || !outputSamplesSize) { + return inputBytesSize * 2; + } + + for (i = 0; i < inputBytesSize; i++) + { + dataOut[i] = ulaw_exp_table[dataIn[i]]; + } + + *outputSamplesSize = inputBytesSize * 2; + return inputBytesSize * 2; +} + +static void * +codec_g711a_init(codec_context_t *ctx _U_) +{ + return NULL; +} + +static void +codec_g711a_release(codec_context_t *ctx _U_) +{ + +} + +static unsigned +codec_g711a_get_channels(codec_context_t *ctx _U_) +{ + return 1; +} + +static unsigned +codec_g711a_get_frequency(codec_context_t *ctx _U_) +{ + return 8000; +} + +static size_t +codec_g711a_decode(codec_context_t *ctx _U_, + const void *inputBytes, size_t inputBytesSize, + void *outputSamples, size_t *outputSamplesSize) +{ + const guint8 *dataIn = (const guint8 *) inputBytes; + gint16 *dataOut = (gint16 *) outputSamples; + size_t i; + + if (!outputSamples || !outputSamplesSize) { + return inputBytesSize * 2; + } + + for (i = 0; i < inputBytesSize; i++) + { + dataOut[i] = alaw_exp_table[dataIn[i]]; + } + + *outputSamplesSize = inputBytesSize * 2; + return inputBytesSize * 2; +} + +void +codec_register_g711(void) +{ + register_codec("g711U", codec_g711u_init, codec_g711u_release, + codec_g711u_get_channels, codec_g711u_get_frequency, codec_g711u_decode); + register_codec("g711A", codec_g711a_init, codec_g711a_release, + codec_g711a_get_channels, codec_g711a_get_frequency, codec_g711a_decode); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/codecs/G722/CMakeLists.txt b/plugins/codecs/G722/CMakeLists.txt new file mode 100644 index 00000000..37c08cd1 --- /dev/null +++ b/plugins/codecs/G722/CMakeLists.txt @@ -0,0 +1,66 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(g722 0 1 0 0) + +set(CODEC_SRC + G722decode.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(g722 codecs) + +target_include_directories(g722 PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(g722 wsutil ${SPANDSP_LIBRARIES}) + +target_include_directories(g722 SYSTEM PRIVATE ${SPANDSP_INCLUDE_DIRS}) + +install_plugin(g722 codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + g722 + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/G722/G722decode.c b/plugins/codecs/G722/G722decode.c new file mode 100644 index 00000000..30c46107 --- /dev/null +++ b/plugins/codecs/G722/G722decode.c @@ -0,0 +1,99 @@ +/* G722decode.c + * G.722 codec + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include "spandsp.h" +#include "wsutil/codecs.h" +#include "ws_attributes.h" + +void codec_register_g722(void); + +static void * +codec_g722_init(codec_context_t *ctx _U_) +{ + g722_decode_state_t *state; + + /* Valid values for bit_rate for G.722 are 48000, 56000, 64000, but RTP/AVP + * profile requires 64kbps, aligned at octets. */ + state = g722_decode_init(NULL, 64000, 0); + + return state; +} + +static void +codec_g722_release(codec_context_t *ctx) +{ + g722_decode_state_t *state = (g722_decode_state_t *)ctx->priv; + + if (!state) { + return; /* out-of-memory; */ + } + + /* Note: replaces g722_decode_release since SpanDSP 20090211 */ + g722_decode_free(state); +} + +static unsigned +codec_g722_get_channels(codec_context_t *ctx _U_) +{ + /* G.722 has only one channel. */ + return 1; +} + +static unsigned +codec_g722_get_frequency(codec_context_t *ctx _U_) +{ + /* Note: RTP Clock rate is 8kHz due to a historic error, but actual sampling + * rate is 16kHz (RFC 3551, section 4.5.2). */ + return 16000; +} + +static size_t +codec_g722_decode(codec_context_t *ctx, const void *inputBytes, + size_t inputBytesSize, void *outputSamples, size_t *outputSamplesSize) +{ + g722_decode_state_t *state = (g722_decode_state_t *)ctx->priv; + + if (!state) { + return 0; /* out-of-memory; */ + } + + if (!outputSamples || !outputSamplesSize) { + return 4 * inputBytesSize; + } + + /* g722_decode returns the number of 16-bit samples. */ + *outputSamplesSize = 2 * g722_decode(state, (int16_t *)outputSamples, + (const uint8_t *)inputBytes, (int)inputBytesSize); + return *outputSamplesSize; +} + +void +codec_register_g722(void) +{ + register_codec("g722", codec_g722_init, codec_g722_release, + codec_g722_get_channels, codec_g722_get_frequency, codec_g722_decode); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/codecs/G726/CMakeLists.txt b/plugins/codecs/G726/CMakeLists.txt new file mode 100644 index 00000000..239b67f0 --- /dev/null +++ b/plugins/codecs/G726/CMakeLists.txt @@ -0,0 +1,66 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(g726 0 1 0 0) + +set(CODEC_SRC + G726decode.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(g726 codecs) + +target_include_directories(g726 PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(g726 wsutil ${SPANDSP_LIBRARIES}) + +target_include_directories(g726 SYSTEM PRIVATE ${SPANDSP_INCLUDE_DIRS}) + +install_plugin(g726 codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + g726 + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/G726/G726decode.c b/plugins/codecs/G726/G726decode.c new file mode 100644 index 00000000..92965251 --- /dev/null +++ b/plugins/codecs/G726/G726decode.c @@ -0,0 +1,135 @@ +/* G726decode.c + * G.726 codec + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include "spandsp.h" +#include "wsutil/codecs.h" +#include "ws_attributes.h" + +typedef struct _g726_codec_ctx { + g726_state_t *state; + int bit_rate; +} g726_codec_ctx; + +void codec_register_g726(void); + +static void * +codec_g726_init(int bit_rate, int packing) +{ + g726_state_t *decoder = g726_init(NULL, bit_rate, G726_ENCODING_LINEAR, packing); + + if (!decoder) { + return NULL; /* out-of-memory; */ + } + + g726_codec_ctx *state = g_new(g726_codec_ctx, 1); + state->state = decoder; + state->bit_rate = bit_rate; + + return state; +} + +static void *codec_g726_16_init(codec_context_t *ctx _U_) { return codec_g726_init(16000, G726_PACKING_RIGHT); } +static void *codec_g726_24_init(codec_context_t *ctx _U_) { return codec_g726_init(24000, G726_PACKING_RIGHT); } +static void *codec_g726_32_init(codec_context_t *ctx _U_) { return codec_g726_init(32000, G726_PACKING_RIGHT); } +static void *codec_g726_40_init(codec_context_t *ctx _U_) { return codec_g726_init(40000, G726_PACKING_RIGHT); } +static void *codec_aal2_g726_16_init(codec_context_t *ctx _U_) { return codec_g726_init(16000, G726_PACKING_LEFT); } +static void *codec_aal2_g726_24_init(codec_context_t *ctx _U_) { return codec_g726_init(24000, G726_PACKING_LEFT); } +static void *codec_aal2_g726_32_init(codec_context_t *ctx _U_) { return codec_g726_init(32000, G726_PACKING_LEFT); } +static void *codec_aal2_g726_40_init(codec_context_t *ctx _U_) { return codec_g726_init(40000, G726_PACKING_LEFT); } + +static void +codec_g726_release(codec_context_t *ctx) +{ + g726_codec_ctx *state = (g726_codec_ctx *)(ctx->priv); + + if (!state) { + return; /* out-of-memory; */ + } + + /* Note: replaces g726_release since SpanDSP 20090211 */ + g726_free(state->state); + g_free(state); +} + +static unsigned +codec_g726_get_channels(codec_context_t *ctx _U_) +{ + return 1; +} + +static unsigned +codec_g726_get_frequency(codec_context_t *ctx _U_) +{ + return 8000; +} + +static size_t +codec_g726_decode(codec_context_t *ctx, const void *inputBytes, + size_t inputBytesSize, void *outputSamples, size_t *outputSamplesSize) +{ + g726_codec_ctx *state = (g726_codec_ctx *)ctx->priv; + + if (!state) { + return 0; /* out-of-memory; */ + } + + if (!outputSamples || !outputSamplesSize) { + /* + * sample rate 8kHz, for bitrate 16kHz we have 16/8 = 2 bits/sample, so + * 1 input byte (8 bits) will expand to four 16-bit samples. Likewise, + * for bitrate 40kHz we have 40/8 = 5 bits/sample. Alternatively: + * bitsPerSample = bitRate / sampleRate (8kHz). + * outputBytes = (inputBits / bitsPerSample) * sizeof(sample) + */ + return inputBytesSize * 8 / (state->bit_rate / 8000) * 2; + } + + /* g726_decode returns the number of 16-bit samples. */ + *outputSamplesSize = 2 * g726_decode(state->state, (int16_t *)outputSamples, (const uint8_t *) inputBytes, (int)inputBytesSize); + return *outputSamplesSize; +} + +void +codec_register_g726(void) +{ + register_codec("G726-16", codec_g726_16_init, codec_g726_release, + codec_g726_get_channels, codec_g726_get_frequency, codec_g726_decode); + register_codec("G726-24", codec_g726_24_init, codec_g726_release, + codec_g726_get_channels, codec_g726_get_frequency, codec_g726_decode); + register_codec("G726-32", codec_g726_32_init, codec_g726_release, + codec_g726_get_channels, codec_g726_get_frequency, codec_g726_decode); + register_codec("G726-40", codec_g726_40_init, codec_g726_release, + codec_g726_get_channels, codec_g726_get_frequency, codec_g726_decode); + register_codec("AAL2-G726-16", codec_aal2_g726_16_init, codec_g726_release, + codec_g726_get_channels, codec_g726_get_frequency, codec_g726_decode); + register_codec("AAL2-G726-24", codec_aal2_g726_24_init, codec_g726_release, + codec_g726_get_channels, codec_g726_get_frequency, codec_g726_decode); + register_codec("AAL2-G726-32", codec_aal2_g726_32_init, codec_g726_release, + codec_g726_get_channels, codec_g726_get_frequency, codec_g726_decode); + register_codec("AAL2-G726-40", codec_aal2_g726_40_init, codec_g726_release, + codec_g726_get_channels, codec_g726_get_frequency, codec_g726_decode); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/codecs/G729/CMakeLists.txt b/plugins/codecs/G729/CMakeLists.txt new file mode 100644 index 00000000..6c533002 --- /dev/null +++ b/plugins/codecs/G729/CMakeLists.txt @@ -0,0 +1,66 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(g729 0 1 0 0) + +set(CODEC_SRC + G729decode.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(g729 codecs) + +target_include_directories(g729 PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(g729 wsutil ${BCG729_LIBRARIES}) + +target_include_directories(g729 SYSTEM PRIVATE ${BCG729_INCLUDE_DIRS}) + +install_plugin(g729 codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + g729 + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/G729/G729decode.c b/plugins/codecs/G729/G729decode.c new file mode 100644 index 00000000..7bb564e6 --- /dev/null +++ b/plugins/codecs/G729/G729decode.c @@ -0,0 +1,109 @@ +/* G729decode.c + * G.729 codec + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include "bcg729/decoder.h" +#include "wsutil/codecs.h" +#include "ws_attributes.h" + +void codec_register_g729(void); + +static void * +codec_g729_init(codec_context_t *ctx _U_) +{ + return initBcg729DecoderChannel(); +} + +static void +codec_g729_release(codec_context_t *ctx) +{ + closeBcg729DecoderChannel((bcg729DecoderChannelContextStruct *)ctx->priv); +} + +static unsigned +codec_g729_get_channels(codec_context_t *ctx _U_) +{ + return 1; +} + +static unsigned +codec_g729_get_frequency(codec_context_t *ctx _U_) +{ + return 8000; +} + +static size_t +codec_g729_decode(codec_context_t *ctx, + const void *inputBytes, size_t inputBytesSize, + void *outputSamples, size_t *outputSamplesSize) +{ + bcg729DecoderChannelContextStruct *state = (bcg729DecoderChannelContextStruct *)ctx->priv; + const guint8 *dataIn = (const guint8 *) inputBytes; + gint16 *dataOut = (gint16 *) outputSamples; + size_t i; + + if (!ctx) { + return 0; + } + + size_t full_frames = inputBytesSize / 10; + /* Almost surely only one SID frame. SID frames come at the end of + the payload, and 10 ms packets can be used when transitioning to + avoid ambiguity. (RFC 3551 4.5.6 "G729") + */ + size_t sid_frames = (inputBytesSize % 10) / 2; + + if (!outputSamples || !outputSamplesSize) { + return 80*2*(full_frames + sid_frames); + } + + /* The G729 algorithm encodes 10ms of voice into 80bit (10 bytes). + Based on the RTP packetization period (usually 20ms), we need to + pass to the bcg729 decoder chunks of 10ms (10 bytes) + */ + for (i = 0; i < full_frames; i++) { + /* As of version 1.1.0, the bcg729 decoder library declares the second + argument to bcg729Decoder() to be a const pointer, but prior to + that it did not (though it didn't modify the input and could be + fixed to accept a const pointer.) Cast away the problem for now; + in the future we could check the version of the library. + */ + bcg729Decoder(state, (guint8 *)dataIn + i*10, 10, 0, 0, 0, dataOut + i*80); + } + + for (; i < full_frames + sid_frames; i++) { + bcg729Decoder(state, (guint8 *)dataIn + full_frames*10 + (i - full_frames)*2, 2, 0, 1, 0, dataOut + i*80); + } + *outputSamplesSize = 80*2*(full_frames + sid_frames); + return *outputSamplesSize; +} + +void +codec_register_g729(void) +{ + register_codec("g729", codec_g729_init, codec_g729_release, + codec_g729_get_channels, codec_g729_get_frequency, codec_g729_decode); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/codecs/amrnb/CMakeLists.txt b/plugins/codecs/amrnb/CMakeLists.txt new file mode 100644 index 00000000..b4931468 --- /dev/null +++ b/plugins/codecs/amrnb/CMakeLists.txt @@ -0,0 +1,66 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(amrnb 0 1 0 0) + +set(CODEC_SRC + amrdecode.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(amrnb codecs) + +target_include_directories(amrnb PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(amrnb wsutil ${AMRNB_LIBRARIES}) + +target_include_directories(amrnb SYSTEM PRIVATE ${AMRNB_INCLUDE_DIRS}) + +install_plugin(amrnb codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + amrnb + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/amrnb/amrdecode.c b/plugins/codecs/amrnb/amrdecode.c new file mode 100644 index 00000000..1cceca3c --- /dev/null +++ b/plugins/codecs/amrnb/amrdecode.c @@ -0,0 +1,274 @@ +/* amrdecode.c + * AMR codec + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include "wsutil/codecs.h" +#include "ws_attributes.h" + +#include + +void codec_register_amr(void); + +static void * +codec_amr_init(codec_context_t *ctx _U_) +{ + void *state; + state = Decoder_Interface_init(); + + return state; +} + +static void +codec_amr_release(codec_context_t *state) +{ + Decoder_Interface_exit(state->priv); +} + +static unsigned +codec_amr_get_channels(codec_context_t *ctx _U_) +{ + return 1; +} + +static unsigned +codec_amr_get_frequency(codec_context_t *ctx _U_) +{ + return 8000; +} + +/* RTP doesn't allow the other SID types */ +static const uint8_t speech_bits[16] = {95,103,118,134,148,159,204,244,39, 0, 0, 0, 0, 0, 0, 0}; +/* The number of speech bits rounded up to bytes */ +static const uint8_t block_size[16] = {12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0}; + +static const uint8_t bit_mask8[] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF }; + +/* Retrieve no_of_bits (<= 8) from in, starting at bit_offset. + * Does not do bounds checking. + */ +static uint8_t +get_bits8(uint8_t *in, unsigned bit_offset, const unsigned no_of_bits) +{ + uint8_t ret; + unsigned octet_offset = bit_offset >> 3; + unsigned bits_in_first_octet = 8 - (bit_offset % 8); + if (bits_in_first_octet >= no_of_bits) { + ret = in[octet_offset] >> (bits_in_first_octet - no_of_bits) & bit_mask8[no_of_bits]; + } else { + unsigned left_shift = no_of_bits - bits_in_first_octet; + ret = (in[octet_offset] << left_shift) & bit_mask8[no_of_bits]; + ret |= (in[octet_offset + 1] >> (8 - left_shift)); + } + return ret; +} + +static size_t +codec_amr_decode_one(void *state, const void *input, size_t inputSizeBytes, + void *output, size_t *outputSizeBytes) +{ + uint8_t *in; + int mode; + unsigned packet_size; + packet_size = 2; /* CMR + TOC */ + + /* 160 samples per frame, two byte per frame, 20ms */ + *outputSizeBytes = 160 * 2; + + /* If no room for CMR + TOC, insert silence */ + if (packet_size > inputSizeBytes) { + memset(output, 0, 160 * 2); + return *outputSizeBytes; + } + + in = (uint8_t*)input + 1; + mode = (in[0] >> 3) & 0x0F; + packet_size += block_size[mode]; + + /* If the size is screwed up, insert silence */ + if (packet_size > inputSizeBytes) { + memset(output, 0, 160 * 2); + return *outputSizeBytes; + } + + /* XXX: The last parameter is the BFI - we could invert the + * Q-bit and pass it in, which might be better? + */ + Decoder_Interface_Decode(state, in, (short *)output, 0); + return *outputSizeBytes; +} + +static size_t +codec_amr_decode_many(void *state, const void *input, size_t inputSizeBytes, + void *output, size_t *outputSizeBytes, unsigned frames) +{ + int mode; + unsigned packet_size = 1; /* CMR */ + + *outputSizeBytes = 160 * 2 * frames; + + uint8_t *toc = (uint8_t *)input + 1; + uint8_t *speech = toc + frames; + uint8_t in[32]; + + for (unsigned i = 0; i < frames; i++) { + mode = (toc[i] >> 3) & 0x0F; + packet_size += block_size[mode] + 1; /* include the TOC */ + + /* If the size is screwed up, insert silence */ + if (packet_size > inputSizeBytes) { + memset(output, 0, 160 * 2 * (frames - i)); + return *outputSizeBytes; + } + + /* OpenCORE-AMR ignores the F-bit (which is why we're doing + * this memcpy) but might as well clear it. + */ + in[0] = toc[i] & 0x7F; + memcpy(&in[1], speech, block_size[mode]); + /* XXX: The last parameter is the BFI - we could invert the + * Q-bit and pass it in, which might be better? + */ + Decoder_Interface_Decode(state, in, (short *)output, 0); + speech += block_size[mode]; + output = (uint8_t *)output + 160 * 2; + } + + return *outputSizeBytes; +} + +static size_t +codec_amr_decode_oa(codec_context_t *ctx, const void *input, + size_t inputSizeBytes, void *output, size_t *outputSizeBytes) +{ + bool f_bit; + unsigned frames = 0; + void *state = ctx->priv; + + /* First byte is CMR, second is the Payload TOC */ + if (inputSizeBytes < 2) { + frames = 1; + } else { + uint8_t *in = (uint8_t *)input; + do { + f_bit = (in[++frames] >> 7) & 0x01; + } while (f_bit && inputSizeBytes > frames + 1); + } + + /* 160 samples per frame, two byte per frame, 20ms */ + if (!output || !outputSizeBytes) + return 160 * 2 * frames; + + if (frames == 1) { + return codec_amr_decode_one(state, input, inputSizeBytes, output, outputSizeBytes); + } else { + return codec_amr_decode_many(state, input, inputSizeBytes, output, outputSizeBytes, frames); + } +} + +static size_t +codec_amr_decode(codec_context_t *ctx, const void *input, + size_t inputSizeBytes, void *output, size_t *outputSizeBytes) +{ + bool f_bit; + unsigned frames = 0; + void *state = ctx->priv; + + if (ctx->fmtp_map) { + const char* octet_align = (const char *)wmem_map_lookup(ctx->fmtp_map, "octet-align"); + /* There's a few other lesser used options like "crc", "interleaving", + * and "robust-sorting" that can change how it should be decoded. + * (All of them imply octet-aligned.) Ideally we'd handle them too. + */ + if (g_strcmp0(octet_align, "1") == 0) { + return codec_amr_decode_oa(ctx, input, inputSizeBytes, output, outputSizeBytes); + } + } + + unsigned bit_offset = 4; + uint8_t *in = (uint8_t *)input; + /* Per RFC 4867, if the format parameters don't indicate octet-align, + * bandwidth-efficient mode is used. (For Decode As, we'll pass in + * the value of the dissector's prefs.) + * OpenCORE-AMR's interface only supports octet-aligned mode, so we + * have to align the data. (From the source, the decode also supports + * IF2, except that there's no way to access that from the interface.) + */ + /* First byte is CMR, second is the Payload TOC */ + if (inputSizeBytes < 2) { + frames = 1; + } else { + do { + f_bit = get_bits8(in, bit_offset, 1); + bit_offset += 6; + frames++; + } while (f_bit && inputSizeBytes > (bit_offset / 8)); + } + + /* 160 samples per frame, two byte per frame, 20ms */ + if (!output || !outputSizeBytes) + return 160 * 2 * frames; + + *outputSizeBytes = 160 * 2 * frames; + /* bit_offset is now where the speech bits begin */ + unsigned toc_offset = 5; /* Mode start */ + uint8_t aligned[32]; + int mode; + for (unsigned i = 0; i < frames; ++i) { + mode = get_bits8(in, toc_offset, 4); + + /* If the size is screwed up, insert silence */ + if ((bit_offset + speech_bits[mode] + 7) / 8 > inputSizeBytes) { + memset(output, 0, 160 * 2 * (frames - i)); + return *outputSizeBytes; + } + + memset(aligned, 0, 32); + aligned[0] = mode << 3; + for (unsigned j = 0; j < speech_bits[mode] / 8; ++j) { + aligned[1 + j] = get_bits8(in, bit_offset, 8); + bit_offset += 8; + } + if (speech_bits[mode] % 8) { + aligned[1 + block_size[mode]] = get_bits8(in, bit_offset, speech_bits[mode] % 8); + } + /* Padding might be different. */ + + /* XXX: The last parameter is the BFI - we could invert the + * Q-bit and pass it in, which might be better? + */ + Decoder_Interface_Decode(state, aligned, (short *)output, 0); + output = (uint8_t *)output + 160 * 2; + } + + return *outputSizeBytes; +} + +void +codec_register_amr(void) +{ + register_codec("AMR", codec_amr_init, codec_amr_release, + codec_amr_get_channels, codec_amr_get_frequency, codec_amr_decode); +} + +/* + * Editor modelines - http://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/codecs/iLBC/CMakeLists.txt b/plugins/codecs/iLBC/CMakeLists.txt new file mode 100644 index 00000000..89292043 --- /dev/null +++ b/plugins/codecs/iLBC/CMakeLists.txt @@ -0,0 +1,66 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(ilbc 0 1 0 0) + +set(CODEC_SRC + iLBCdecode.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(ilbc codecs) + +target_include_directories(ilbc PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(ilbc wsutil ${ILBC_LIBRARIES}) + +target_include_directories(ilbc SYSTEM PRIVATE ${ILBC_INCLUDE_DIRS}) + +install_plugin(ilbc codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + ilbc + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/iLBC/iLBCdecode.c b/plugins/codecs/iLBC/iLBCdecode.c new file mode 100644 index 00000000..d127f160 --- /dev/null +++ b/plugins/codecs/iLBC/iLBCdecode.c @@ -0,0 +1,141 @@ +/* iLBCdecode.c + * iLBC codec + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include + +#include "ilbc.h" +#include "wsutil/codecs.h" +#include "ws_attributes.h" + +#define ILBC_20MS 20 +#define ILBC_30MS 30 +#define ILBC_PAYLOAD_LEN_20MS 38 +#define ILBC_PAYLOAD_LEN_30MS 50 +#define SAMPLE_SIZE 2 + +typedef struct { +#ifdef LIBILBC_VERSION_MAJOR + IlbcDecoderInstance *ilbc_ctx; /* Real iLBC context */ +#else + iLBC_decinst_t *ilbc_ctx; /* Real iLBC context */ +#endif + guint8 payload_len; /* Remember last payload_len */ +} ilbc_ctx_t; + +void codec_register_iLBC(void); + +static void * +codec_iLBC_init(codec_context_t *ctx _U_) +{ + ilbc_ctx_t *priv; + + priv=(ilbc_ctx_t *)g_malloc0(sizeof(*priv)); + WebRtcIlbcfix_DecoderCreate(&(priv->ilbc_ctx)); + + return priv; +} + +static void +codec_iLBC_release(codec_context_t *ctx) +{ + WebRtcIlbcfix_DecoderFree(((ilbc_ctx_t *)ctx->priv)->ilbc_ctx); + g_free(ctx); +} + +static unsigned +codec_iLBC_get_channels(codec_context_t *ctx _U_) +{ + return 1; +} + +static unsigned +codec_iLBC_get_frequency(codec_context_t *ctx _U_) +{ + return 8000; +} + +static size_t +codec_iLBC_decode(codec_context_t *ctx, + const void *inputBytes, size_t inputBytesSize, + void *outputSamples, size_t *outputSamplesSize) +{ + int16_t speechType; // Not used in Wireshark code +#ifdef LIBILBC_VERSION_MAJOR + int8_t *dataIn = (int8_t *)inputBytes; +#else + int16_t *dataIn = (int16_t *)inputBytes; +#endif + int16_t *dataOut = (int16_t *)outputSamples; + ilbc_ctx_t *dataCtx = (ilbc_ctx_t *)ctx->priv; + size_t outputSamplesCount; + + if (!outputSamples || !outputSamplesSize) + { + if (0 == inputBytesSize%ILBC_PAYLOAD_LEN_20MS) { + /* 20ms packet size = 160 samples = 320 bytes */ + return BLOCKL_20MS*SAMPLE_SIZE; + } else if (0 == inputBytesSize%ILBC_PAYLOAD_LEN_30MS) { + /* 30ms packet size = 240 samples = 480 bytes */ + return BLOCKL_30MS*SAMPLE_SIZE; + } else { + /* unknown packet size */ + return 0; + } + } + + if (0 == inputBytesSize%ILBC_PAYLOAD_LEN_20MS) { + /* 20ms packet size */ + if (dataCtx->payload_len != ILBC_20MS) { + WebRtcIlbcfix_DecoderInit(dataCtx->ilbc_ctx, ILBC_20MS); + dataCtx->payload_len = ILBC_20MS; + } + outputSamplesCount = WebRtcIlbcfix_Decode(dataCtx->ilbc_ctx, dataIn, + (int16_t)inputBytesSize, dataOut, &speechType); + } else if (0 == inputBytesSize%ILBC_PAYLOAD_LEN_30MS) { + /* 30ms packet size */ + if (dataCtx->payload_len != ILBC_30MS) { + WebRtcIlbcfix_DecoderInit(dataCtx->ilbc_ctx, ILBC_30MS); + dataCtx->payload_len = ILBC_30MS; + } + outputSamplesCount = WebRtcIlbcfix_Decode(dataCtx->ilbc_ctx, dataIn, + (int16_t)inputBytesSize, dataOut, &speechType); + } else { + /* unknown packet size */ + outputSamplesCount = 0; + } + + /* WebRtcIlbcfix_Decode returns count of samples, but we return count of bytes */ + *outputSamplesSize = outputSamplesCount*SAMPLE_SIZE; + return *outputSamplesSize; +} + +void +codec_register_iLBC(void) +{ + register_codec("iLBC", codec_iLBC_init, codec_iLBC_release, + codec_iLBC_get_channels, codec_iLBC_get_frequency, codec_iLBC_decode); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/codecs/l16_mono/AUTHORS b/plugins/codecs/l16_mono/AUTHORS new file mode 100644 index 00000000..f00e0146 --- /dev/null +++ b/plugins/codecs/l16_mono/AUTHORS @@ -0,0 +1,2 @@ +Author : +Jaap Keuter diff --git a/plugins/codecs/l16_mono/CMakeLists.txt b/plugins/codecs/l16_mono/CMakeLists.txt new file mode 100644 index 00000000..f90713b7 --- /dev/null +++ b/plugins/codecs/l16_mono/CMakeLists.txt @@ -0,0 +1,64 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(l16mono 0 1 0 0) + +set(CODEC_SRC + l16decode.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(l16mono codecs) + +target_include_directories(l16mono PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(l16mono wsutil) + +install_plugin(l16mono codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + l16mono + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/l16_mono/README b/plugins/codecs/l16_mono/README new file mode 100644 index 00000000..993730a4 --- /dev/null +++ b/plugins/codecs/l16_mono/README @@ -0,0 +1,3 @@ +This codec plugin serves a dual purpose. +First it is to add L16 codec suppport to Wireshark. +Second it is an illustration of a basic codec plugin module. diff --git a/plugins/codecs/l16_mono/l16decode.c b/plugins/codecs/l16_mono/l16decode.c new file mode 100644 index 00000000..12994cfc --- /dev/null +++ b/plugins/codecs/l16_mono/l16decode.c @@ -0,0 +1,122 @@ +/* l16decode.c + * 16-bit audio, mono codec + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include + +#include "wsutil/codecs.h" +#include "ws_attributes.h" + +void codec_register_l16(void); + +static void * +codec_l16_init(codec_context_t *ctx _U_) +{ + return NULL; +} + +static void * +codec_l16_mono_init(codec_context_t *ctx) +{ + /* L16 mono as registered as PT 11 */ + ctx->sample_rate = 44100; + ctx->channels = 1; + return NULL; +} + +static void * +codec_l16_stereo_init(codec_context_t *ctx) +{ + /* L16 stereo as registered as PT 10 */ + ctx->sample_rate = 44100; + /* In practice, we will downmix to mono. */ + ctx->channels = 2; + return NULL; +} + +static void +codec_l16_release(codec_context_t *ctx _U_) +{ + +} + +static unsigned +codec_l16_get_channels(codec_context_t *ctx _U_) +{ + /* XXX: Downmix to mono regardless of the actual number of channels + * because RTP Player expects mono, and doesn't actually do anything + * with this. + */ + return 1; +} + +static unsigned +codec_l16_get_frequency(codec_context_t *ctx) +{ + return ctx->sample_rate ? ctx->sample_rate : 44100; +} + +static size_t +codec_l16_decode(codec_context_t *ctx _U_, + const void *inputBytes, size_t inputBytesSize, + void *outputSamples, size_t *outputSamplesSize) +{ + const guint16 *dataIn = (const guint16 *)inputBytes; + guint16 *dataOut = (gint16 *)outputSamples; + size_t i; + unsigned channels = ctx->channels ? ctx->channels : 1; + if (!outputSamples || !outputSamplesSize) + { + return inputBytesSize/channels; + } + + /* Downmix to mono. No worries about overflow because tmp is 32 bit. */ + for (i=0; i +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(opus_dec 0 1 0 0) + +set(CODEC_SRC + opusdecode.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(opus_dec codecs) + +target_include_directories(opus_dec PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(opus_dec wsutil ${OPUS_LIBRARIES}) + +target_include_directories(opus_dec SYSTEM PRIVATE ${OPUS_INCLUDE_DIRS}) + +install_plugin(opus_dec codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + opus + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/opus_dec/opusdecode.c b/plugins/codecs/opus_dec/opusdecode.c new file mode 100644 index 00000000..97398bb5 --- /dev/null +++ b/plugins/codecs/opus_dec/opusdecode.c @@ -0,0 +1,107 @@ +/* opusdecode.c + * opus codec + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" +#include +#include "opus/opus.h" + +#include "wsutil/codecs.h" +#include "ws_attributes.h" + +void codec_register_opus(void); + +static void * +codec_opus_init(codec_context_t *ctx _U_) +{ + OpusDecoder *state; + int err = OPUS_INTERNAL_ERROR; + /* Opus has in-band signaling and can convert what is sent to our + * desired output. + * always use maximum 48000 to cover all 8k/12k/16k/24k/48k + * always downmix to mono because RTP Player only supports mono now + */ + state = opus_decoder_create(48000, 1, &err); + return state; +} + +static void +codec_opus_release(codec_context_t *ctx) +{ + OpusDecoder* state = (OpusDecoder*)ctx->priv; + if (!state) { + return; /* out-of-memory; */ + } + opus_decoder_destroy(state); +} + +static unsigned +codec_opus_get_channels(codec_context_t *ctx _U_) +{ + return 1; +} + +static unsigned +codec_opus_get_frequency(codec_context_t *ctx _U_) +{ + /* although can set kinds of fs, but we set 48K now */ + return 48000; +} + +static size_t +codec_opus_decode(codec_context_t *ctx, + const void *input, size_t inputSizeBytes, + void *output, size_t *outputSizeBytes) +{ + OpusDecoder *state = (OpusDecoder *)ctx->priv; + + if (!state) { + return 0; /* out-of-memory */ + } + + const unsigned char *data = (const unsigned char *)input; + opus_int32 len = (opus_int32)inputSizeBytes; + int frame_samples = opus_decoder_get_nb_samples(state, data, len); + if (frame_samples < 0) { // OPUS_INVALID_PACKET + return 0; + } + + // reserve space for the first time + if (!output || !outputSizeBytes) { + return frame_samples*2; + } + opus_int16 *pcm = (opus_int16*)(output); + int ret = opus_decode(state, data, len, pcm, frame_samples, 0); + + if (ret < 0) { + return 0; + } + *outputSizeBytes = ret * 2; + return *outputSizeBytes; +} + +void +codec_register_opus(void) +{ + register_codec("opus", codec_opus_init, codec_opus_release, + codec_opus_get_channels, codec_opus_get_frequency, codec_opus_decode); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/codecs/sbc/CMakeLists.txt b/plugins/codecs/sbc/CMakeLists.txt new file mode 100644 index 00000000..d12de70d --- /dev/null +++ b/plugins/codecs/sbc/CMakeLists.txt @@ -0,0 +1,66 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(sbc 0 1 0 0) + +set(CODEC_SRC + sbc.c +) + +set(PLUGIN_FILES + plugin.c + ${CODEC_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_codec + ${CODEC_SRC} +) + +add_wireshark_plugin_library(sbc codecs) + +target_include_directories(sbc PRIVATE ${CMAKE_SOURCE_DIR}/codecs) + +target_link_libraries(sbc wsutil ${SBC_LIBRARIES}) + +target_include_directories(sbc SYSTEM PRIVATE ${SBC_INCLUDE_DIRS}) + +install_plugin(sbc codecs) + +file(GLOB CODEC_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + sbc + SWITCHES + SOURCES + ${CODEC_SRC} + ${CODEC_HEADERS} +) + +# +# 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: +# diff --git a/plugins/codecs/sbc/sbc.c b/plugins/codecs/sbc/sbc.c new file mode 100644 index 00000000..5ac31b94 --- /dev/null +++ b/plugins/codecs/sbc/sbc.c @@ -0,0 +1,142 @@ +/* sbc.c + * Support for external Bluetooth SBC codec + * + * Copyright 2012, Michal Labedzki for Tieto Corporation + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include + +#include "wsutil/codecs.h" + +#define SBC_BUFFER 8192 + +void codec_register_sbc(void); + +static void * +codec_sbc_init(codec_context_t *ctx _U_) +{ + sbc_t *sbc; + + sbc = g_new(sbc_t, 1); + sbc_init(sbc, 0L); + + return sbc; +} + +static void +codec_sbc_release(codec_context_t *ctx) +{ + sbc_t *sbc = (sbc_t *) ctx->priv; + + sbc_finish(sbc); + g_free(sbc); +} + +static unsigned +codec_sbc_get_channels(codec_context_t *ctx) +{ + sbc_t *sbc = (sbc_t *) ctx->priv; + if (sbc->mode == SBC_MODE_MONO) + return 1; + + return 2; +} + +static unsigned +codec_sbc_get_frequency(codec_context_t *ctx) +{ + sbc_t *sbc = (sbc_t *) ctx->priv; + int frequency; + + switch (sbc->frequency) { + case SBC_FREQ_16000: + frequency = 16000; + break; + + case SBC_FREQ_32000: + frequency = 32000; + break; + + case SBC_FREQ_44100: + frequency = 44100; + break; + + case SBC_FREQ_48000: + frequency = 48000; + break; + default: + frequency = 0; + } + + return frequency; +} + +static size_t +codec_sbc_decode(codec_context_t *ctx, + const void *input, size_t inputSizeBytes, + void *output, size_t *outputSizeBytes) +{ + size_t size_in = (size_t) inputSizeBytes; + size_t size_out = SBC_BUFFER; + size_t len; + size_t framelen; + size_t xframe_pos = 0; + const guint8 *data_in = (const guint8 *) input; + guint8 *data_out = (guint8 *) output; + sbc_t *sbc = (sbc_t *) ctx->priv; + guint8 *i_data; + guint8 tmp; + + if (!output || !outputSizeBytes) { + return size_out; + } + + sbc->endian = SBC_BE; + + *outputSizeBytes = 0; + while (xframe_pos < inputSizeBytes) { + framelen = sbc_decode(sbc, data_in, size_in, data_out, size_out, &len); + xframe_pos += framelen; + data_in += framelen; + *outputSizeBytes += len; + + for (i_data = data_out; i_data < data_out + len; i_data += 2) { + tmp = i_data[0]; + i_data[0] = i_data[1]; + i_data[1] = tmp; + } + + data_out += len; + } + + return *outputSizeBytes; +} + +void +codec_register_sbc(void) +{ + register_codec("SBC", codec_sbc_init, codec_sbc_release, + codec_sbc_get_channels, codec_sbc_get_frequency, codec_sbc_decode); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/AUTHORS b/plugins/epan/ethercat/AUTHORS new file mode 100644 index 00000000..8e9f8dae --- /dev/null +++ b/plugins/epan/ethercat/AUTHORS @@ -0,0 +1,5 @@ +Author : +Richard Kuemmel + +Updates and bugfixes: +Peter Johansson diff --git a/plugins/epan/ethercat/CMakeLists.txt b/plugins/epan/ethercat/CMakeLists.txt new file mode 100644 index 00000000..afa46e82 --- /dev/null +++ b/plugins/epan/ethercat/CMakeLists.txt @@ -0,0 +1,70 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(ethercat 0 1 0 0) + +set(DISSECTOR_SRC + packet-ams.c + packet-ecatmb.c + packet-esl.c + packet-ethercat-datagram.c + packet-ethercat-frame.c + packet-ioraw.c + packet-nv.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_wireshark_plugin_library(ethercat epan) + +target_link_libraries(ethercat epan) + +install_plugin(ethercat epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + ethercat + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/ethercat/packet-ams.c b/plugins/epan/ethercat/packet-ams.c new file mode 100644 index 00000000..b6246eb5 --- /dev/null +++ b/plugins/epan/ethercat/packet-ams.c @@ -0,0 +1,1245 @@ +/* packet-ams.c + * Routines for ethercat packet disassembly + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include + +#include "packet-ams.h" + +void proto_register_ams(void); +void proto_reg_handoff_ams(void); + +#define AMS_TCP_PORT 48898 /* Not IANA registered */ + +/* Define the ams proto */ +int proto_ams = -1; + +static dissector_handle_t amstcp_handle; + +/* Define the tree for ams */ +static int ett_ams = -1; +static int ett_ams_stateflags = -1; +static int ett_ams_adsreadrequest = -1; +static int ett_ams_adsreadresponse = -1; +static int ett_ams_adswriterequest = -1; +static int ett_ams_adswriteresponse = -1; +static int ett_ams_adsreadwriterequest = -1; +static int ett_ams_adsreadwriteresponse = -1; +static int ett_ams_adsreadstaterequest = -1; +static int ett_ams_adsreadstateresponse = -1; +static int ett_ams_adswritectrlrequest = -1; +static int ett_ams_adswritectrlresponse = -1; +static int ett_ams_adsreaddinforequest = -1; +static int ett_ams_adsreaddinforesponse = -1; +static int ett_ams_adsadddnrequest = -1; +static int ett_ams_adsadddnresponse = -1; +static int ett_ams_adsdeldnrequest = -1; +static int ett_ams_adsdeldnresponse = -1; +static int ett_ams_adsdnrequest = -1; + +static int hf_ams_sendernetid = -1; +static int hf_ams_senderport = -1; +static int hf_ams_targetnetid = -1; +static int hf_ams_targetport = -1; +static int hf_ams_cmdid = -1; +static int hf_ams_stateflags = -1; +static int hf_ams_stateresponse = -1; +static int hf_ams_statenoreturn = -1; +static int hf_ams_stateadscmd = -1; +static int hf_ams_statesyscmd = -1; +static int hf_ams_statehighprio = -1; +static int hf_ams_statetimestampadded = -1; +static int hf_ams_stateudp = -1; +static int hf_ams_stateinitcmd = -1; +static int hf_ams_statebroadcast = -1; +static int hf_ams_cbdata = -1; +static int hf_ams_errorcode = -1; +static int hf_ams_invokeid = -1; +static int hf_ams_data = -1; + +/*ads Commands */ +static int hf_ams_adsindexgroup = -1; +static int hf_ams_adsindexoffset = -1; +static int hf_ams_adscblength = -1; +static int hf_ams_adsreadrequest = -1; +static int hf_ams_adsreadresponse = -1; +static int hf_ams_adsinvokeid = -1; +static int hf_ams_adsresult = -1; +static int hf_ams_adsdata = -1; +static int hf_ams_adswriterequest = -1; +static int hf_ams_adswriteresponse = -1; +static int hf_ams_adsreadwriterequest = -1; +static int hf_ams_adsreadwriteresponse = -1; +static int hf_ams_adscbreadlength = -1; +static int hf_ams_adscbwritelength = -1; +static int hf_ams_adsstate = -1; +static int hf_ams_adsdevicestate = -1; +static int hf_ams_adsnotificationhandle = -1; +static int hf_ams_adsreadstaterequest = -1; +static int hf_ams_adsreadstateresponse = -1; +static int hf_ams_adswritectrlrequest = -1; +static int hf_ams_adswritectrlresponse = -1; +static int hf_ams_adsreaddinforequest = -1; +static int hf_ams_adsreaddinforesponse = -1; +static int hf_ams_adsadddnrequest = -1; +static int hf_ams_adsadddnresponse = -1; +static int hf_ams_adsdeldnrequest = -1; +static int hf_ams_adsdeldnresponse = -1; +static int hf_ams_adsdnrequest = -1; +/* static int hf_ams_adsdnresponse = -1; */ +/* static int hf_ams_adsnoteattrib = -1; */ +/* static int hf_ams_adsnoteblocks = -1; */ +/* static int hf_ams_adsversion = -1; */ +static int hf_ams_adsdevicename = -1; +static int hf_ams_adsversionversion = -1; +static int hf_ams_adsversionrevision = -1; +static int hf_ams_adsversionbuild = -1; +static int hf_ams_adsnoteblocksstamps = -1; +/* static int hf_ams_adsnoteblocksstamp = -1; */ +/* static int hf_ams_adstimestamp = -1; */ +/* static int hf_ams_adssamplecnt = -1; */ +/* static int hf_ams_adsnoteblockssample = -1; */ +static int hf_ams_adstransmode = -1; +static int hf_ams_adsmaxdelay = -1; +static int hf_ams_adscycletime = -1; +/* static int hf_ams_adscmpmax = -1; */ +/* static int hf_ams_adscmpmin = -1; */ + +static dissector_handle_t ams_handle; + +static const value_string TransMode[] = +{ + { 0, "NO TRANS"}, + { 1, "CLIENT CYCLE"}, + { 2, "CLIENT ON CHANGE"}, + { 3, "SERVER CYCLE"}, + { 4, "SERVER ON CHANGE"}, + { 10, "CLIENT FIRST REQUEST"}, + { 0, NULL } +}; + +static const value_string ErrorCode[] = +{ + { ERR_NOERROR, "NO ERROR"}, + { ERR_INTERNAL, "INTERNAL"}, + { ERR_NORTIME, "NO RTIME"}, + { ERR_ALLOCLOCKEDMEM, "ALLOC LOCKED MEM"}, + { ERR_INSERTMAILBOX, "INSERT MAILBOX"}, + { ERR_WRONGRECEIVEHMSG, "WRONGRECEIVEHMSG"}, + { ERR_TARGETPORTNOTFOUND, "TARGET PORT NOT FOUND"}, + { ERR_TARGETMACHINENOTFOUND, "TARGET MACHINE NOT FOUND"}, + { ERR_UNKNOWNCMDID, "UNKNOWN CMDID"}, + { ERR_BADTASKID, "BAD TASKID"}, + { ERR_NOIO, "NOIO"}, + { ERR_UNKNOWNAMSCMD, "UNKNOWN AMSCMD"}, + { ERR_WIN32ERROR, "WIN32 ERROR"}, + { ERR_PORTNOTCONNECTED, "PORT NOT CONNECTED"}, + { ERR_INVALIDAMSLENGTH, "INVALID AMS LENGTH"}, + { ERR_INVALIDAMSNETID, "INVALID AMS NETID"}, + { ERR_LOWINSTLEVEL, "LOW INST LEVEL"}, + { ERR_NODEBUGINTAVAILABLE, "NO DEBUG INT AVAILABLE"}, + { ERR_PORTDISABLED, "PORT DISABLED"}, + { ERR_PORTALREADYCONNECTED, "PORT ALREADY CONNECTED"}, + { ERR_AMSSYNC_W32ERROR, "AMSSYNC_W32ERROR"}, + { ERR_AMSSYNC_TIMEOUT, "AMSSYNC_TIMEOUT"}, + { ERR_AMSSYNC_AMSERROR, "AMSSYNC_AMSERROR"}, + { ERR_AMSSYNC_NOINDEXINMAP, "AMSSYNC_NOINDEXINMAP"}, + { ERR_INVALIDAMSPORT, "INVALID AMSPORT"}, + { ERR_NOMEMORY, "NO MEMORY"}, + { ERR_TCPSEND, "TCP SEND"}, + { ERR_HOSTUNREACHABLE, "HOST UNREACHABLE"}, + { ROUTERERR_NOLOCKEDMEMORY, "ROUTERERR_NOLOCKEDMEMORY"}, + { ROUTERERR_RESIZEMEMORY, "ROUTERERR_RESIZEMEMORY"}, + { ROUTERERR_MAILBOXFULL, "ROUTERERR_MAILBOXFULL"}, + { ROUTERERR_DEBUGBOXFULL, "ROUTERERR_DEBUGBOXFULL"}, + { ROUTERERR_UNKNOWNPORTTYPE, "ROUTERERR_UNKNOWNPORTTYPE"}, + { ROUTERERR_NOTINITIALIZED, "ROUTERERR_NOTINITIALIZED"}, + { ROUTERERR_PORTALREADYINUSE, "ROUTERERR_PORTALREADYINUSE"}, + { ROUTERERR_NOTREGISTERED, "ROUTERERR_NOTREGISTERED "}, + { ROUTERERR_NOMOREQUEUES, "ROUTERERR_NOMOREQUEUES"}, + { ROUTERERR_INVALIDPORT, "ROUTERERR_INVALIDPORT"}, + { ROUTERERR_NOTACTIVATED, "ROUTERERR_NOTACTIVATED"}, + { IOERR_INTERNAL, "IOERR_INTERNAL"}, + { IOERR_BADCARDNO, "IOERR_BADCARDNO"}, + { IOERR_INVALIDCARDADDR, "IOERR_INVALIDCARDADDR"}, + { IOERR_CDLLISTFULL, "IOERR_CDLLISTFULL"}, + { IOERR_BADCDLPARAM, "IOERR_BADCDLPARAM"}, + { IOERR_OPENIOFAILED, "IOERR_OPENIOFAILED"}, + { IOERR_RESETIOFAILED, "IOERR_RESETIOFAILED"}, + { IOERR_UNKNOWNDEVICE, "IOERR_UNKNOWNDEVICE"}, + { IOERR_UNKNOWNDEVICEID, "IOERR_UNKNOWNDEVICEID"}, + { IOERR_UNKNOWNIMAGEID, "IOERR_UNKNOWNIMAGEID"}, + { IOERR_GETIOSTATE, "IOERR_GETIOSTATE"}, + { IOERR_BADIMAGEID, "IOERR_BADIMAGEID"}, + { IOERR_NOMORECLIENTSPACE, "IOERR_NOMORECLIENTSPACE"}, + { IOERR_CLIENTINFONOTFOUND, "IOERR_CLIENTINFONOTFOUND"}, + { IOERR_CDLNOTINUSE, "IOERR_CDLNOTINUSE"}, + { IOERR_TIMEOUTWITHDEVICE, "IOERR_TIMEOUTWITHDEVICE"}, + { IOERR_C1220FUNC_1, "IOERR_C1220FUNC_1"}, + { IOERR_C1220FUNC_9, "IOERR_C1220FUNC_9"}, + { IOERR_C1220FUNC_C, "IOERR_C1220FUNC_C"}, + { IOERR_C1220FUNC_10, "IOERR_C1220FUNC_10"}, + { IOERR_C1220FUNC_1_MAXSEND, "IOERR_C1220FUNC_1_MAXSEND"}, + { IOERR_C1220FUNC_1_ADDRSET, "IOERR_C1220FUNC_1_ADDRSET"}, + { IOERR_C1220FUNC_1_BREAK, "IOERR_C1220FUNC_1_BREAK"}, + { IOERR_C1220FUNC_1_BREAK0, "IOERR_C1220FUNC_1_BREAK0"}, + { IOERR_C1220FUNC_1_BREAK1, "IOERR_C1220FUNC_1_BREAK1"}, + { IOERR_C1220FUNC_1_BREAK2, "IOERR_C1220FUNC_1_BREAK2"}, + { IOERR_C1220FUNC_1_BREAK3, "IOERR_C1220FUNC_1_BREAK3"}, + { IOERR_C1220FUNC_1_BREAK4, "IOERR_C1220FUNC_1_BREAK4"}, + { IOERR_C1220FUNC_1_BREAK5, "IOERR_C1220FUNC_1_BREAK5"}, + { IOERR_C1220FUNC_1_BREAK6, "IOERR_C1220FUNC_1_BREAK6"}, + { IOERR_C1220FUNC_1_BREAK7, "IOERR_C1220FUNC_1_BREAK7"}, + { IOERR_C1220FUNC_1_BREAK8, "IOERR_C1220FUNC_1_BREAK8"}, + { IOERR_C1220FUNC_1_BREAK9, "IOERR_C1220FUNC_1_BREAK9"}, + { IOERR_C1220FUNC_1_BREAK10, "IOERR_C1220FUNC_1_BREAK10"}, + { IOERR_C1220FUNC_1_BREAK11, "IOERR_C1220FUNC_1_BREAK11"}, + { IOERR_C1220FUNC_1_BREAK12, "IOERR_C1220FUNC_1_BREAK12"}, + { IOERR_C1220FUNC_1_BREAK13, "IOERR_C1220FUNC_1_BREAK13"}, + { IOERR_C1220FUNC_1_BREAK14, "IOERR_C1220FUNC_1_BREAK14"}, + { IOERR_C1220FUNC_1_BREAK15, "IOERR_C1220FUNC_1_BREAK15"}, + { IOERR_C1220FUNC_1_BREAK16, "IOERR_C1220FUNC_1_BREAK16"}, + { IOERR_SPC3DEVINITDP, "IOERR_SPC3DEVINITDP"}, + { IOERR_SPC3UPDATEOUTPUT, "IOERR_SPC3UPDATEOUTPUT"}, + { IOERR_CIF30READDIAG, "IOERR_CIF30READDIAG"}, + { IOERR_CIF30COMMNOTSTARTED, "IOERR_CIF30COMMNOTSTARTED"}, + { IOERR_CIF30SLAVEPARASIZE, "IOERR_CIF30SLAVEPARASIZE"}, + { IOERR_CIF30NOPARAS, "IOERR_CIF30NOPARAS"}, + { IOERR_CIF30SLAVEERROR, "IOERR_CIF30SLAVEERROR"}, + { IOERR_CIF30WATCHDOGEXPIRED, "IOERR_CIF30WATCHDOGEXPIRED"}, + { IOERR_UNKNOWNDEVICECMD, "IOERR_UNKNOWNDEVICECMD"}, + { IOERR_CIF40MESSAGEHANDLING, "IOERR_CIF40MESSAGEHANDLING"}, + { IOERR_CIF40PARAERROR, "IOERR_CIF40PARAERROR"}, + { IOERR_CIF40WATCHDOGEXPIRED, "IOERR_CIF40WATCHDOGEXPIRED"}, + { IOERR_CIF40FLAGERROR, "IOERR_CIF40FLAGERROR"}, + { IOERR_CIF40COMMNOTSTARTED, "IOERR_CIF40COMMNOTSTARTED"}, + { IOERR_CIF40READDIAG, "IOERR_CIF40READDIAG"}, + { IOERR_CIF40SLAVEERROR, "IOERR_CIF40SLAVEERROR"}, + { IOERR_CIF40GLOBALERROR, "IOERR_CIF40GLOBALERROR"}, + { IOERR_CIF40CONFIGLIST, "IOERR_CIF40CONFIGLIST"}, + { IOERR_CP5412A2SLAVEPARASIZE, "IOERR_CP5412A2SLAVEPARASIZE"}, + { IOERR_CP5412A2NOPARAS, "IOERR_CP5412A2NOPARAS"}, + { IOERR_CP5412A2SLAVEERROR, "IOERR_CP5412A2SLAVEERROR"}, + { IOERR_CP5412A2FATAL, "IOERR_CP5412A2FATAL"}, + { IOERR_CP5412A2MAILBOXUSED, "IOERR_CP5412A2MAILBOXUSED"}, + { IOERR_BEGINCONFIGWHILETICKER, "IOERR_BEGINCONFIGWHILETICKER"}, + { IOERR_UNEXPECTEDBOXCOUNT, "IOERR_UNEXPECTEDBOXCOUNT"}, + { IOERR_C1200CHECKADDR, "IOERR_C1200CHECKADDR"}, + { IOERR_C1200INTENSITYTEST, "IOERR_C1200INTENSITYTEST"}, + { IOERR_NOIMAGE, "IOERR_NOIMAGE"}, + { IOERR_INVALIDIMAGEOFFSSIZE, "IOERR_INVALIDIMAGEOFFSSIZE"}, + { IOERR_FORCESCOUNTEXCEEDEDMAXIMUM, "IOERR_FORCESCOUNTEXCEEDEDMAXIMUM"}, + { IOERR_SERCOSLIFECOUNTERERR, "IOERR_SERCOSLIFECOUNTERERR"}, + { IOERR_C1220NOTFOUND, "IOERR_C1220NOTFOUND"}, + { IOERR_AMSDEVICENOAMSINTF, "IOERR_AMSDEVICENOAMSINTF"}, + { IOERR_AMSDEVICEAMSCMDIDNOTSUPP, "IOERR_AMSDEVICEAMSCMDIDNOTSUPP"}, + { IOERR_AMSDEVICEAMSSERVICERUNNING, "IOERR_AMSDEVICEAMSSERVICERUNNING"}, + { IOERR_PLCINTERFACE_BUSY, "IOERR_PLCINTERFACE_BUSY"}, + { IOERR_PLCINTERFACE_FAULT, "IOERR_PLCINTERFACE_FAULT"}, + { IOERR_PLCINTERFACE_TIMEOUT, "IOERR_PLCINTERFACE_TIMEOUT"}, + { IOERR_PLCINTERFACE_RESETTIMEOUT, "IOERR_PLCINTERFACE_RESETTIMEOUT"}, + { IOERR_PLCINTERFACE_NODATAEXCH, "IOERR_PLCINTERFACE_NODATAEXCH"}, + { IOERR_PLCINTERFACE_RESET, "IOERR_PLCINTERFACE_RESET"}, + { IOERR_CP5412A2INVALIDADDR, "IOERR_CP5412A2INVALIDADDR"}, + { IOERR_CP5412A2INVALIDPORT, "IOERR_CP5412A2INVALIDPORT"}, + { IOERR_AMSDEVICEBADBOXNO, "IOERR_AMSDEVICEBADBOXNO"}, + { IOERR_AMSDEVICEBADTYPE, "IOERR_AMSDEVICEBADTYPE"}, + { IOERR_AMSDEVICEILLEGALADDRESS, "IOERR_AMSDEVICEILLEGALADDRESS"}, + { IOERR_CP5412A2INVALIDBOX, "IOERR_CP5412A2INVALIDBOX"}, + { IOERR_AMSDEVICEFIFOOVERFLOW, "IOERR_AMSDEVICEFIFOOVERFLOW"}, + { IOERR_AMSDEVICEAMSSEQUENCEERROR, "IOERR_AMSDEVICEAMSSEQUENCEERROR"}, + { IOERR_CP5412A2DPV1SYNTAXERROR, "IOERR_CP5412A2DPV1SYNTAXERROR"}, + { IOERR_CP5412A2DEVICENOTRUNNING, "IOERR_CP5412A2DEVICENOTRUNNING"}, + { IOERR_AMSDEVICENOTRUNNING, "IOERR_AMSDEVICENOTRUNNING"}, + { IOERR_AMSDEVICEBOXNOTDEFINED, "IOERR_AMSDEVICEBOXNOTDEFINED"}, + { IOERR_CP5412A2BADSERVICEPARA, "IOERR_CP5412A2BADSERVICEPARA"}, + { IOERR_CP5412A2FIFOOVERFLOW, "IOERR_CP5412A2FIFOOVERFLOW"}, + { IOERR_COMPORTOPENFAILED, "IOERR_COMPORTOPENFAILED"}, + { IOERR_CIF30BADMESSAGERESPONSE, "IOERR_CIF30BADMESSAGERESPONSE"}, + { IOERR_CIF30DELETEDATABASE, "IOERR_CIF30DELETEDATABASE"}, + { IOERR_CIF30STARTSEQFAILED, "IOERR_CIF30STARTSEQFAILED"}, + { IOERR_CIF30DOWNLOADFAILED, "IOERR_CIF30DOWNLOADFAILED"}, + { IOERR_CIF30ENDSEQFAILED, "IOERR_CIF30ENDSEQFAILED"}, + { IOERR_CIF30BUSLOADFAILED, "IOERR_CIF30BUSLOADFAILED"}, + { IOERR_PLCINTERFACE_RESETREQ, "IOERR_PLCINTERFACE_RESETREQ"}, + { IOERR_CP5412A2INVALIDCYCLETICKS, "IOERR_CP5412A2INVALIDCYCLETICKS"}, + { IOERR_CP5412A2DPBUSFAULT, "IOERR_CP5412A2DPBUSFAULT"}, + { IOERR_INVALIDTERMCONFIG, "IOERR_INVALIDTERMCONFIG"}, + { IOERR_SERCANSBREAK, "IOERR_SERCANSBREAK"}, + { IOERR_SERCANSPHASE0, "IOERR_SERCANSPHASE0"}, + { IOERR_SERCANSPHASE1, "IOERR_SERCANSPHASE1"}, + { IOERR_SERCANSPHASE2, "IOERR_SERCANSPHASE2"}, + { IOERR_SERCANSPHASE3, "IOERR_SERCANSPHASE3"}, + { IOERR_SERCANSPHASE4, "IOERR_SERCANSPHASE4"}, + { IOERR_SERCANSNCSERVICECHNFAILED, "IOERR_SERCANSNCSERVICECHNFAILED"}, + { IOERR_RESOURCECONFICT, "IOERR_RESOURCECONFICT"}, + { IOERR_C1220INITSTRINGCOMM, "IOERR_C1220INITSTRINGCOMM"}, + { IOERR_C1220REGSTRINGSLAVE, "IOERR_C1220REGSTRINGSLAVE"}, + { IOERR_C1220STRREGFAULT, "IOERR_C1220STRREGFAULT"}, + { IOERR_IOSTATEBUSY, "IOERR_IOSTATEBUSY"}, + { IOERR_IBSSCITWATCHDOGEXPIRED, "IOERR_IBSSCITWATCHDOGEXPIRED"}, + { IOERR_IBSSCITSYNCMAILBOXERROR, "IOERR_IBSSCITSYNCMAILBOXERROR"}, + { IOERR_IBSSCITCONFIRMDIAGERROR, "IOERR_IBSSCITCONFIRMDIAGERROR"}, + { IOERR_IBSSCITCREATECFGERROR, "IOERR_IBSSCITCREATECFGERROR"}, + { 0, NULL } +}; + +static const value_string AdsErrorMode[] = +{ + { ADSERR_NOERR, "NO ERROR", }, + { ADSERR_DEVICE_ERROR, "ERROR", }, + { ADSERR_DEVICE_SRVNOTSUPP, "SRV NOT SUPP", }, + { ADSERR_DEVICE_INVALIDGRP, "INVALID GRP", }, + { ADSERR_DEVICE_INVALIDOFFSET, "INVALID OFFSET", }, + { ADSERR_DEVICE_INVALIDACCESS, "INVALID ACCESS", }, + { ADSERR_DEVICE_INVALIDSIZE, "INVALID SIZE", }, + { ADSERR_DEVICE_INVALIDDATA, "INVALID DATA", }, + { ADSERR_DEVICE_NOTREADY, "NOT READY", }, + { ADSERR_DEVICE_BUSY, "BUSY", }, + { ADSERR_DEVICE_INVALIDCONTEXT, "INVALID CONTEXT", }, + { ADSERR_DEVICE_NOMEMORY, "NO MEMORY", }, + { ADSERR_DEVICE_INVALIDPARM, "INVALID PARM", }, + { ADSERR_DEVICE_NOTFOUND, "NOT FOUND", }, + { ADSERR_DEVICE_SYNTAX, "SYNTAX", }, + { ADSERR_DEVICE_INCOMPATIBLE, "INCOMPATIBLE", }, + { ADSERR_DEVICE_EXISTS, "EXISTS", }, + { ADSERR_DEVICE_SYMBOLNOTFOUND, "SYMBOL NOT FOUND", }, + { ADSERR_DEVICE_SYMBOLVERSIONINVALID, "SYMBOL VERSION INVALID", }, + { ADSERR_DEVICE_INVALIDSTATE, "INVALID STATE", }, + { ADSERR_DEVICE_TRANSMODENOTSUPP, "TRANS MODE NOT SUPP", }, + { ADSERR_DEVICE_NOTIFYHNDINVALID, "NOTIFY HND INVALID", }, + { ADSERR_DEVICE_CLIENTUNKNOWN, "CLIENT UNKNOWN", }, + { ADSERR_DEVICE_NOMOREHDLS, "NO MORE HDLS", }, + { ADSERR_DEVICE_INVALIDWATCHSIZE, "INVALID WATCHSIZE", }, + { ADSERR_DEVICE_NOTINIT, "NOT INIT", }, + { ADSERR_DEVICE_TIMEOUT, "TIMEOUT", }, + { ADSERR_DEVICE_NOINTERFACE, "NO INTERFACE", }, + { ADSERR_DEVICE_INVALIDINTERFACE, "INVALID INTERFACE", }, + { ADSERR_DEVICE_INVALIDCLSID, "INVALID CLSID", }, + { ADSERR_DEVICE_INVALIDOBJID, "INVALID OBJID", }, + { ADSERR_DEVICE_PENDING, "PENDING", }, + { ADSERR_DEVICE_ABORTED, "ABORTED", }, + { ADSERR_DEVICE_WARNING, "WARNING", }, + { ADSERR_DEVICE_INVALIDARRAYIDX, "INVALID ARRAY IDX", }, + { ADSERR_CLIENT_ERROR, "CLIENT ERROR", }, + { ADSERR_CLIENT_INVALIDPARM, "CLIENT INVALID PARM", }, + { ADSERR_CLIENT_LISTEMPTY, "CLIENT LIST EMPTY", }, + { ADSERR_CLIENT_VARUSED, "CLIENT VAR USED", }, + { ADSERR_CLIENT_DUPLINVOKEID, "CLIENT DUPL INVOKEID", }, + { ADSERR_CLIENT_SYNCTIMEOUT, "CLIENT SYNC TIMEOUT", }, + { ADSERR_CLIENT_W32ERROR, "CLIENT W32ERROR", }, + { ADSERR_CLIENT_TIMEOUTINVALID, "CLIENT TIMEOUT INVALID", }, + { ADSERR_CLIENT_PORTNOTOPEN, "CLIENT PORT NOT OPEN", }, + { ADSERR_CLIENT_NOAMSADDR, "CLIENT NO AMS ADDR", }, + { ADSERR_CLIENT_SYNCINTERNAL, "CLIENT SYNC INTERNAL", }, + { ADSERR_CLIENT_ADDHASH, "CLIENT ADD HASH", }, + { ADSERR_CLIENT_REMOVEHASH, "CLIENT REMOVE HASH", }, + { ADSERR_CLIENT_NOMORESYM, "CLIENT NO MORE SYM", }, + { ADSERR_CLIENT_SYNCRESINVALID, "CLIENT SYNC RES INVALID", }, + { ADSERR_CLIENT_SYNCPORTLOCKED, "CLIENT SYNC PORT LOCKED", }, + { 0, NULL } +}; + + +/* AMS Command Id + * https://infosys.beckhoff.com/english.php?content=../content/1033/tcadsamsspec/html/tcadsamsspec_adscmd_readstate.htm&id=10652 + */ +static const value_string AMS_CommandId_vals[] = +{ + { ADSSRVID_INVALID, "Invalid", }, + { ADSSRVID_READDEVICEINFO, "ADS Read Device Info", }, + { ADSSRVID_READ, "ADS Read", }, + { ADSSRVID_WRITE, "ADS Write", }, + { ADSSRVID_READSTATE, "ADS Read State", }, + { ADSSRVID_WRITECTRL, "ADS Write Control", }, + { ADSSRVID_ADDDEVICENOTE, "ADS Add Device Notification", }, + { ADSSRVID_DELDEVICENOTE, "ADS Delete Device Notification", }, + { ADSSRVID_DEVICENOTE, "ADS Device Notification", }, + { ADSSRVID_READWRITE, "ADS Read Write", }, + { 0, NULL } +}; + + +static void NetIdFormater(tvbuff_t *tvb, guint offset, char *szText, gint nMax) +{ + snprintf ( szText, nMax, "%d.%d.%d.%d.%d.%d", tvb_get_guint8(tvb, offset), + tvb_get_guint8(tvb, offset+1), + tvb_get_guint8(tvb, offset+2), + tvb_get_guint8(tvb, offset+3), + tvb_get_guint8(tvb, offset+4), + tvb_get_guint8(tvb, offset+5) + ); +} + + + +/*ams*/ +static gint dissect_ams_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset) +{ + proto_item *ti, *anItem; + proto_tree *ams_tree = NULL, *ams_adstree, *ams_statetree; + guint ams_length = tvb_reported_length(tvb); + guint16 stateflags = 0; + guint16 cmdId = 0; + guint32 cbdata = 0; + + char szText[200]; + int nMax = sizeof(szText)-1; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMS"); + + col_clear(pinfo->cinfo, COL_INFO); + + if( ams_length < AmsHead_Len ) + return offset; + + if (tree) + { + ti = proto_tree_add_item(tree, proto_ams, tvb, 0, -1, ENC_NA); + ams_tree = proto_item_add_subtree(ti, ett_ams); + + NetIdFormater(tvb, offset, szText, nMax); + proto_tree_add_string(ams_tree, hf_ams_targetnetid, tvb, offset, AmsNetId_Len, szText); + offset += AmsNetId_Len; + + proto_tree_add_item(ams_tree, hf_ams_targetport, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset += (int)sizeof(guint16); + + NetIdFormater(tvb, offset, szText, nMax); + proto_tree_add_string(ams_tree, hf_ams_sendernetid, tvb, offset, AmsNetId_Len, szText); + offset += AmsNetId_Len; + + proto_tree_add_item(ams_tree, hf_ams_senderport, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset += (int)sizeof(guint16); + + proto_tree_add_item(ams_tree, hf_ams_cmdid, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + cmdId = tvb_get_letohs(tvb, offset); + offset+=(int)sizeof(guint16); + + anItem = proto_tree_add_item(ams_tree, hf_ams_stateflags, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + ams_statetree = proto_item_add_subtree(anItem, ett_ams_stateflags); + proto_tree_add_item(ams_statetree, hf_ams_stateresponse,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_statetree, hf_ams_statenoreturn,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_statetree, hf_ams_stateadscmd,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_statetree, hf_ams_statesyscmd,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_statetree, hf_ams_statehighprio,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_statetree, hf_ams_statetimestampadded,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_statetree, hf_ams_stateudp,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_statetree, hf_ams_stateinitcmd,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_statetree, hf_ams_statebroadcast,tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + stateflags = tvb_get_letohs(tvb, offset); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(ams_tree, hf_ams_cbdata, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + cbdata = tvb_get_letohl(tvb,offset); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_tree, hf_ams_errorcode, tvb, offset, (int)sizeof(guint32),ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_tree, hf_ams_invokeid, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + } + else + { + offset+=AmsHead_Len; + } + + if ( (stateflags & AMSCMDSF_ADSCMD) != 0 ) + { + /* ADS */ + if ( (stateflags & AMSCMDSF_RESPONSE) == 0 ) + { + /* Request */ + switch ( cmdId ) + { + case ADSSRVID_READ: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Request"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadrequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsReadReq_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadrequest); + proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + } + } + } + break; + case ADSSRVID_WRITE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Request"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adswriterequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsWriteReq_Len - (int)sizeof(guint16) ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswriterequest); + proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); + } + } + } + break; + case ADSSRVID_READWRITE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Write Request"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadwriterequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsReadWriteReq_Len - (int)sizeof(guint16)) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadwriterequest); + proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adscbreadlength, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adscbwritelength, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); + } + } + } + break; + case ADSSRVID_READSTATE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Read State Request"); + + if( tree && cbdata !=0 ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadstaterequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsReadStateReq_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadstaterequest); + proto_tree_add_item(ams_adstree, hf_ams_adsinvokeid, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + } + } + } + break; + case ADSSRVID_WRITECTRL: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Control Request"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adswritectrlrequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsWriteControlReq_Len - (int)sizeof(guint16) ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswritectrlrequest); + proto_tree_add_item(ams_adstree, hf_ams_adsstate, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(ams_adstree, hf_ams_adsdevicestate, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); + } + } + } + break; + case ADSSRVID_READDEVICEINFO: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Device Info Request"); + + if( tree && cbdata !=0 ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsreaddinforequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsReadDeviceInfoReq_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreaddinforequest); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + } + } + } + break; + case ADSSRVID_ADDDEVICENOTE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Add Device Notification Request"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsadddnrequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsAddDeviceNotificationReq_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsadddnrequest); + proto_tree_add_item(ams_adstree, hf_ams_adsindexgroup, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsindexoffset, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adstransmode, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsmaxdelay, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adscycletime, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + } + } + } + break; + case ADSSRVID_DELDEVICENOTE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Delete Device Notification Request"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsdeldnrequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsDelDeviceNotificationReq_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdeldnrequest); + proto_tree_add_item(ams_adstree, hf_ams_adsnotificationhandle, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + } + } + } + break; + case ADSSRVID_DEVICENOTE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Device Notification Request"); + + if( tree ) + { + /*guint32 cbLength; + guint32 nStamps;*/ + + anItem = proto_tree_add_item(ams_tree, hf_ams_adsdnrequest, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsDeviceNotificationReq_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdnrequest); + proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + /*cbLength = tvb_get_letohs(tvb, offset);*/ + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsnoteblocksstamps, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + /*nStamps = tvb_get_letohs(tvb, offset);*/ + offset+=(int)sizeof(guint32); + + /*ToDo: dissect noteblocks*/ + } + } + } + break; + } + } + else + { + /* Response */ + switch ( cmdId ) + { + case ADSSRVID_READ: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Response"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadresponse, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsReadRes_Len - (int)sizeof(guint16) ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadresponse); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); + } + } + } + break; + case ADSSRVID_WRITE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Response"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adswriteresponse, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsWriteRes_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswriteresponse); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + } + } + } + break; + case ADSSRVID_READWRITE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Write Response"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadwriteresponse, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsReadWriteRes_Len - (int)sizeof(guint16) ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadwriteresponse); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adscblength, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsdata, tvb, offset, ams_length-offset, ENC_NA); + } + } + } + break; + case ADSSRVID_READSTATE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Read State Response"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsreadstateresponse, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsReadStateRes_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreadstateresponse); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsstate, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(ams_adstree, hf_ams_adsdevicestate, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + } + } + } + break; + case ADSSRVID_WRITECTRL: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Write Control Response"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adswritectrlresponse, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsWriteControlRes_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adswritectrlresponse); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + } + } + } + break; + case ADSSRVID_READDEVICEINFO: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Read Device Info Response"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsreaddinforesponse, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsReadDeviceInfoRes_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsreaddinforesponse); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsversionversion, tvb, offset++, (int)sizeof(guint8), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_adstree, hf_ams_adsversionrevision, tvb, offset++, (int)sizeof(guint8), ENC_LITTLE_ENDIAN); + proto_tree_add_item(ams_adstree, hf_ams_adsversionbuild, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(ams_adstree, hf_ams_adsdevicename, tvb, offset, ams_length-offset, ENC_ASCII|ENC_NA); + } + } + } + break; + case ADSSRVID_ADDDEVICENOTE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Device Notification Response"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsadddnresponse, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsAddDeviceNotificationRes_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsadddnresponse); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint32); + + proto_tree_add_item(ams_adstree, hf_ams_adsnotificationhandle, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + } + } + } + break; + case ADSSRVID_DELDEVICENOTE: + { + col_append_str(pinfo->cinfo, COL_INFO, "ADS Delete Device Notification Response"); + + if( tree ) + { + anItem = proto_tree_add_item(ams_tree, hf_ams_adsdeldnresponse, tvb, offset, ams_length-offset, ENC_NA); + if( ams_length-offset >= TAdsDelDeviceNotificationRes_Len ) + { + ams_adstree = proto_item_add_subtree(anItem, ett_ams_adsdeldnresponse); + proto_tree_add_item(ams_adstree, hf_ams_adsresult, tvb, offset, (int)sizeof(guint32), ENC_LITTLE_ENDIAN); + } + } + } + break; + } + } + } + else + { + if ( (stateflags & AMSCMDSF_RESPONSE) == 0 ) + col_append_str(pinfo->cinfo, COL_INFO, "AMS Request"); + else + col_append_str(pinfo->cinfo, COL_INFO, "AMS Response"); + if( tree && ams_length-offset > 0 ) + proto_tree_add_item(ams_tree, hf_ams_data, tvb, offset, ams_length-offset, ENC_NA); + } + return offset; +} + +/*ams*/ +static gint dissect_ams(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + return dissect_ams_pdu(tvb, pinfo, tree, 0); +} + +static gint dissect_amstcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + if( TcpAdsParserHDR_Len > tvb_reported_length(tvb)) + return 0; + + return dissect_ams_pdu(tvb, pinfo, tree, TcpAdsParserHDR_Len); +} + +void proto_register_ams(void) +{ + static const true_false_string flags_set_truth = + { + "Set", + "Not set" + }; + + static hf_register_info hf[] = + { + { &hf_ams_sendernetid, + { "AMS Sender Net Id", "ams.sendernetid", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_senderport, + { "AMS Sender port", "ams.senderport", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_targetnetid, + { "AMS Target Net Id", "ams.targetnetid", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_targetport, + { "AMS Target port", "ams.targetport", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_cmdid, + { "CmdId", "ams.cmdid", + FT_UINT16, BASE_DEC, VALS(AMS_CommandId_vals), 0x0, + NULL, HFILL } + }, + { &hf_ams_stateflags, + { "StateFlags", "ams.stateflags", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_stateresponse, + { "RESPONSE", "ams.state_response", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_RESPONSE, + NULL, HFILL } + }, + { &hf_ams_statenoreturn, + { "NO RETURN", "ams.state_noreturn", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_NORETURN, + NULL, HFILL } + }, + { &hf_ams_stateadscmd, + { "ADS COMMAND", "ams.state_adscmd", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_ADSCMD, + NULL, HFILL } + }, + { &hf_ams_statesyscmd, + { "SYSTEM COMMAND", "ams.state_syscmd", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_SYSCMD, + NULL, HFILL } + }, + { &hf_ams_statehighprio, + { "HIGH PRIORITY COMMAND", "ams.state_highprio", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_HIGHPRIO, + NULL, HFILL } + }, + { &hf_ams_statetimestampadded, + { "TIMESTAMP ADDED", "ams.state_timestampadded", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_TIMESTAMPADDED, + NULL, HFILL } + }, + { &hf_ams_stateudp, + { "UDP COMMAND", "ams.state_udp", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_UDP, + NULL, HFILL } + }, + { &hf_ams_stateinitcmd, + { "INIT COMMAND", "ams.state_initcmd", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_INITCMD, + NULL, HFILL } + }, + { &hf_ams_statebroadcast, + { "BROADCAST", "ams.state_broadcast", + FT_BOOLEAN, 16, TFS(&flags_set_truth), AMSCMDSF_BROADCAST, + NULL, HFILL } + }, + { &hf_ams_cbdata, + { "cbData", "ams.cbdata", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_errorcode, + { "ErrorCode", "ams.errorcode", + FT_UINT32, BASE_HEX, VALS(ErrorCode), 0x0, + NULL, HFILL } + }, + { &hf_ams_invokeid, + { "InvokeId", "ams.invokeid", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsdata, + { "Data", "ams.ads_data", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_data, + { "Data", "ams.data", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsindexgroup, + { "IndexGroup", "ams.ads_indexgroup", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsindexoffset, + { "IndexOffset", "ams.ads_indexoffset", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adscblength, + { "CbLength", "ams.ads_cblength", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsreadrequest, + { "ADS Read Request", "ams.ads_read_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsreadresponse, + { "ADS Read Response", "ams.ads_read_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsinvokeid, + { "InvokeId", "ams.ads_invokeid", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsresult, + { "Result", "ams.adsresult", + FT_UINT32, BASE_HEX, VALS(AdsErrorMode), 0x0, + NULL, HFILL } + }, + { &hf_ams_adswriterequest, + { "ADS Write Request", "ams.ads_write_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adswriteresponse, + { "ADS Write Response", "ams.ads_write_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsreadwriterequest, + { "ADS ReadWrite Request", "ams.ads_readwrite_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsreadwriteresponse, + { "ADS ReadWrite Response", "ams.ads_readwrite_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adscbreadlength, + { "CBReadLength", "ams.ads_cbreadlength", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adscbwritelength, + { "CBWriteLength", "ams.ads_cbwritelength", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsstate, + { "AdsState", "ams.ads_state", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsdevicestate, + { "DeviceState", "ams.ads_devicestate", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsnotificationhandle, + { "NotificationHandle", "ams.ads_notificationhandle", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsreadstaterequest, + { "ADS Read State Request", "ams.ads_readstate_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsreadstateresponse, + { "ADS Read State Response", "ams.ads_readstate_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adswritectrlrequest, + { "ADS Write Ctrl Request", "ams.ads_writectrl_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adswritectrlresponse, + { "ADS Write Ctrl Response", "ams.ads_writectrl_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsreaddinforequest, + { "ADS Read Device Info Request", "ams.ads_readdinfo_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsreaddinforesponse, + { "ADS Read Device Info Response", "ams.ads_readdinfo_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsadddnrequest, + { "ADS Add Device Notification Request", "ams.ads_adddn_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsadddnresponse, + { "ADS Add Device Notification Response", "ams.ads_adddn_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsdeldnrequest, + { "ADS Delete Device Notification Request", "ams.ads_deldn_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsdeldnresponse, + { "ADS Delete Device Notification Response", "ams.ads_deldn_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsdnrequest, + { "ADS Device Notification Request", "ams.ads_dn_req", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_ams_adsdnresponse, + { "ADS Device Notification Response", "ams.ads_dn_res", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsnoteattrib, + { "InvokeId", "ams.ads_noteattrib", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsnoteblocks, + { "InvokeId", "ams.ads_noteblocks", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsversion, + { "ADS Version", "ams.ads_version", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_ams_adsdevicename, + { "Device Name","ams.ads_devicename", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsversionversion, + { "ADS Major Version", "ams.ads_versionversion", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsversionrevision, + { "ADS Minor Version", "ams.ads_versionrevision", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsversionbuild, + { "ADS Version Build", "ams.ads_versionbuild", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsnoteblocksstamps, + { "Count of Stamps", "ams.ads_noteblocksstamps", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_ams_adsnoteblocksstamp, + { "Notification Stamp", "ams.ads_noteblocksstamp", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adstimestamp, + { "Time Stamp", "ams.ads_timestamp", + FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adssamplecnt, + { "Count of Stamps", "ams.ads_samplecnt", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adsnoteblockssample, + { "Notification Sample", "ams.ads_noteblockssample", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_ams_adstransmode, + { "Trans Mode", "ams.ads_transmode", + FT_UINT32, BASE_DEC, VALS(TransMode), 0x0, + NULL, HFILL } + }, + { &hf_ams_adsmaxdelay, + { "Max Delay", "ams.ads_maxdelay", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adscycletime, + { "Cycle Time", "ams.ads_cycletime", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_ams_adscmpmax, + { "Cmp Mad", "ams.ads_cmpmax", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ams_adscmpmin, + { "Cmp Min", "ams.ads_cmpmin", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + } +#endif + }; + + static gint *ett[] = + { + &ett_ams, + &ett_ams_stateflags, + &ett_ams_adsreadrequest, + &ett_ams_adsreadresponse, + &ett_ams_adswriterequest, + &ett_ams_adswriteresponse, + &ett_ams_adsreadwriterequest, + &ett_ams_adsreadwriteresponse, + &ett_ams_adsreadstaterequest, + &ett_ams_adsreadstateresponse, + &ett_ams_adswritectrlrequest, + &ett_ams_adswritectrlresponse, + &ett_ams_adsreaddinforequest, + &ett_ams_adsreaddinforesponse, + &ett_ams_adsadddnrequest, + &ett_ams_adsadddnresponse, + &ett_ams_adsdeldnrequest, + &ett_ams_adsdeldnresponse, + &ett_ams_adsdnrequest + }; + + proto_ams = proto_register_protocol("AMS", "AMS", "ams"); + proto_register_field_array(proto_ams, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + ams_handle = register_dissector("ams", dissect_ams, proto_ams); + amstcp_handle = register_dissector("ams.tcp", dissect_amstcp, proto_ams ); +} + +/* The registration hand-off routing */ + +void proto_reg_handoff_ams(void) +{ + dissector_add_uint_with_preference("tcp.port", AMS_TCP_PORT, amstcp_handle); + dissector_add_uint("ecatf.type", 2, ams_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 3 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=3 tabstop=8 expandtab: + * :indentSize=3:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/packet-ams.h b/plugins/epan/ethercat/packet-ams.h new file mode 100644 index 00000000..199e1028 --- /dev/null +++ b/plugins/epan/ethercat/packet-ams.h @@ -0,0 +1,1153 @@ +/* packet-ams.h + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __PACKET_AMS_H__ +#define __PACKET_AMS_H__ + +/* FIXED PORTS */ + +#define AMSPORT_ROUTER 1 +#define AMSPORT_DEBUGGER 2 + +#define AMSPORT_LOGGER 100 +#define AMSPORT_EVENTLOG 110 +#define AMSPORT_R0_RTIME 200 +#define AMSPORT_R0_TRACE (AMSPORT_R0_RTIME+90) +#define AMSPORT_R0_IO 300 +#define AMSPORT_R0_SPS 400 +#define AMSPORT_R0_NC 500 +#define AMSPORT_R0_NCSAF 501 +#define AMSPORT_R0_NCSVB 511 +#define AMSPORT_R0_ISG 550 +#define AMSPORT_R0_CNC 600 +#define AMSPORT_R0_LINE 700 +#define AMSPORT_R0_PLC 800 +#define AMSPORT_R0_CAM 900 +#define AMSPORT_R0_CAMTOOL 950 + +#define AMSPORT_R0_IOPORTBEGIN 1000 +#define AMSPORT_R0_IOPORTEND 1199 + +#define AMSPORT_R0_USER 2000 + +#define AMSPORT_R3_SYSSERV 10000 +#define AMSPORT_R3_CTRLPROG 10000 +#define AMSPORT_R3_SYSCTRL 10001 +#define AMSPORT_R3_SYSSAMPLER 10100 +#define AMSPORT_R3_TCPRAWCONN 10200 +#define AMSPORT_R3_TCPIPSERVER 10201 +#define AMSPORT_R3_SYSMANAGER 10300 +#define AMSPORT_R3_SMSSERVER 10400 +#define AMSPORT_R3_MODBUSSERVER 10500 +#define AMSPORT_R3_PLCCONTROL 10800 +#define AMSPORT_R3_NCCTRL 11000 +#define AMSPORT_R3_NCINTERPRETER 11500 +#define AMSPORT_R3_STRECKECTRL 12000 +#define AMSPORT_R3_CAMCTRL 13000 +#define AMSPORT_R3_SCOPE 14000 +#define AMSPORT_R3_SINECH1 15000 +#define AMSPORT_R3_CONTROLNET 16000 +#define AMSPORT_R3_OPCSERVER 17000 +#define AMSPORT_R3_OPCCLIENT 17500 + +#define AMSPORT_R3_CUSTOMER_FIRST 25000 +#define AMSPORT_R3_CUSTOMER_LAST 25999 + +#define AMSPORT_FIRST 1 +#define AMSPORT_LAST 0xFFFE + +#define AMSPORT_UNFIXEDPORT 0 +#define AMSPORT_USEDEFAULT 0xFFFF + +#define AMSPORT_IOBOXBEGIN_USB 0x6E00 +#define AMSPORT_IOBOXEND_USB 0x6EFF +#define AMSPORT_IODEVBEGIN 0x7000 +#define AMSPORT_IODEVEND 0x70FF +#define AMSPORT_IOBOXBEGIN 0x7100 +#define AMSPORT_IOBOXEND 0x7FFF + +#define AMSPORT_FREEBEGIN 0x8000 +#define AMSPORT_FREEEND 0xBFFF + + +#define AMSPORT_NAMESIZE 31 + +/* Port types */ +typedef enum +{ + PORTTYPE_INVALID = -1, + PORTTYPE_ROUTER = 0x00, + PORTTYPE_R3PORT = 0x01, + PORTTYPE_R0CTRLPORT = 0x02, + PORTTYPE_R0TASKPORT = 0x03, + PORTTYPE_R0IOPORT = 0x04, + PORTTYPE_TPPORT = 0x05, + PORTTYPE_MAXVAL = 0xFF +}AMSPORT_TYPE; + +/* Command IDs */ + +#define AMSCMD_LOGMESSAGE 0x0001 +#define AMSCMD_ROUTERSHUTDOWN 0x0002 +#define AMSCMD_ROUTERACTIVATED 0x0003 +#define AMSCMD_SYSTEMREMOVED 0x0004 +#define AMSCMD_CLOSECONNECTION 0x0005 +#define AMSCMD_SIGNALSTART 0x00FB +#define AMSCMD_SIGNALSTOP 0x00FC +#define AMSCMD_HANDLERETAINDATA 0x00FD +#define AMSCMD_DEVICECONFIGID 0x00FE +#define AMSCMD_DOWNLOADSYMBOLS 0x00FF + +#define AMS_ERRLOGCMDS 0x100 + +#define AMS_TASKCMDS 0x500 +#define AMS_CTRLCMDS 0x600 + +#define AMS_ROUTERCMDS 0x900 +#define AMS_RTIMECMDS 0x1000 +#define AMS_TRACECMDS (AMS_RTIMECMDS+0x900) +#define AMS_IOCMDS 0x2000 +#define AMS_C1220CMDS (AMS_IOCMDS+0x100) +#define AMS_FCxxxxCMDS (AMS_IOCMDS+0x200) +#define AMS_SPSCMDS 0x3000 +#define AMS_NCCMDS 0x4000 +#define AMS_PLCCMDS 0x5000 +#define AMS_LINECMDS 0x6000 +#define AMS_CAMCMDS 0x7000 + +#define AMS_CMDSPECIFIC 0x8000 + + +#define AMSERRCODEISWARNING 0x80000000 + +/* Error Arrays */ + +#define ERR_ROUTERERRS 0x0500 +#define ERR_TASKERRS 0x0600 +#define ERR_ADSERRS 0x0700 +#define ERR_SYSSMPLERRS 0x0800 +#define ERR_RTIMEERRS 0x1000 +#define ERR_TRACEERRS (ERR_RTIMEERRS+0x900) +#define ERR_IOERRS 0x2000 +#define ERR_DPSLAVE (ERR_IOERRS+0x900) +#define ERR_CP5412A2 (ERR_IOERRS+0xA00) +#define ERR_ASP (ERR_IOERRS+0xB00) +#define ERR_CANSLAVE (ERR_IOERRS+0xC00) +#define ERR_CIF30 (ERR_IOERRS+0xD00) +#define ERR_IBSSLAVE (ERR_IOERRS+0xE00) +#define ERR_SPSERRS 0x3000 +#define ERR_NCERRS 0x4000 +#define ERR_PLCERRS 0x6000 +#define ERR_STRKERRS 0x7000 + +#define ERR_PRJSPECIFIC 0x7800 + +#define ERR_DRIVEERRS_C3D 0xD000 +#define ERR_DRIVEERRS_C2D 0xE000 +#define ERR_DRIVEERRS_C1D 0xF000 + + +/* Global Error codes */ +#define ERR_NOERROR 0 +#define ERR_INTERNAL 1 +#define ERR_NORTIME 2 +#define ERR_ALLOCLOCKEDMEM 3 +#define ERR_INSERTMAILBOX 4 +#define ERR_WRONGRECEIVEHMSG 5 +#define ERR_TARGETPORTNOTFOUND 6 +#define ERR_TARGETMACHINENOTFOUND 7 +#define ERR_UNKNOWNCMDID 8 +#define ERR_BADTASKID 9 +#define ERR_NOIO 10 +#define ERR_UNKNOWNAMSCMD 11 +#define ERR_WIN32ERROR 12 +#define ERR_PORTNOTCONNECTED 13 +#define ERR_INVALIDAMSLENGTH 14 +#define ERR_INVALIDAMSNETID 15 +#define ERR_LOWINSTLEVEL 16 +#define ERR_NODEBUGINTAVAILABLE 17 +#define ERR_PORTDISABLED 18 +#define ERR_PORTALREADYCONNECTED 19 +#define ERR_AMSSYNC_W32ERROR 20 +#define ERR_AMSSYNC_TIMEOUT 21 +#define ERR_AMSSYNC_AMSERROR 22 +#define ERR_AMSSYNC_NOINDEXINMAP 23 +#define ERR_INVALIDAMSPORT 24 +#define ERR_NOMEMORY 25 +#define ERR_TCPSEND 26 +#define ERR_HOSTUNREACHABLE 27 +#define ERR_INVALIDAMSFRAGMENT 28 + + +/* ROUTER */ +#define ROUTERERR_NOLOCKEDMEMORY 0 + ERR_ROUTERERRS +#define ROUTERERR_RESIZEMEMORY 1 + ERR_ROUTERERRS +#define ROUTERERR_MAILBOXFULL 2 + ERR_ROUTERERRS +#define ROUTERERR_DEBUGBOXFULL 3 + ERR_ROUTERERRS +#define ROUTERERR_UNKNOWNPORTTYPE 4 + ERR_ROUTERERRS +#define ROUTERERR_NOTINITIALIZED 5 + ERR_ROUTERERRS +#define ROUTERERR_PORTALREADYINUSE 6 + ERR_ROUTERERRS +#define ROUTERERR_NOTREGISTERED 7 + ERR_ROUTERERRS +#define ROUTERERR_NOMOREQUEUES 8 + ERR_ROUTERERRS +#define ROUTERERR_INVALIDPORT 9 + ERR_ROUTERERRS +#define ROUTERERR_NOTACTIVATED 10 + ERR_ROUTERERRS +#define ROUTERERR_FRAGMENTBOXFULL 11 + ERR_ROUTERERRS +#define ROUTERERR_FRAGMENTTIMEOUT 12 + ERR_ROUTERERRS +#define ROUTERERR_TOBEREMOVED 13 + ERR_ROUTERERRS + +#define TASKERR_UNKNOWNTASKTYPE 0 + ERR_TASKERRS +#define TASKERR_TASKTERMINATED 1 + ERR_TASKERRS +#define TASKERR_EVENTTIMEOUT 2 + ERR_TASKERRS + + +/* System Sampler */ +#define SMPLERR_INTERNAL 0 + ERR_SYSSMPLERRS +#define SMPLERR_INVALIDTYPE 1 + ERR_SYSSMPLERRS + + +/* RTIME */ +#define RTERR_INTERNAL 0 + ERR_RTIMEERRS +#define RTERR_BADTIMERPERIODS 1 + ERR_RTIMEERRS +#define RTERR_INVALIDTASKPTR 2 + ERR_RTIMEERRS +#define RTERR_INVALIDSTACKPTR 3 + ERR_RTIMEERRS +#define RTERR_PRIOEXISTS 4 + ERR_RTIMEERRS +#define RTERR_NOMORETCB 5 + ERR_RTIMEERRS +#define RTERR_NOMORESEMAS 6 + ERR_RTIMEERRS +#define RTERR_NOMOREQUEUES 7 + ERR_RTIMEERRS +#define RTERR_SHUTDOWNTIMEOUT 8 + ERR_RTIMEERRS +#define RTERR_CHECKHOSTOSNOPCR 9 + ERR_RTIMEERRS +#define RTERR_CHECKHOSTOSNOIDT 10 + ERR_RTIMEERRS +#define RTERR_CHECKHOSTOSNOPHYSMEM 11 + ERR_RTIMEERRS +#define RTERR_CHECKHOSTOSMAPERR 12 + ERR_RTIMEERRS +#define RTERR_EXTIRQALREADYDEF 13 + ERR_RTIMEERRS +#define RTERR_EXTIRQNOTDEF 14 + ERR_RTIMEERRS +#define RTERR_EXTIRQINSTALLFAILED 15 + ERR_RTIMEERRS +#define RTERR_IRQLNOTLESSOREQUAL 16 + ERR_RTIMEERRS +#define RTERR_SYSCLOCKFAILURE 17 + ERR_RTIMEERRS + + +/* TRACE */ +#define TRACEERR_REGISTRY 0 + ERR_TRACEERRS +#define TRACEERR_MEMMAP 1 + ERR_TRACEERRS +#define TRACEERR_NOTAVAIL 2 + ERR_TRACEERRS + + +/* IO */ +#define IOERR_INTERNAL (0 + ERR_IOERRS) +#define IOERR_BADCARDNO (1 + ERR_IOERRS) +#define IOERR_INVALIDCARDADDR (2 + ERR_IOERRS) +#define IOERR_CDLLISTFULL (3 + ERR_IOERRS) +#define IOERR_BADCDLPARAM (4 + ERR_IOERRS) +#define IOERR_OPENIOFAILED (5 + ERR_IOERRS) +#define IOERR_RESETIOFAILED (6 + ERR_IOERRS) +#define IOERR_UNKNOWNDEVICE (7 + ERR_IOERRS) +#define IOERR_UNKNOWNDEVICEID (8 + ERR_IOERRS) +#define IOERR_UNKNOWNIMAGEID (9 + ERR_IOERRS) +#define IOERR_GETIOSTATE (10 + ERR_IOERRS) +#define IOERR_BADIMAGEID (11 + ERR_IOERRS) +#define IOERR_NOMORECLIENTSPACE (12 + ERR_IOERRS) +#define IOERR_CLIENTINFONOTFOUND (13 + ERR_IOERRS) +#define IOERR_CDLNOTINUSE (14 + ERR_IOERRS) +#define IOERR_TIMEOUTWITHDEVICE (15 + ERR_IOERRS) +#define IOERR_C1220FUNC_1 (16 + ERR_IOERRS) +#define IOERR_C1220FUNC_9 (17 + ERR_IOERRS) +#define IOERR_C1220FUNC_C (18 + ERR_IOERRS) +#define IOERR_C1220FUNC_10 (19 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_MAXSEND (20 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_ADDRSET (21 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK (22 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK0 (23 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK1 (24 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK2 (25 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK3 (26 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK4 (27 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK5 (28 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK6 (29 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK7 (30 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK8 (31 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK9 (32 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK10 (33 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK11 (34 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK12 (35 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK13 (36 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK14 (37 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK15 (38 + ERR_IOERRS) +#define IOERR_C1220FUNC_1_BREAK16 (39 + ERR_IOERRS) +#define IOERR_SPC3DEVINITDP (40 + ERR_IOERRS) +#define IOERR_SPC3UPDATEOUTPUT (41 + ERR_IOERRS) +#define IOERR_CIF30READDIAG (42 + ERR_IOERRS) +#define IOERR_CIF30COMMNOTSTARTED (43 + ERR_IOERRS) +#define IOERR_CIF30SLAVEPARASIZE (44 + ERR_IOERRS) +#define IOERR_CIF30NOPARAS (45 + ERR_IOERRS) +#define IOERR_CIF30SLAVEERROR (46 + ERR_IOERRS) +#define IOERR_CIF30WATCHDOGEXPIRED (47 + ERR_IOERRS) +#define IOERR_UNKNOWNDEVICECMD (48 + ERR_IOERRS) +#define IOERR_CIF40MESSAGEHANDLING (49 + ERR_IOERRS) +#define IOERR_CIF40PARAERROR (50 + ERR_IOERRS) +#define IOERR_CIF40WATCHDOGEXPIRED (51 + ERR_IOERRS) +#define IOERR_CIF40FLAGERROR (52 + ERR_IOERRS) +#define IOERR_CIF40COMMNOTSTARTED (53 + ERR_IOERRS) +#define IOERR_CIF40READDIAG (54 + ERR_IOERRS) +#define IOERR_CIF40SLAVEERROR (55 + ERR_IOERRS) +#define IOERR_CIF40GLOBALERROR (56 + ERR_IOERRS) +#define IOERR_CIF40CONFIGLIST (57 + ERR_IOERRS) +#define IOERR_CP5412A2SLAVEPARASIZE (58 + ERR_IOERRS) +#define IOERR_CP5412A2NOPARAS (59 + ERR_IOERRS) +#define IOERR_CP5412A2SLAVEERROR (60 + ERR_IOERRS) +#define IOERR_CP5412A2FATAL (61 + ERR_IOERRS) +#define IOERR_CP5412A2MAILBOXUSED (62 + ERR_IOERRS) +#define IOERR_BEGINCONFIGWHILETICKER (63 + ERR_IOERRS) +#define IOERR_UNEXPECTEDBOXCOUNT (64 + ERR_IOERRS) +#define IOERR_C1200CHECKADDR (65 + ERR_IOERRS) +#define IOERR_C1200INTENSITYTEST (66 + ERR_IOERRS) +#define IOERR_NOIMAGE (67 + ERR_IOERRS) +#define IOERR_INVALIDIMAGEOFFSSIZE (68 + ERR_IOERRS) +#define IOERR_FORCESCOUNTEXCEEDEDMAXIMUM (69 + ERR_IOERRS) +#define IOERR_SERCOSLIFECOUNTERERR (70 + ERR_IOERRS) +#define IOERR_C1220NOTFOUND (71 + ERR_IOERRS) +#define IOERR_AMSDEVICENOAMSINTF (72 + ERR_IOERRS) +#define IOERR_AMSDEVICEAMSCMDIDNOTSUPP (73 + ERR_IOERRS) +#define IOERR_AMSDEVICEAMSSERVICERUNNING (74 + ERR_IOERRS) +#define IOERR_PLCINTERFACE_BUSY (75 + ERR_IOERRS) +#define IOERR_PLCINTERFACE_FAULT (76 + ERR_IOERRS) +#define IOERR_PLCINTERFACE_TIMEOUT (77 + ERR_IOERRS) +#define IOERR_PLCINTERFACE_RESETTIMEOUT (78 + ERR_IOERRS) +#define IOERR_PLCINTERFACE_NODATAEXCH (79 + ERR_IOERRS) +#define IOERR_PLCINTERFACE_RESET (80 + ERR_IOERRS) +#define IOERR_CP5412A2INVALIDADDR (81 + ERR_IOERRS) +#define IOERR_CP5412A2INVALIDPORT (82 + ERR_IOERRS) +#define IOERR_AMSDEVICEBADBOXNO (83 + ERR_IOERRS) +#define IOERR_AMSDEVICEBADTYPE (84 + ERR_IOERRS) +#define IOERR_AMSDEVICEILLEGALADDRESS (85 + ERR_IOERRS) +#define IOERR_CP5412A2INVALIDBOX (86 + ERR_IOERRS) +#define IOERR_AMSDEVICEFIFOOVERFLOW (87 + ERR_IOERRS) +#define IOERR_AMSDEVICEAMSSEQUENCEERROR (88 + ERR_IOERRS) +#define IOERR_CP5412A2DPV1SYNTAXERROR (89 + ERR_IOERRS) +#define IOERR_CP5412A2DEVICENOTRUNNING (90 + ERR_IOERRS) +#define IOERR_AMSDEVICENOTRUNNING (91 + ERR_IOERRS) +#define IOERR_AMSDEVICEBOXNOTDEFINED (92 + ERR_IOERRS) +#define IOERR_CP5412A2BADSERVICEPARA (93 + ERR_IOERRS) +#define IOERR_CP5412A2FIFOOVERFLOW (94 + ERR_IOERRS) +#define IOERR_COMPORTOPENFAILED (95 + ERR_IOERRS) +#define IOERR_CIF30BADMESSAGERESPONSE (96 + ERR_IOERRS) +#define IOERR_CIF30DELETEDATABASE (97 + ERR_IOERRS) +#define IOERR_CIF30STARTSEQFAILED (98 + ERR_IOERRS) +#define IOERR_CIF30DOWNLOADFAILED (99 + ERR_IOERRS) +#define IOERR_CIF30ENDSEQFAILED (100 + ERR_IOERRS) +#define IOERR_CIF30BUSLOADFAILED (101 + ERR_IOERRS) +#define IOERR_PLCINTERFACE_RESETREQ (102 + ERR_IOERRS) +#define IOERR_CP5412A2INVALIDCYCLETICKS (103 + ERR_IOERRS) +#define IOERR_CP5412A2DPBUSFAULT (104 + ERR_IOERRS) +#define IOERR_INVALIDTERMCONFIG (105 + ERR_IOERRS) +#define IOERR_SERCANSBREAK (106 + ERR_IOERRS) +#define IOERR_SERCANSPHASE0 (107 + ERR_IOERRS) +#define IOERR_SERCANSPHASE1 (108 + ERR_IOERRS) +#define IOERR_SERCANSPHASE2 (109 + ERR_IOERRS) +#define IOERR_SERCANSPHASE3 (110 + ERR_IOERRS) +#define IOERR_SERCANSPHASE4 (111 + ERR_IOERRS) +#define IOERR_SERCANSNCSERVICECHNFAILED (112 + ERR_IOERRS) +#define IOERR_RESOURCECONFICT (113 + ERR_IOERRS) +#define IOERR_C1220INITSTRINGCOMM (114 + ERR_IOERRS) +#define IOERR_C1220REGSTRINGSLAVE (115 + ERR_IOERRS) +#define IOERR_C1220STRREGFAULT (116 + ERR_IOERRS) +#define IOERR_IOSTATEBUSY (117 + ERR_IOERRS) +#define IOERR_IBSSCITWATCHDOGEXPIRED (118 + ERR_IOERRS) +#define IOERR_IBSSCITSYNCMAILBOXERROR (119 + ERR_IOERRS) +#define IOERR_IBSSCITCONFIRMDIAGERROR (120 + ERR_IOERRS) +#define IOERR_IBSSCITCREATECFGERROR (121 + ERR_IOERRS) +#define IOERR_IBSSCITCOMPLETEREADCFGERROR (122 + ERR_IOERRS) +#define IOERR_IBSSCITSTARTDATATRANSFERERROR (123 + ERR_IOERRS) +#define IOERR_IBSSCITSETFAULTINDICATION (124 + ERR_IOERRS) +#define IOERR_IBSSCITSETDEVICESTATEINDICATION (125 + ERR_IOERRS) +#define IOERR_IBSSCITSETBUSERRORINDICATION (126 + ERR_IOERRS) +#define IOERR_IBSSCITSTOPDATATRANSFERERROR (127 + ERR_IOERRS) +#define IOERR_IBSSCITSETVALUEINDICATION (128 + ERR_IOERRS) +#define IOERR_IBSSCITINITIATEREQ (129 + ERR_IOERRS) +#define IOERR_IBSSCITACTIVATECFGERROR (130 + ERR_IOERRS) +#define IOERR_IBSSCITCOMPACTLOADPDRLERROR (131 + ERR_IOERRS) +#define IOERR_IBSSCITCONTROLPARAMERROR (132 + ERR_IOERRS) +#define IOERR_IBSSCITDEACTIVATECFGERROR (133 + ERR_IOERRS) +#define IOERR_IBSSCITINVALIDPORT (134 + ERR_IOERRS) +#define IOERR_C1220FUNC_7_ADDRESSTEST (135 + ERR_IOERRS) +#define IOERR_FCXXXXMAILBOXUSED (136 + ERR_IOERRS) +#define IOERR_FCXXXXDPRAMTOOSMALL (137 + ERR_IOERRS) +#define IOERR_COMUPS_PORTINUSE (138 + ERR_IOERRS) +#define IOERR_COMUPS_NOUPSORNOPOWER (139 + ERR_IOERRS) +#define IOERR_COMUPS_LOWBATTERY (140 + ERR_IOERRS) +#define IOERR_UPS_ALREADY_EXISTS (141 + ERR_IOERRS) +#define IOERR_FCXXXXSTARTUPFAILED (142 + ERR_IOERRS) +#define IOERR_C1220GETSTRINGCOMMTXSTATEFAILED (143 + ERR_IOERRS) +#define IOERR_C1220SENDSTRINGTOSLAVEFAILED (144 + ERR_IOERRS) +#define IOERR_CP5613FIRMWARELOADFAILED (145 + ERR_IOERRS) +#define IOERR_CP5613DPOPENFAILED (146 + ERR_IOERRS) +#define IOERR_CP5613FATALERROR (147 + ERR_IOERRS) +#define IOERR_CP5613DPUSEROPENFAILED (148 + ERR_IOERRS) +#define IOERR_CP5613DPSETMODESTOPFAILED (149 + ERR_IOERRS) +#define IOERR_CP5613DPSETMODECLEARFAILED (150 + ERR_IOERRS) +#define IOERR_CP5613DPSETMODEOPERATEFAILED (151 + ERR_IOERRS) +#define IOERR_CP5613NODATAAVAILABLE (152 + ERR_IOERRS) +#define IOERR_CP5613DPSERVICEFAILED (153 + ERR_IOERRS) +#define IOERR_CP5613DPSETMODEOFFLINEFAILED (154 + ERR_IOERRS) +#define IOERR_CP5613DPUSERCLOSEFAILED (155 + ERR_IOERRS) +#define IOERR_CP5613DPCLOSEFAILED (156 + ERR_IOERRS) +#define IOERR_CP5613OTHERSERVICERETURNED (157 + ERR_IOERRS) +#define IOERR_CP5613DPOKASYNC (158 + ERR_IOERRS) +#define IOERR_CP5613DPERROREVENT (159 + ERR_IOERRS) +#define IOERR_CP5613DPERROREVENTNET (160 + ERR_IOERRS) +#define IOERR_CP5613DPERRORREQPAR (161 + ERR_IOERRS) +#define IOERR_CP5613DPERRORCI (162 + ERR_IOERRS) +#define IOERR_CP5613DPERRORRES (163 + ERR_IOERRS) +#define IOERR_CP5613DPERRORUSRABORT (164 + ERR_IOERRS) +#define IOERR_PKWSYNTAXERROR (165 + ERR_IOERRS) +#define IOERR_CP5412A2CDLCFGFAULT (166 + ERR_IOERRS) +#define IOERR_IBSSCITINITLOADCFGERROR (168 + ERR_IOERRS) +#define IOERR_IBSSCITLOADCFGERROR (169 + ERR_IOERRS) +#define IOERR_IBSSCITTERMLOADCFGERROR (170 + ERR_IOERRS) +#define IOERR_IBSSCITINITLOADPDRLERROR (171 + ERR_IOERRS) +#define IOERR_IBSSCITLOADPDRLERROR (172 + ERR_IOERRS) +#define IOERR_IBSSCITTERMLOADPDRLERROR (173 + ERR_IOERRS) +#define IOERR_IBSSCITDELETEOBJECTERROR (174 + ERR_IOERRS) +#define IOERR_IBSSCITCONTROLACTIVECFGGERROR (175 + ERR_IOERRS) +#define IOERR_IBSSCITINITLOADPDDLERROR (176 + ERR_IOERRS) +#define IOERR_IBSSCITLOADPDDLERROR (177 + ERR_IOERRS) +#define IOERR_IBSSCITTERMLOADPDDLERROR (178 + ERR_IOERRS) +#define IOERR_NOMOREMAPSINIMAGE (179 + ERR_IOERRS) +#define IOERR_IBSSCITSETSLAVEINFOERROR (180 + ERR_IOERRS) +#define IOERR_CIF40NOTREADY (190 + ERR_IOERRS) +#define IOERR_C1220SETAMSNETIDFAILED (191 + ERR_IOERRS) +#define IOERR_AMSDEVICEIORESETACTIVE (192 + ERR_IOERRS) +#define IOERR_C1220INITPROGRAMMABLECDL (193 + ERR_IOERRS) +#define IOERR_FCXXXXINVALIDBOXNODOWNLOADED (194 + ERR_IOERRS) + + +#define IOERR_CP5412A2_RESET (4 + ERR_CP5412A2) +#define IOERR_CP5412A2_LOADBUSPARA (5 + ERR_CP5412A2) +#define IOERR_CP5412A2_LOADSLAVE (6 + ERR_CP5412A2) +#define IOERR_CP5412A2_LOADPRMDATA (7 + ERR_CP5412A2) +#define IOERR_CP5412A2_LOADCFGDATA (8 + ERR_CP5412A2) +#define IOERR_CP5412A2_LOADSLAVECDL (9 + ERR_CP5412A2) +#define IOERR_CP5412A2_ACTIVATESLAVE (10 + ERR_CP5412A2) +#define IOERR_CP5412A2_ADDSLAVE (11 + ERR_CP5412A2) +#define IOERR_CP5412A2_DELETESLAVE (12 + ERR_CP5412A2) +#define IOERR_CP5412A2_STARTDATAEXCH (13 + ERR_CP5412A2) +#define IOERR_CP5412A2_STOPDATAEXCH (14 + ERR_CP5412A2) +#define IOERR_CP5412A2_DEBUGDPM (15 + ERR_CP5412A2) + + +/* FC Box - stamndadisiert */ + +#define FCERR_FMNOERROR 0 +#define FCERR_FMDEACTIVATED 1 +#define FCERR_FMNOANSWER 2 +#define FCERR_FMMASTERLOCK 3 +#define FCERR_FMINVALIDRESPONSE 4 +#define FCERR_FMPRMFAULT 5 +#define FCERR_FMFEATURENOTSUPPORTED 6 +#define FCERR_FMCFGFAULT 7 +#define FCERR_FMSTATIONNOTREADY 8 +#define FCERR_FMSTATDIAG 9 +#define FCERR_FMDIAGOVERFLOW 10 +#define FCERR_FMPHYSICALFAULT 11 +#define FCERR_FMDATATRANSFERLEFT 12 +#define FCERR_FMSYNIFAULT 13 +#define FCERR_FMTELEGRAMFAULT 14 +#define FCERR_FMNORESSOURCES 15 +#define FCERR_FMSERVICENOTACTIVATED 16 +#define FCERR_FMUNEXPECTEDTELEGRAM 17 +#define FCERR_FMSTATIONREADY 18 +#define FCERR_FMADSSTARTUP 19 +#define FCERR_FMINVALIDINDICATION 20 +#define FCERR_FMSTATIONINFAULT 21 +#define FCERR_FMINDICATIONMISSED 22 +#define FCERR_FMWAITFORINDICATIONS 23 + +#define FCERR_FMFBUSSPECIFIC_1 40 +#define FCERR_FMFBUSSPECIFIC_2 41 +#define FCERR_FMFBUSSPECIFIC_3 42 +#define FCERR_FMFBUSSPECIFIC_4 43 +#define FCERR_FMFBUSSPECIFIC_5 44 +#define FCERR_FMFBUSSPECIFIC_6 45 +#define FCERR_FMFBUSSPECIFIC_7 46 +#define FCERR_FMFBUSSPECIFIC_8 47 +#define FCERR_FMFBUSSPECIFIC_9 48 + + +/* FC520x */ + +#define FCERR_FMFC520XHEARTBEATFAULT 40 +#define FCERR_FMFC520XSHUTDOWNRECEIVED 41 +#define FCERR_FMFC520XEKEYERROR_VENDOR 42 +#define FCERR_FMFC520XEKEYERROR_DEVTYPE 43 +#define FCERR_FMFC520XEKEYERROR_PRODCODE 44 +#define FCERR_FMFC520XEKEYERROR_REVISION 45 +#define FCERR_FMFC520XSTARTUPATTR 46 +#define FCERR_FMFC520XIOLENGTH_PROD 47 +#define FCERR_FMFC520XIOLENGTH_CONS 48 + +#define FCERR_FMFC520XDEVICEOPERATE_RUN 0 +#define FCERR_FMFC520XDEVICEOPERATE_IDLE 1 +#define FCERR_FMFC520XDEVICEDUPMAC 2 +#define FCERR_FMFC520XDEVICESELFTEST 3 +#define FCERR_FMFC520XDEVICESTANDBY 4 +#define FCERR_FMFC520XDEVICEMAJORFAULT 5 +#define FCERR_FMFC520XDEVICEMINORFAULT 6 +#define FCERR_FMFC520XDEVICEBUSSENSEFAIL 7 + +#define FCERR_FMFC520XCANBUSON 0x01 +#define FCERR_FMFC520XCANBUSOFF 0x02 +#define FCERR_FMFC520XCANWARNINGLIMIT 0x04 +#define FCERR_FMFC520XCANOVERRUN 0x08 + + +/* DP-Slave-Errors */ + +#define DPSLAVEERROR_NOERROR (FCERR_FMNOERROR + ERR_DPSLAVE) +#define DPSLAVEERROR_STATIONDEACTIVATED (FCERR_FMDEACTIVATED + ERR_DPSLAVE) +#define DPSLAVEERROR_STATIONNONEXISTENT (FCERR_FMNOANSWER + ERR_DPSLAVE) +#define DPSLAVEERROR_MASTERLOCK (FCERR_FMMASTERLOCK + ERR_DPSLAVE) +#define DPSLAVEERROR_INVALIDSLAVERESPONSE (FCERR_FMINVALIDRESPONSE + ERR_DPSLAVE) +#define DPSLAVEERROR_PRMFAULT (FCERR_FMPRMFAULT + ERR_DPSLAVE) +#define DPSLAVEERROR_NOTSUPPORTED (FCERR_FMFEATURENOTSUPPORTED + ERR_DPSLAVE) +#define DPSLAVEERROR_CFGFAULT (FCERR_FMCFGFAULT + ERR_DPSLAVE) +#define DPSLAVEERROR_STATIONNOTREADY (FCERR_FMSTATIONNOTREADY + ERR_DPSLAVE) +#define DPSLAVEERROR_STATDIAG (FCERR_FMSTATDIAG + ERR_DPSLAVE) +#define DPSLAVEERROR_DIAGOVERFLOW (FCERR_FMDIAGOVERFLOW + ERR_DPSLAVE) +#define DPSLAVEERROR_PHYSICALFAULT (FCERR_FMPHYSICALFAULT + ERR_DPSLAVE) +#define DPSLAVEERROR_TELEGRAMFAULT (FCERR_FMTELEGRAMFAULT + ERR_DPSLAVE) +#define DPSLAVEERROR_NORESSOURCES (FCERR_FMNORESSOURCES + ERR_DPSLAVE) +#define DPSLAVEERROR_SERVICENOTACTIVATED (FCERR_FMSERVICENOTACTIVATED + ERR_DPSLAVE) +#define DPSLAVEERROR_UNEXPECTEDTELEGRAM (FCERR_FMUNEXPECTEDTELEGRAM + ERR_DPSLAVE) +#define DPSLAVEERROR_STATIONREADY (FCERR_FMSTATIONREADY + ERR_DPSLAVE) +#define DPSLAVEERROR_ADSSTARTUP (FCERR_FMADSSTARTUP + ERR_DPSLAVE) + + +/* CAN-Node-Errors */ + +#define CANNODEERROR_NOERROR (0 + ERR_CANSLAVE) +#define CANNODEERROR_STATIONNONEXISTENT (1 + ERR_CANSLAVE) +#define CANNODEERROR_PRMFAULT (4 + ERR_CANSLAVE) +#define CANNODEERROR_CFGFAULT (6 + ERR_CANSLAVE) +#define CANNODEERROR_DEACTIVATED (8 + ERR_CANSLAVE) +#define CANNODEERROR_PREOPERATIONAL (12 + ERR_CANSLAVE) +#define CANNODEERROR_NOT_OPERATIONAL (13 + ERR_CANSLAVE) + + +/* IBS-Device-Errors */ + +#define IBSDEVICEERROR_NOERROR (0 + ERR_IBSSLAVE) +#define IBSDEVICEERROR_STATIONDEACTIVATED (1 + ERR_IBSSLAVE) +#define IBSDEVICEERROR_STATIONNONEXISTENT (2 + ERR_IBSSLAVE) +#define IBSDEVICEERROR_CFGFAULT (6 + ERR_IBSSLAVE) +#define IBSDEVICEERROR_DIAGOVERFLOW (10 + ERR_IBSSLAVE) +#define IBSDEVICEERROR_PHYSICALFAULT (11 + ERR_IBSSLAVE) + + +/* PLC */ +#define PLCWRN_LOADINGBOOTPRJ ((0 + ERR_PLCERRS) | AMSERRCODEISWARNING) +#define PLCWRN_LOADINGRETAINDATA ((1 + ERR_PLCERRS) | AMSERRCODEISWARNING) + + +/* NC */ +#define ERR_NCR0MANERRS (ERR_NCERRS+0x0000) +#define ERR_NCCHNERRS (ERR_NCERRS+0x0100) + + +/* NC: R0-Manager Error Codes */ +#define NCERR_INTERNAL (0x0000 + ERR_NCR0MANERRS) +#define NCERR_NOMEMORY (0x0001 + ERR_NCR0MANERRS) + +#define NCERR_UNKNOWNCHANNELID (0x0010 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNGROUPID (0x0011 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNAXISID (0x0012 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNENCODERID (0x0013 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNCONTROLLERID (0x0014 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNDRIVEID (0x0015 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNTABULARID (0x0016 + ERR_NCR0MANERRS) + +#define NCERR_UNKNOWNPLCTONCADDR (0x0020 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNNCTOPLCADDR (0x0021 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNENCINADDR (0x0022 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNENCOUTADDR (0x0023 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNDRIVEINADDR (0x0024 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNDRIVEOUTADDR (0x0025 + ERR_NCR0MANERRS) + +#define NCERR_UNKNOWNDSLAVETYPE (0x0030 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNAXISTYPE (0x0031 + ERR_NCR0MANERRS) +#define NCERR_UNKNOWNCHNTYPE (0x0032 + ERR_NCR0MANERRS) + +#define NCERR_AXISINCOMPATIBLE (0x0040 + ERR_NCR0MANERRS) + +#define NCERR_CHANNELINCOMPLETE (0x0050 + ERR_NCR0MANERRS) +#define NCERR_GROUPINCOMPLETE (0x0051 + ERR_NCR0MANERRS) +#define NCERR_AXISINCOMPLETE (0x0052 + ERR_NCR0MANERRS) + +#define NCERR_CHANNELEXISTS (0x0060 + ERR_NCR0MANERRS) +#define NCERR_GROUPEXISTS (0x0061 + ERR_NCR0MANERRS) +#define NCERR_AXISEXISTS (0x0062 + ERR_NCR0MANERRS) +#define NCERR_TABULAREXISTS (0x0063 + ERR_NCR0MANERRS) + +#define NCERR_WRONGCHANNELINDEX (0x0070 + ERR_NCR0MANERRS) +#define NCERR_WRONGGROUPINDEX (0x0071 + ERR_NCR0MANERRS) + + +/* Channel Error Codes */ +#define NCCHNERR_GROUPINDEX (0x0001 + ERR_NCCHNERRS) +#define NCCHNERR_ADDR_GROUP (0x0002 + ERR_NCCHNERRS) +#define NCCHNERR_NO_PLCINTERFACE (0x0003 + ERR_NCCHNERRS) +#define NCCHNERR_ILLEGALMFUNCNR (0x0004 + ERR_NCCHNERRS) +#define NCCHNERR_NOMEMORY (0x0005 + ERR_NCCHNERRS) +#define NCCHNERR_ISBUSY (0x0006 + ERR_NCCHNERRS) +#define NCCHNERR_NOTSUPPORTED (0x0007 + ERR_NCCHNERRS) +#define NCCHNERR_ILLEGALSETTING (0x0008 + ERR_NCCHNERRS) + +#define NCCHNERR_NOFILE (0x0010 + ERR_NCCHNERRS) +#define NCCHNERR_ITPSYNTAXLT (0x0011 + ERR_NCCHNERRS) +#define NCCHNERR_ITPSYNTAXRT (0x0012 + ERR_NCCHNERRS) +#define NCCHNERR_SUBNOTFOUND (0x0013 + ERR_NCCHNERRS) +#define NCCHNERR_LOADBUFFERFULL (0x0014 + ERR_NCCHNERRS) +#define NCCHNERR_INVALIDIDENTIFIER (0x0015 + ERR_NCCHNERRS) +#define NCCHNERR_UNKNOWNIDENTIFIER (0x0016 + ERR_NCCHNERRS) +#define NCCHNERR_SUBINCOMPLETE (0x0017 + ERR_NCCHNERRS) + +#define NCCHNERR_ZERODIVIDE (0x0020 + ERR_NCCHNERRS) +#define NCCHNERR_BADCIRCLE (0x0021 + ERR_NCCHNERRS) +#define NCCHNERR_INVALIDOPERATION (0x0022 + ERR_NCCHNERRS) + +#define NCCHNERR_CALLSTACKOVR (0x0030 + ERR_NCCHNERRS) +#define NCCHNERR_CALLSTACKUDR (0x0031 + ERR_NCCHNERRS) +#define NCCHNERR_CALCSTACKOVR (0x0032 + ERR_NCCHNERRS) +#define NCCHNERR_CALCSTACKUDR (0x0033 + ERR_NCCHNERRS) + +#define NCCHNERR_REGINDEX (0x0040 + ERR_NCCHNERRS) +#define NCCHNERR_GFUNCINDEX (0x0041 + ERR_NCCHNERRS) +#define NCCHNERR_MFUNCINDEX (0x0042 + ERR_NCCHNERRS) +#define NCCHNERR_EXTENDEDADDR (0x0043 + ERR_NCCHNERRS) +#define NCCHNERR_INTERNALINDEXH (0x0044 + ERR_NCCHNERRS) +#define NCCHNERR_MDBACCESSINDEX (0x0045 + ERR_NCCHNERRS) + +#define NCTRAFOERR_CANNOTCHANGE (0x0050 + ERR_NCCHNERRS) +#define NCTRAFOERR_CANNOTCORRECT (0x0051 + ERR_NCCHNERRS) +#define NCTRAFOERR_PLANE (0x0052 + ERR_NCCHNERRS) +#define NCTRAFOERR_DPARAMINVALID (0x0053 + ERR_NCCHNERRS) +#define NCTRAFOERR_TOOLRADIUSINV (0x0054 + ERR_NCCHNERRS) +#define NCTRAFOERR_CHANGETOOLRAD (0x0055 + ERR_NCCHNERRS) +#define NCTRAFOERR_CDOVERFLOW (0x0056 + ERR_NCCHNERRS) +#define NCTRAFOERR_CDON (0x0057 + ERR_NCCHNERRS) +#define NCTRAFOERR_CDCHECK (0x0058 + ERR_NCCHNERRS) +#define NCTRAFOERR_CDUNEXPECTED (0x0059 + ERR_NCCHNERRS) +#define NCTRAFOERR_CDNEGRADIUS (0x005A + ERR_NCCHNERRS) +#define NCTRAFOERR_CDOCCURED (0x005B + ERR_NCCHNERRS) +#define NCTRAFOERR_COOKEDTBLFULL (0x005C + ERR_NCCHNERRS) +#define NCTRAFOERR_TFTBLFULL (0x005D + ERR_NCCHNERRS) +#define NCTRAFOERR_EXECTFTBLFULL (0x005E + ERR_NCCHNERRS) +#define NCTRAFOERR_EXECTFT (0x005F + ERR_NCCHNERRS) + +#define NCBACKUPERR_WRITEDATA (0x0060 + ERR_NCCHNERRS) +#define NCBACKUPERR_TARGETENTRY (0x0061 + ERR_NCCHNERRS) + + +#define MACHINEIDENTRYDONTCARE 0xFF +#define AMS_NETIDLEN 23 + +typedef struct AmsNetId_ +{ + guint8 b[6]; +} AmsNetId; +#define AmsNetId_Len (int)sizeof(AmsNetId) + +typedef struct AmsAddr_ +{ + AmsNetId netId; + guint16 port; +} AmsAddr; + +typedef union ErrCodeUnion +{ + gint32 errCode; + gint32 hRcv; +} ErrCodeUnion; + +typedef union tUserUnion +{ + gint32 hUser; + struct + { + guint16 fragmentNo; + guint16 packetNo; + } a; +} UserUnion; + +typedef struct +{ + AmsAddr target; + AmsAddr sender; + guint16 cmdId; + guint16 stateFlags; + guint32 cbData; + + ErrCodeUnion anErrCodeUnion; + UserUnion aUserUnion; +} AmsHead; +#define AmsHead_Len (int)sizeof(AmsHead) + + +/* State flags */ + +#define AMSCMDSF_RESPONSE 0x0001 +#define AMSCMDSF_NORETURN 0x0002 +#define AMSCMDSF_ADSCMD 0x0004 +#define AMSCMDSF_SYSCMD 0x0008 +#define AMSCMDSF_HIGHPRIO 0x0010 +#define AMSCMDSF_TIMESTAMPADDED 0x0020 +#define AMSCMDSF_UDP 0x0040 +#define AMSCMDSF_INITCMD 0x0080 +#define AMSCMDSF_BROADCAST 0x8000 + + +/* AmsCmd */ + +typedef struct +{ + AmsHead head; +} AmsCmd, *PAmsCmd; + + +/* ADS */ + +#define ADS_FIXEDNAMESIZE 16 + + +/* ADS Service Ids */ +#define ADSSRVID_INVALID 0x00 +#define ADSSRVID_READDEVICEINFO 0x01 +#define ADSSRVID_READ 0x02 +#define ADSSRVID_WRITE 0x03 +#define ADSSRVID_READSTATE 0x04 +#define ADSSRVID_WRITECTRL 0x05 +#define ADSSRVID_ADDDEVICENOTE 0x06 +#define ADSSRVID_DELDEVICENOTE 0x07 +#define ADSSRVID_DEVICENOTE 0x08 +#define ADSSRVID_READWRITE 0x09 + +/* ADS reserved index groups */ +#define ADSIGRP_SYMTAB 0xF000 +#define ADSIGRP_SYMNAME 0xF001 +#define ADSIGRP_SYMVAL 0xF002 + +#define ADSIGRP_SYM_HNDBYNAME 0xF003 +#define ADSIGRP_SYM_VALBYNAME 0xF004 +#define ADSIGRP_SYM_VALBYHND 0xF005 +#define ADSIGRP_SYM_RELEASEHND 0xF006 +#define ADSIGRP_SYM_INFOBYNAME 0xF007 +#define ADSIGRP_SYM_VERSION 0xF008 +#define ADSIGRP_SYM_INFOBYNAMEEX 0xF009 + +#define ADSIGRP_SYM_DOWNLOAD 0xF00A +#define ADSIGRP_SYM_UPLOAD 0xF00B +#define ADSIGRP_SYM_UPLOADINFO 0xF00C +#define ADSIGRP_SYM_DOWNLOAD2 0xF00D +#define ADSIGRP_SYM_DT_UPLOAD 0xF00E +#define ADSIGRP_SYM_UPLOADINFO2 0xF00F + +#define ADSIGRP_SYMNOTE 0xF010 + +#define ADSIGRP_SYM_DT_INFOBYNAMEEX 0xF011 +#define ADSIGRP_SYM_ADDRBYHND 0xF012 + + +#define ADSIGRP_IOIMAGE_RWIB 0xF020 +#define ADSIGRP_IOIMAGE_RWIX 0xF021 +#define ADSIGRP_IOIMAGE_RISIZE 0xF025 + +#define ADSIGRP_IOIMAGE_RWOB 0xF030 +#define ADSIGRP_IOIMAGE_RWOX 0xF031 +#define ADSIGRP_IOIMAGE_ROSIZE 0xF035 +#define ADSIGRP_IOIMAGE_CLEARI 0xF040 +#define ADSIGRP_IOIMAGE_CLEARO 0xF050 + +#define ADSIGRP_IOIMAGE_RWIOB 0xF060 + +#define ADSIGRP_IOIMAGE_CREATE 0xF068 + +#define ADSIGRP_SUMUP_READ 0xF080 + +#define ADSIGRP_SUMUP_WRITE 0xF081 +#define ADS_SUMUP_IGRP(p, i) (((guint32*)p)[(i)*3+0]) +#define ADS_SUMUP_IOFFS(p, i) (((guint32*)p)[(i)*3+1]) +#define ADS_SUMUP_LENGTH(p, i) (((guint32*)p)[(i)*3+2]) + +#define ADSIGRP_DEVICE_DATA 0xF100 + #define ADSIOFFS_DEVDATA_ADSSTATE 0x0000 + #define ADSIOFFS_DEVDATA_DEVSTATE 0x0002 + #define ADSIOFFS_DEVDATA_CONFIGID 0x0004 + #define ADSIOFFS_DEVDATA_ADSVERSIONCHECK 0x0005 + +#define ADSIGRP_TASK_DATA 0xF200 +/* ADSIGRP_TASK_DATA reserved until 0xF2FF*/ + +#define ADSIGRP_CANOPEN_BEGIN 0xF300 +#define ADSIGRP_CANOPEN_SDO 0xF302 +#define ADSIGRP_CANOPEN_SDO_INFO_LIST 0xF3FC +#define ADSIGRP_CANOPEN_SDO_INFO_OBJ 0xF3FD +#define ADSIGRP_CANOPEN_SDO_INFO_ENTRY 0xF3FE +#define ADSIGRP_CANOPEN_END 0xF3FF + +#define ADSIGRP_ECAT_FOE_BEGIN 0xF400 +#define ADSIGRP_ECAT_FOE_FOPENREAD 0xF401 +#define ADSIGRP_ECAT_FOE_FOPENWRITE 0xF402 +#define ADSIGRP_ECAT_FOE_FCLOSE 0xF403 +#define ADSIGRP_ECAT_FOE_FREAD 0xF404 +#define ADSIGRP_ECAT_FOE_FWRITE 0xF405 +#define ADSIGRP_ECAT_FOE_PROGRESSINFO 0xF406 +#define ADSIGRP_ECAT_FOE_END 0xF41F + +#define ADSIGRP_ECAT_SOE 0xF420 + #define ADSIOFFS_ECAT_SOE_ELEMENT_MASK 0x00FF0000 + #define ADSIOFFS_ECAT_SOE_DATASTATE 0x00010000 + #define ADSIOFFS_ECAT_SOE_NAME 0x00020000 + #define ADSIOFFS_ECAT_SOE_ATTRIBUTE 0x00040000 + #define ADSIOFFS_ECAT_SOE_UNIT 0x00080000 + #define ADSIOFFS_ECAT_SOE_MIN 0x00100000 + #define ADSIOFFS_ECAT_SOE_MAX 0x00200000 + #define ADSIOFFS_ECAT_SOE_VALUE 0x00400000 + #define ADSIOFFS_ECAT_SOE_DEFAULT 0x00800000 + #define ADSIOFFS_ECAT_SOE_DRIVENO_MASK 0x07000000 + #define ADSIOFFS_ECAT_SOE_COMMAND 0x08000000 + +#define ADSIGRP_ECAT_VOE 0xF430 + + +typedef enum nAdsState +{ + ADSSTATE_INVALID =0, + ADSSTATE_IDLE =1, + ADSSTATE_RESET =2, + ADSSTATE_INIT =3, + ADSSTATE_START =4, + ADSSTATE_RUN =5, + ADSSTATE_STOP =6, + ADSSTATE_SAVECFG =7, + ADSSTATE_LOADCFG =8, + ADSSTATE_POWERFAILURE =9, + ADSSTATE_POWERGOOD =10, + ADSSTATE_ERROR =11, + ADSSTATE_SHUTDOWN =12, + ADSSTATE_SUSPEND =13, + ADSSTATE_RESUME =14, + ADSSTATE_CONFIG =15, + ADSSTATE_RECONFIG =16, + ADSSTATE_MAXSTATES +} ADSSTATE; + +typedef enum nAdsTransMode +{ + ADSTRANS_NOTRANS =0, + ADSTRANS_CLIENTCYCLE =1, + ADSTRANS_CLIENTONCHA =2, + ADSTRANS_SERVERCYCLE =3, + ADSTRANS_SERVERONCHA =4, + ADSTRANS_CLIENT1REQ =10, + ADSTRANS_MAXMODES +}ADSTRANSMODE; + + +/* ADS error codes */ +#define ADSERR_NOERR 0x00 + +#define ADSERR_DEVICE_ERROR (0x700) +#define ADSERR_DEVICE_SRVNOTSUPP (0x701) +#define ADSERR_DEVICE_INVALIDGRP (0x702) +#define ADSERR_DEVICE_INVALIDOFFSET (0x703) +#define ADSERR_DEVICE_INVALIDACCESS (0x704) +#define ADSERR_DEVICE_INVALIDSIZE (0x705) +#define ADSERR_DEVICE_INVALIDDATA (0x706) +#define ADSERR_DEVICE_NOTREADY (0x707) +#define ADSERR_DEVICE_BUSY (0x708) +#define ADSERR_DEVICE_INVALIDCONTEXT (0x709) +#define ADSERR_DEVICE_NOMEMORY (0x70A) +#define ADSERR_DEVICE_INVALIDPARM (0x70B) +#define ADSERR_DEVICE_NOTFOUND (0x70C) +#define ADSERR_DEVICE_SYNTAX (0x70D) +#define ADSERR_DEVICE_INCOMPATIBLE (0x70E) +#define ADSERR_DEVICE_EXISTS (0x70F) +#define ADSERR_DEVICE_SYMBOLNOTFOUND (0x710) +#define ADSERR_DEVICE_SYMBOLVERSIONINVALID (0x711) +#define ADSERR_DEVICE_INVALIDSTATE (0x712) +#define ADSERR_DEVICE_TRANSMODENOTSUPP (0x713) +#define ADSERR_DEVICE_NOTIFYHNDINVALID (0x714) +#define ADSERR_DEVICE_CLIENTUNKNOWN (0x715) +#define ADSERR_DEVICE_NOMOREHDLS (0x716) +#define ADSERR_DEVICE_INVALIDWATCHSIZE (0x717) +#define ADSERR_DEVICE_NOTINIT (0x718) +#define ADSERR_DEVICE_TIMEOUT (0x719) +#define ADSERR_DEVICE_NOINTERFACE (0x71A) +#define ADSERR_DEVICE_INVALIDINTERFACE (0x71B) +#define ADSERR_DEVICE_INVALIDCLSID (0x71C) +#define ADSERR_DEVICE_INVALIDOBJID (0x71D) +#define ADSERR_DEVICE_PENDING (0x71E) +#define ADSERR_DEVICE_ABORTED (0x71F) +#define ADSERR_DEVICE_WARNING (0x720) +#define ADSERR_DEVICE_INVALIDARRAYIDX (0x721) +#define ADSERR_DEVICE_SYMBOLNOTACTIVE (0x722) +#define ADSERR_DEVICE_ACCESSDENIED (0x723) + +#define ADSERR_CLIENT_ERROR (0x740) +#define ADSERR_CLIENT_INVALIDPARM (0x741) +#define ADSERR_CLIENT_LISTEMPTY (0x742) +#define ADSERR_CLIENT_VARUSED (0x743) +#define ADSERR_CLIENT_DUPLINVOKEID (0x744) +#define ADSERR_CLIENT_SYNCTIMEOUT (0x745) +#define ADSERR_CLIENT_W32ERROR (0x746) +#define ADSERR_CLIENT_TIMEOUTINVALID (0x747) +#define ADSERR_CLIENT_PORTNOTOPEN (0x748) +#define ADSERR_CLIENT_NOAMSADDR (0x749) +#define ADSERR_CLIENT_SYNCINTERNAL (0x750) +#define ADSERR_CLIENT_ADDHASH (0x751) +#define ADSERR_CLIENT_REMOVEHASH (0x752) +#define ADSERR_CLIENT_NOMORESYM (0x753) +#define ADSERR_CLIENT_SYNCRESINVALID (0x754) +#define ADSERR_CLIENT_SYNCPORTLOCKED (0x755) + + +#define FACILITY_TC_ADS 0x1811 +#define FACILITY_TC_CNC 0x1821 +#define FACILITY_TC_IO 0x1831 + + +#if 0 /* Unused ?? */ +#define ADS_E_ERROR (0x98110000L + ADSERR_DEVICE_ERROR) +#define ADS_E_SRVNOTSUPP (0x98110000L + ADSERR_DEVICE_SRVNOTSUPP) +#define ADS_E_INVALIDGRP (0x98110000L + ADSERR_DEVICE_INVALIDGRP) +#define ADS_E_INVALIDOFFSET (0x98110000L + ADSERR_DEVICE_INVALIDOFFSET) +#define ADS_E_INVALIDACCESS (0x98110000L + ADSERR_DEVICE_INVALIDACCESS) +#define ADS_E_INVALIDSIZE (0x98110000L + ADSERR_DEVICE_INVALIDSIZE) +#define ADS_E_INVALIDDATA (0x98110000L + ADSERR_DEVICE_INVALIDDATA) +#define ADS_E_NOTREADY (0x98110000L + ADSERR_DEVICE_NOTREADY) +#define ADS_E_BUSY (0x98110000L + ADSERR_DEVICE_BUSY) +#define ADS_E_INVALIDCONTEXT (0x98110000L + ADSERR_DEVICE_INVALIDCONTEXT) +#define ADS_E_NOMEMORY (0x98110000L + ADSERR_DEVICE_NOMEMORY) +#define ADS_E_INVALIDPARM (0x98110000L + ADSERR_DEVICE_INVALIDPARM) +#define ADS_E_NOTFOUND (0x98110000L + ADSERR_DEVICE_NOTFOUND) +#define ADS_E_SYNTAX (0x98110000L + ADSERR_DEVICE_SYNTAX) +#define ADS_E_INCOMPATIBLE (0x98110000L + ADSERR_DEVICE_INCOMPATIBLE) +#define ADS_E_EXISTS (0x98110000L + ADSERR_DEVICE_EXISTS) +#define ADS_E_SYMBOLNOTFOUND (0x98110000L + ADSERR_DEVICE_SYMBOLNOTFOUND) +#define ADS_E_SYMBOLVERSIONINVALID (0x98110000L + ADSERR_DEVICE_SYMBOLVERSIONINVALID) +#define ADS_E_INVALIDSTATE (0x98110000L + ADSERR_DEVICE_INVALIDSTATE) +#define ADS_E_TRANSMODENOTSUPP (0x98110000L + ADSERR_DEVICE_TRANSMODENOTSUPP) +#define ADS_E_NOTIFYHNDINVALID (0x98110000L + ADSERR_DEVICE_NOTIFYHNDINVALID) +#define ADS_E_CLIENTUNKNOWN (0x98110000L + ADSERR_DEVICE_CLIENTUNKNOWN) +#define ADS_E_NOMOREHDLS (0x98110000L + ADSERR_DEVICE_NOMOREHDLS) +#define ADS_E_INVALIDWATCHSIZE (0x98110000L + ADSERR_DEVICE_INVALIDWATCHSIZE) +#define ADS_E_NOTINIT (0x98110000L + ADSERR_DEVICE_NOTINIT) +#define ADS_E_TIMEOUT (0x98110000L + ADSERR_DEVICE_TIMEOUT) +#define ADS_E_NOINTERFACE (0x98110000L + ADSERR_DEVICE_NOINTERFACE) +#define ADS_E_INVALIDINTERFACE (0x98110000L + ADSERR_DEVICE_INVALIDINTERFACE) +#define ADS_E_INVALIDCLSID (0x98110000L + ADSERR_DEVICE_INVALIDCLSID) +#define ADS_E_INVALIDOBJID (0x98110000L + ADSERR_DEVICE_INVALIDOBJID) +#define ADS_E_PENDING (0x98110000L + ADSERR_DEVICE_PENDING) +#define ADS_E_ABORTED (0x98110000L + ADSERR_DEVICE_ABORTED) +#define ADS_E_WARNING (0x98110000L + ADSERR_DEVICE_WARNING) +#define ADS_E_INVALIDARRAYIDX (0x98110000L + ADSERR_DEVICE_INVALIDARRAYIDX) +#define ADS_E_SYMBOLNOTACTIVE (0x98110000L + ADSERR_DEVICE_SYMBOLNOTACTIVE) +#define ADS_E_ACCESSDENIED (0x98110000L + ADSERR_DEVICE_ACCESSDENIED) +#endif + +#ifndef ANYSIZE_ARRAY + #define ANYSIZE_ARRAY 1 +#endif + +/* ADS AMS command */ +/*typedef struct +{ + guint32 hNotification; + guint32 cbSampleSize; + guint8 data[ANYSIZE_ARRAY]; +} AdsNotificationSample, *PAdsNotificationSample;*/ +#define AdsNotificationSample_Min_Len 4 + +typedef struct +{ + guint32 invokeId; +} TAdsReadDeviceInfoReq; + +#define TAdsReadDeviceInfoReq_Len (int)sizeof(TAdsReadDeviceInfoReq) + +/*typedef struct +{ + guint16 adsState; + guint16 deviceState; + guint32 cbLength; + guint16 firstDataWord; +} TAdsWriteControlReq, TAdsWriteControlInd;*/ +#define TAdsWriteControlReq_Len 10 + +typedef struct +{ + guint32 invokeId; +} TAdsReadStateReq; +#define TAdsReadStateReq_Len (int)sizeof(TAdsReadStateReq) + +typedef struct +{ + guint32 indexGroup; + guint32 indexOffset; + guint32 cbLength; +} TAdsReadReq; +#define TAdsReadReq_Len (int)sizeof(TAdsReadReq) + +/*typedef struct +{ + guint32 indexGroup; + guint32 indexOffset; + guint32 cbLength; + guint16 firstDataWord; +} TAdsWriteReq;*/ +#define TAdsWriteReq_Len 14 + +/* +typedef struct +{ + guint32 indexGroup; + guint32 indexOffset; + guint32 cbReadLength; + guint32 cbWriteLength; + guint16 firstDataWord; +} TAdsReadWriteReq;*/ +#define TAdsReadWriteReq_Len 18 + +typedef struct +{ + guint32 cbLength; + guint32 nTransMode; + guint32 nMaxDelay; + guint32 nCycleTime; + guint8 nCmpMax[sizeof(double)]; + guint8 nCmpMin[sizeof(double)]; +} AdsNotificationAttrib; + +typedef struct +{ + guint32 indexGroup; + guint32 indexOffset; + AdsNotificationAttrib noteAttrib; +} TAdsAddDeviceNotificationReq; +#define TAdsAddDeviceNotificationReq_Len (int)sizeof(TAdsAddDeviceNotificationReq) + +typedef struct +{ + guint32 hNotification; +} TAdsDelDeviceNotificationReq; +#define TAdsDelDeviceNotificationReq_Len (int)sizeof(TAdsDelDeviceNotificationReq) + +typedef struct +{ + guint32 cbLength; + guint32 nStamps; +} TAdsDeviceNotificationReq; +#define TAdsDeviceNotificationReq_Len (int)sizeof(TAdsDeviceNotificationReq) + +typedef struct +{ + guint32 result; +} TAdsRes; +#define TAdsRes_Len (int)sizeof(TAdsRes) + +typedef struct +{ + guint8 version; + guint8 revision; + guint16 build; +} AdsVersion, *PAdsVersion; + +typedef struct +{ + guint32 result; + AdsVersion version; + char sName[ADS_FIXEDNAMESIZE]; +} TAdsReadDeviceInfoRes; +#define TAdsReadDeviceInfoRes_Len (int)sizeof(TAdsReadDeviceInfoRes) + +typedef struct +{ + guint32 result; +} TAdsWriteControlRes; +#define TAdsWriteControlRes_Len (int)sizeof(TAdsWriteControlRes) + +typedef struct +{ + guint32 result; + guint16 adsState; + guint16 deviceState; +} TAdsReadStateRes; +#define TAdsReadStateRes_Len (int)sizeof(TAdsReadStateRes) + +typedef struct +{ + guint32 result; + guint32 cbLength; + guint16 firstDataWord; +} TAdsReadRes; +#define TAdsReadRes_Len (int)sizeof(TAdsReadRes) + +typedef struct +{ + guint32 result; + guint32 cbLength; + guint16 firstDataWord; +} TAdsReadWriteRes; +#define TAdsReadWriteRes_Len (int)sizeof(TAdsReadWriteRes) + +typedef struct +{ + guint32 result; +} TAdsWriteRes; +#define TAdsWriteRes_Len (int)sizeof(TAdsWriteRes) + +typedef struct +{ + guint32 result; + guint32 handle; +} TAdsAddDeviceNotificationRes; +#define TAdsAddDeviceNotificationRes_Len (int)sizeof(TAdsAddDeviceNotificationRes) + +typedef struct +{ + guint32 result; +} TAdsDelDeviceNotificationRes; +#define TAdsDelDeviceNotificationRes_Len (int)sizeof(TAdsDelDeviceNotificationRes) + + +/* structure for decoding the header -----------------------------------------*/ +/*typedef struct +{ + guint16 reserved; + guint32 cbLength; +} TcpAdsParserHDR; +typedef TcpAdsParserHDR;*/ +#define TcpAdsParserHDR_Len 6 + + +#endif + + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 3 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=3 tabstop=8 expandtab: + * :indentSize=3:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/packet-ecatmb.c b/plugins/epan/ethercat/packet-ecatmb.c new file mode 100644 index 00000000..c5998540 --- /dev/null +++ b/plugins/epan/ethercat/packet-ecatmb.c @@ -0,0 +1,1995 @@ +/* packet-ecatmb.c + * Routines for EtherCAT packet disassembly + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include + +#include +#include + +#include "packet-ecatmb.h" + +#define BIT2BYTE(x) ((x+7)/8) +#define ENDOF(p) ((p)+1) /* pointer to end of *p */ + +void proto_register_ecat_mailbox(void); +void proto_reg_handoff_ecat_mailbox(void); + +static dissector_handle_t eth_handle; +static dissector_handle_t ams_handle; +static dissector_handle_t ecat_mailbox_handle; + +/* Define the EtherCAT mailbox proto */ +int proto_ecat_mailbox = -1; + +static int ett_ecat_mailbox = -1; +static int ett_ecat_mailbox_eoe = -1; +static int ett_ecat_mailbox_eoe_init = -1; +static int ett_ecat_mailbox_eoe_macfilter = -1; +static int ett_ecat_mailbox_eoe_macfilter_filter = -1; +static int ett_ecat_mailbox_eoe_macfilter_filtermask = -1; +static int ett_ecat_mailbox_coe = -1; +static int ett_ecat_mailbox_sdo = -1; +static int ett_ecat_mailbox_coe_sdoccs = -1; +static int ett_ecat_mailbox_coe_sdoscs = -1; +static int ett_ecat_mailbox_foe = -1; +static int ett_ecat_mailbox_foe_efw = -1; +static int ett_ecat_mailbox_soeflag = -1; +static int ett_ecat_mailbox_soe = -1; +static int ett_ecat_mailbox_fraghead = -1; +static int ett_ecat_mailbox_header = -1; + +static int hf_ecat_mailboxlength = -1; +static int hf_ecat_mailboxaddress = -1; +static int hf_ecat_mailboxpriority = -1; +static int hf_ecat_mailboxtype = -1; +static int hf_ecat_mailboxcounter = -1; +static int hf_ecat_mailbox_eoe = -1; +static int hf_ecat_mailbox_eoe_fraghead = -1; +static int hf_ecat_mailbox_eoe_type = -1; +static int hf_ecat_mailbox_eoe_fragno = -1; +static int hf_ecat_mailbox_eoe_offset = -1; +static int hf_ecat_mailbox_eoe_frame = -1; +static int hf_ecat_mailbox_eoe_last = -1; +static int hf_ecat_mailbox_eoe_timestampreq = -1; +static int hf_ecat_mailbox_eoe_timestampapp = -1; +static int hf_ecat_mailbox_eoe_fragment = -1; +static int hf_ecat_mailbox_eoe_init = -1; +static int hf_ecat_mailbox_eoe_init_contains_macaddr = -1; +static int hf_ecat_mailbox_eoe_init_contains_ipaddr = -1; +static int hf_ecat_mailbox_eoe_init_contains_subnetmask = -1; +static int hf_ecat_mailbox_eoe_init_contains_defaultgateway = -1; +static int hf_ecat_mailbox_eoe_init_contains_dnsserver = -1; +static int hf_ecat_mailbox_eoe_init_contains_dnsname = -1; +static int hf_ecat_mailbox_eoe_init_append_timestamp = -1; +static int hf_ecat_mailbox_eoe_init_macaddr = -1; +static int hf_ecat_mailbox_eoe_init_ipaddr = -1; +static int hf_ecat_mailbox_eoe_init_subnetmask = -1; +static int hf_ecat_mailbox_eoe_init_defaultgateway = -1; +static int hf_ecat_mailbox_eoe_init_dnsserver = -1; +static int hf_ecat_mailbox_eoe_init_dnsname = -1; +static int hf_ecat_mailbox_eoe_macfilter = -1; +static int hf_ecat_mailbox_eoe_macfilter_macfiltercount = -1; +static int hf_ecat_mailbox_eoe_macfilter_maskcount = -1; +static int hf_ecat_mailbox_eoe_macfilter_nobroadcasts = -1; +static int hf_ecat_mailbox_eoe_macfilter_filter; +static int hf_ecat_mailbox_eoe_macfilter_filters[16] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}; +static int hf_ecat_mailbox_eoe_macfilter_filtermask = -1; +static int hf_ecat_mailbox_eoe_macfilter_filtermasks[4] = {-1,-1,-1,-1}; +static int hf_ecat_mailbox_eoe_timestamp = -1; +static int hf_ecat_mailbox_coe = -1; +static int hf_ecat_mailbox_coe_number = -1; +static int hf_ecat_mailbox_coe_type = -1; +static int hf_ecat_mailbox_coe_sdoreq = -1; +static int hf_ecat_mailbox_coe_sdoccsid = -1; +static int hf_ecat_mailbox_coe_sdoccsid_sizeind = -1; +static int hf_ecat_mailbox_coe_sdoccsid_expedited = -1; +static int hf_ecat_mailbox_coe_sdoccsid_size0= -1; +static int hf_ecat_mailbox_coe_sdoccsid_size1= -1; +static int hf_ecat_mailbox_coe_sdoccsid_complete = -1; +static int hf_ecat_mailbox_coe_sdoccsds = -1; +static int hf_ecat_mailbox_coe_sdoccsds_lastseg = -1; +static int hf_ecat_mailbox_coe_sdoccsds_size = -1; +static int hf_ecat_mailbox_coe_sdoccsds_toggle = -1; +static int hf_ecat_mailbox_coe_sdoccsus = -1; +static int hf_ecat_mailbox_coe_sdoccsus_toggle = -1; +static int hf_ecat_mailbox_coe_sdoccsiu = -1; +/* static int hf_ecat_mailbox_coe_sdoccsiu_complete = -1; */ +static int hf_ecat_mailbox_coe_sdoidx = -1; +static int hf_ecat_mailbox_coe_sdoabortcode = -1; +static int hf_ecat_mailbox_coe_sdosub = -1; +static int hf_ecat_mailbox_coe_sdodata = -1; +static int hf_ecat_mailbox_coe_sdodata1 = -1; +static int hf_ecat_mailbox_coe_sdodata2 = -1; +static int hf_ecat_mailbox_coe_sdoldata = -1; +static int hf_ecat_mailbox_coe_sdolength = -1; +/* static int hf_ecat_mailbox_coe_sdoerror = -1; */ +static int hf_ecat_mailbox_coe_sdores = -1; +static int hf_ecat_mailbox_coe_sdoscsds = -1; +static int hf_ecat_mailbox_coe_sdoscsds_toggle = -1; +static int hf_ecat_mailbox_coe_sdoscsiu = -1; +static int hf_ecat_mailbox_coe_sdoscsiu_sizeind = -1; +static int hf_ecat_mailbox_coe_sdoscsiu_expedited = -1; +static int hf_ecat_mailbox_coe_sdoscsiu_size0 = -1; +static int hf_ecat_mailbox_coe_sdoscsiu_size1 = -1; +static int hf_ecat_mailbox_coe_sdoscsiu_complete = -1; +static int hf_ecat_mailbox_coe_sdoscsus = -1; +static int hf_ecat_mailbox_coe_sdoscsus_lastseg = -1; +static int hf_ecat_mailbox_coe_sdoscsus_bytes = -1; +static int hf_ecat_mailbox_coe_sdoscsus_toggle = -1; +static int hf_ecat_mailbox_coe_sdoinfoopcode = -1; +static int hf_ecat_mailbox_coe_sdoinfofrag = -1; +static int hf_ecat_mailbox_coe_sdoinfolisttype = -1; +static int hf_ecat_mailbox_coe_sdoinfolist = -1; +static int hf_ecat_mailbox_coe_sdoinfoindex = -1; +static int hf_ecat_mailbox_coe_sdoinfosubindex = -1; +static int hf_ecat_mailbox_coe_sdoinfovalueinfo = -1; +static int hf_ecat_mailbox_coe_sdoinfoerrorcode = -1; +static int hf_ecat_mailbox_coe_sdoinfodatatype = -1; +static int hf_ecat_mailbox_coe_sdoinfomaxsub = -1; +static int hf_ecat_mailbox_coe_sdoinfoobjcode = -1; +static int hf_ecat_mailbox_coe_sdoinfoname = -1; +static int hf_ecat_mailbox_coe_sdoinfobitlen = -1; +static int hf_ecat_mailbox_coe_sdoinfoobjaccess = -1; +static int hf_ecat_mailbox_coe_sdoinfounittype = -1; +static int hf_ecat_mailbox_coe_sdoinfodefaultvalue = -1; +static int hf_ecat_mailbox_coe_sdoinfominvalue = -1; +static int hf_ecat_mailbox_coe_sdoinfomaxvalue = -1; +static int hf_ecat_mailboxdata = -1; +static int hf_ecat_mailbox_foe = -1; +static int hf_ecat_mailbox_foe_opmode = -1; +static int hf_ecat_mailbox_foe_filelength = -1; +static int hf_ecat_mailbox_foe_filename = -1; +static int hf_ecat_mailbox_foe_packetno = -1; +static int hf_ecat_mailbox_foe_errcode = -1; +static int hf_ecat_mailbox_foe_errtext = -1; +static int hf_ecat_mailbox_foe_busydone = -1; +static int hf_ecat_mailbox_foe_busyentire = -1; +static int hf_ecat_mailbox_foe_data = -1; +static int hf_ecat_mailbox_foe_efw = -1; +static int hf_ecat_mailbox_foe_efw_cmd = -1; +static int hf_ecat_mailbox_foe_efw_size = -1; +static int hf_ecat_mailbox_foe_efw_addresslw = -1; +static int hf_ecat_mailbox_foe_efw_addresshw = -1; +static int hf_ecat_mailbox_foe_efw_data = -1; +static int hf_ecat_mailbox_soe = -1; +static int hf_ecat_mailbox_soe_header = -1; + +static int hf_ecat_mailbox_soe_header_opcode = -1; +static int hf_ecat_mailbox_soe_header_incomplete = -1; +static int hf_ecat_mailbox_soe_header_error = -1; +static int hf_ecat_mailbox_soe_header_driveno = -1; +static int hf_ecat_mailbox_soe_header_datastate = -1; +static int hf_ecat_mailbox_soe_header_name = -1; +static int hf_ecat_mailbox_soe_header_attribute = -1; +static int hf_ecat_mailbox_soe_header_unit = -1; +static int hf_ecat_mailbox_soe_header_min = -1; +static int hf_ecat_mailbox_soe_header_max = -1; +static int hf_ecat_mailbox_soe_header_value = -1; +static int hf_ecat_mailbox_soe_header_reserved = -1; +static int hf_ecat_mailbox_soe_idn = -1; +static int hf_ecat_mailbox_soe_data = -1; +static int hf_ecat_mailbox_soe_frag = -1; +static int hf_ecat_mailbox_soe_error = -1; + +static expert_field ei_ecat_mailbox_error = EI_INIT; +static expert_field ei_ecat_mailbox_coe_error = EI_INIT; +static expert_field ei_ecat_mailbox_eoe_error = EI_INIT; +static expert_field ei_ecat_mailbox_soe_error = EI_INIT; +static expert_field ei_ecat_mailbox_foe_error = EI_INIT; + + +static const value_string EcMBoxType[] = +{ + { 0, "Invalid", }, + { 1, "AoE (Vendor specific; Beckhoff ADS over EtherCAT)", }, + { 2, "EoE (Ethernet over EtherCAT)", }, + { 3, "CoE (CANopen over EtherCAT)", }, + { 4, "FoE (File access over EtherCAT)", }, + { 5, "SoE (Servo profile over EtherCAT)", }, + { 15, "VoE (Vendor specific over EtherCAT)"}, + { 0x80+1, "AoE - Err", }, + { 0x80+2, "EoE - Err", }, + { 0x80+3, "CoE - Err", }, + { 0x80+4, "FoE - Err", }, + { 0x80+5, "SoE - Err", }, + { 0, NULL } +}; + +static const value_string FoEOpMode[] = +{ + { 1, "RRQ", }, + { 2, "WRQ", }, + { 3, "DATA", }, + { 4, "ACK", }, + { 5, "ERROR", }, + { 6, "BUSY", }, + { 0, NULL } +}; + +static const value_string FoEEfwCmd[] = +{ + { 1, "Memory Transfer", }, + { 2, "Write Code", }, + { 3, "Check device id", }, + { 4, "Checksum", }, + { 5, "Write code checksum", }, + { 6, "Set device id", }, + { 8, "Set code id", }, + { 9, "NOP", }, + { 10, "Checksum checksum", }, + { 11, "boot checksum", }, + { 0, NULL } +}; + +static const value_string SoeOpcode[] = +{ + { 0, "unused" }, + { 1, "readReq" }, + { 2, "readRes"}, + { 3, "writeReq"}, + { 4, "writeRes" }, + { 5, "notification" }, + { 6, "emergency"}, + { 0, NULL } +}; + +static const value_string EoEType[] = +{ + { EOE_TYPE_FRAME_FRAG, "Fragment" }, + { EOE_TYPE_TIMESTAMP_RES, "TimeStamp" }, + { EOE_TYPE_INIT_REQ, "Init Req"}, + { EOE_TYPE_INIT_RES, "Init Res"}, + { EOE_TYPE_MACFILTER_REQ, "MAC Req" }, + { EOE_TYPE_MACFILTER_RES, "MAC Res" }, + { 0, NULL } +}; + +static const value_string CANopenType[] = +{ + { ETHERCAT_COE_TYPE_EMERGENCY, "EMERGENCY" }, + { ETHERCAT_COE_TYPE_SDOREQ, "SDO Req" }, + { ETHERCAT_COE_TYPE_SDORES, "SDO Res"}, + { ETHERCAT_COE_TYPE_TXPDO, "TxPDO"}, + { ETHERCAT_COE_TYPE_RXPDO, "RxPDO" }, + { ETHERCAT_COE_TYPE_TXPDO_RTR, "TxPDO_RTR" }, + { ETHERCAT_COE_TYPE_RXPDO_RTR, "RxPDO_RTR" }, + { ETHERCAT_COE_TYPE_SDOINFO, "SDO Information" }, + { 0, NULL } +}; + +static const value_string CANopenSdoInfo[] = +{ + { ECAT_COE_INFO_OPCODE_LIST_Q, "List Req" }, + { ECAT_COE_INFO_OPCODE_LIST_S, "List Res" }, + { ECAT_COE_INFO_OPCODE_OBJ_Q, "Obj Req"}, + { ECAT_COE_INFO_OPCODE_OBJ_S, "Obj Res"}, + { ECAT_COE_INFO_OPCODE_ENTRY_Q, "Entry Req" }, + { ECAT_COE_INFO_OPCODE_ENTRY_S, "Entry Res" }, + { ECAT_COE_INFO_OPCODE_ERROR_S, "Error Res" }, + { 0, NULL } +}; + +static const true_false_string tfs_complete = +{ + "Complete", "Legacy" +}; + +void init_mbx_header(PETHERCAT_MBOX_HEADER pMbox, tvbuff_t *tvb, gint offset) +{ + pMbox->Length = tvb_get_letohs(tvb, offset); offset+=2; + pMbox->Address = tvb_get_letohs(tvb, offset); offset+=2; + pMbox->aControlUnion.Control = tvb_get_letohs(tvb, offset); +} + +static void init_eoe_header(PETHERCAT_EOE_HEADER pEoE, tvbuff_t *tvb, gint offset) +{ + pEoE->anEoeHeaderInfoUnion.Info = tvb_get_letohs(tvb, offset); offset+=2; + pEoE->anEoeHeaderDataUnion.Result = tvb_get_letohs(tvb, offset); +} + +static void init_foe_header(PETHERCAT_FOE_HEADER pFoE, tvbuff_t *tvb, gint offset) +{ + pFoE->OpMode = tvb_get_guint8(tvb, offset++); + pFoE->Reserved1 = tvb_get_guint8(tvb, offset++); + pFoE->aFoeHeaderDataUnion.FileLength = tvb_get_letohl(tvb, offset); +} + +static void init_soe_header(PETHERCAT_SOE_HEADER pSoE, tvbuff_t *tvb, gint offset) +{ + pSoE->anSoeHeaderControlUnion.v2.Control = tvb_get_guint8(tvb, offset++); + pSoE->anSoeHeaderControlUnion.v2.Element = tvb_get_guint8(tvb, offset++); + pSoE->anSoeHeaderDataUnion.FragmentsLeft = tvb_get_letohs(tvb, offset); +} + +static void init_coe_header(PETHERCAT_COE_HEADER pCoE, tvbuff_t *tvb, gint offset) +{ + pCoE->header = tvb_get_letohs(tvb, offset); +} + +static void init_sdo_header(PETHERCAT_SDO_HEADER pSdo, tvbuff_t *tvb, gint offset) +{ + pSdo->anSdoHeaderUnion.CS = tvb_get_guint8(tvb, offset++); + pSdo->Index = tvb_get_letohs(tvb, offset);offset+=2; + pSdo->SubIndex = tvb_get_guint8(tvb, offset++); + pSdo->Data = tvb_get_letohl(tvb, offset); +} + +static void init_sdo_info_header(PETHERCAT_SDO_INFO_HEADER pInfo, tvbuff_t *tvb, gint offset) +{ + pInfo->anSdoControlUnion.Control = tvb_get_guint8(tvb, offset++); + pInfo->Reserved = tvb_get_guint8(tvb, offset); + pInfo->FragmentsLeft = 2; +} + +static void CANopenSdoReqFormatter(PETHERCAT_SDO_HEADER pSdo, char *szText, gint nMax) +{ + switch ( pSdo->anSdoHeaderUnion.Idq.Ccs ) + { + case SDO_CCS_INITIATE_DOWNLOAD: + snprintf ( szText, nMax, "SDO Req : 'Initiate Download' (%d) Idx=0x%x Sub=%d", pSdo->anSdoHeaderUnion.Idq.Ccs, pSdo->Index, pSdo->SubIndex); + break; + case SDO_CCS_INITIATE_UPLOAD: + snprintf ( szText, nMax, "SDO Req : 'Initiate Upload' (%d) Idx=0x%x Sub=%d", pSdo->anSdoHeaderUnion.Idq.Ccs, pSdo->Index, pSdo->SubIndex); + break; + case SDO_CCS_DOWNLOAD_SEGMENT: + snprintf ( szText, nMax, "SDO Req : 'Download Segment' (%d)", pSdo->anSdoHeaderUnion.Idq.Ccs); + break; + case SDO_CCS_UPLOAD_SEGMENT: + snprintf ( szText, nMax, "SDO Req : 'Upload Segment' (%d)", pSdo->anSdoHeaderUnion.Idq.Ccs); + break; + case SDO_CCS_ABORT_TRANSFER: + snprintf ( szText, nMax, "SDO Req : 'Abort Transfer' (%d)", pSdo->anSdoHeaderUnion.Idq.Ccs); + break; + default: + snprintf ( szText, nMax, "SDO Req : Ccs %d", pSdo->anSdoHeaderUnion.Idq.Ccs); + } +} + +static void FoeFormatter(tvbuff_t *tvb, wmem_allocator_t *scope, gint offset, char *szText, gint nMax, guint foe_length) +{ + ETHERCAT_FOE_HEADER foe; + char *tmp = NULL; + + init_foe_header(&foe, tvb, offset); + + switch ( foe.OpMode ) + { + case ECAT_FOE_OPMODE_RRQ: + case ECAT_FOE_OPMODE_WRQ: + case ECAT_FOE_OPMODE_ERR: + if ( foe_length > ETHERCAT_FOE_HEADER_LEN ) { + tmp = tvb_get_string_enc(scope, tvb, offset+ETHERCAT_FOE_HEADER_LEN, MIN(foe_length-ETHERCAT_FOE_HEADER_LEN, 49), ENC_ASCII); + } + break; + } + + switch ( foe.OpMode ) + { + case ECAT_FOE_OPMODE_RRQ: + snprintf ( szText, nMax, "FoE RRQ (%d) : '%s'", foe.aFoeHeaderDataUnion.FileLength, tmp ? tmp : ""); + break; + case ECAT_FOE_OPMODE_WRQ: + snprintf ( szText, nMax, "FoE WRQ (%d) : '%s'", foe.aFoeHeaderDataUnion.FileLength, tmp ? tmp : ""); + break; + case ECAT_FOE_OPMODE_DATA: + snprintf ( szText, nMax, "FoE DATA (%d) : %d Bytes", foe.aFoeHeaderDataUnion.v.PacketNo, foe_length-ETHERCAT_FOE_HEADER_LEN); + break; + case ECAT_FOE_OPMODE_ACK: + snprintf ( szText, nMax, "FoE ACK (%d)", foe.aFoeHeaderDataUnion.v.PacketNo); + break; + case ECAT_FOE_OPMODE_ERR: + snprintf ( szText, nMax, "FoE ERR (%d) : '%s'", foe.aFoeHeaderDataUnion.ErrorCode, tmp ? tmp : ""); + break; + case ECAT_FOE_OPMODE_BUSY: + if ( foe.aFoeHeaderDataUnion.v2.Entire > 0 ) + snprintf ( szText, nMax, "FoE BUSY (%d%%)", ((guint32)foe.aFoeHeaderDataUnion.v2.Done*100)/foe.aFoeHeaderDataUnion.v2.Entire); + else + snprintf ( szText, nMax, "FoE BUSY (%d/%d)", foe.aFoeHeaderDataUnion.v2.Done, foe.aFoeHeaderDataUnion.v2.Entire); + break; + default: + snprintf ( szText, nMax, "FoE Unknown"); + } +} + +static void SoEIdToString( char* txt, guint16 id, int nMax) +{ + if ( id & 0x8000 ) + snprintf(txt, nMax, "P-%d-%04d", (id>>12) & 0x0007, id & 0x0FFF ); + else + snprintf(txt, nMax, "S-%d-%04d", id>>12, id & 0x0FFF ); +} + +static void SoeFormatter(tvbuff_t *tvb, gint offset, char *szText, gint nMax, guint soe_length) +{ + ETHERCAT_SOE_HEADER soe; + char tmp[50]; + char elm[50]; + memset(tmp, 0, sizeof(tmp)); + + init_soe_header(&soe, tvb, offset); + offset+=ETHERCAT_SOE_HEADER_LEN; + + if ( !soe.anSoeHeaderControlUnion.v.Error ) + { + if ( !soe.anSoeHeaderControlUnion.v.InComplete ) + { + SoEIdToString(tmp, soe.anSoeHeaderDataUnion.IDN, sizeof(tmp)-1); + elm[0] = '\0'; + if ( soe.anSoeHeaderControlUnion.v.DataState ) + (void) g_strlcat(elm, "D", 50); + if ( soe.anSoeHeaderControlUnion.v.Name ) + (void) g_strlcat(elm, "N", 50); + if ( soe.anSoeHeaderControlUnion.v.Attribute ) + (void) g_strlcat(elm, "A", 50); + if ( soe.anSoeHeaderControlUnion.v.Unit ) + (void) g_strlcat(elm, "U", 50); + if ( soe.anSoeHeaderControlUnion.v.Min ) + (void) g_strlcat(elm, "I", 50); + if ( soe.anSoeHeaderControlUnion.v.Max ) + (void) g_strlcat(elm, "X", 50); + if ( soe.anSoeHeaderControlUnion.v.Value ) + (void) g_strlcat(elm, "V", 50); + switch ( soe.anSoeHeaderControlUnion.v.OpCode ) + { + case ECAT_SOE_OPCODE_RRQ: + snprintf ( szText, nMax, "SoE: RRQ (%s, '%s')", tmp, elm); + break; + case ECAT_SOE_OPCODE_RRS: + snprintf ( szText, nMax, "SoE: RRS (%s, '%s') : %u Bytes", tmp, elm, (guint)(soe_length-ETHERCAT_SOE_HEADER_LEN)); + break; + case ECAT_SOE_OPCODE_WRS: + snprintf ( szText, nMax, "SoE: WRS (%s, '%s')", tmp, elm); + break; + case ECAT_SOE_OPCODE_WRQ: + snprintf ( szText, nMax, "SoE: WRQ (%s, '%s') : %u Bytes", tmp, elm, (guint)(soe_length-ETHERCAT_SOE_HEADER_LEN)); + break; + case ECAT_SOE_OPCODE_NFC: + snprintf ( szText, nMax, "SoE: NFC (%s, '%s') : %u Bytes", tmp, elm, (guint)(soe_length-ETHERCAT_SOE_HEADER_LEN)); + break; + case 6: + snprintf ( szText, nMax, "SoE: EMGCY"); + break; + default: + snprintf ( szText, nMax, "SoE:"); + } + } + else + snprintf ( szText, nMax, "SoE: FragmentsLeft %d", soe.anSoeHeaderDataUnion.FragmentsLeft); + } + else + snprintf ( szText, nMax, "SoE: Error %04x", tvb_get_letohs(tvb, offset)); +} + +/* ethercat mailbox */ +static void dissect_ecat_coe(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *ecat_coe_tree = NULL, *ecat_sdo_tree, *ecat_coe_sdoccs_tree, *ecat_coe_sdoscs_tree; + + proto_item *anItem = NULL, *aparent = NULL; + char szText[200]; + int nMax = sizeof(szText)-1; + + guint coe_length = tvb_reported_length(tvb)-offset; + guint16 len; + + if( tree ) + { + anItem = proto_tree_add_bytes_format(tree, hf_ecat_mailbox_coe, tvb, offset, coe_length, NULL, "CoE"); + aparent = proto_item_get_parent(anItem); + proto_item_append_text(aparent,":CoE "); + } + + col_append_str(pinfo->cinfo, COL_INFO, "CoE "); + + if( coe_length >= ETHERCAT_COE_HEADER_LEN ) + { + ETHERCAT_COE_HEADER coe; + init_coe_header(&coe, tvb, offset); + if( tree ) + { + ecat_coe_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_coe); + + proto_tree_add_uint(ecat_coe_tree, hf_ecat_mailbox_coe_number, tvb, offset, ETHERCAT_COE_HEADER_LEN, coe.v.Number); + proto_tree_add_uint(ecat_coe_tree, hf_ecat_mailbox_coe_type, tvb, offset, ETHERCAT_COE_HEADER_LEN, coe.v.Type); + } + + offset += ETHERCAT_COE_HEADER_LEN; + + switch (coe.v.Type) + { + case ETHERCAT_COE_TYPE_SDOREQ: + { + ETHERCAT_SDO_HEADER sdo; + + if( coe_length < ETHERCAT_COE_HEADER_LEN + ETHERCAT_SDO_HEADER_LEN ) + { + col_append_str(pinfo->cinfo, COL_INFO, "Sdo Req - invalid length"); + expert_add_info_format(pinfo, ecat_coe_tree, &ei_ecat_mailbox_coe_error, "Sdo Req - invalid length"); + break; + } + + init_sdo_header(&sdo, tvb, offset); + + CANopenSdoReqFormatter(&sdo, szText, nMax); + col_append_str(pinfo->cinfo, COL_INFO, szText); + + if( tree ) + { + proto_item_append_text(aparent, "%s", szText); + + anItem = proto_tree_add_uint(ecat_coe_tree, hf_ecat_mailbox_coe_sdoreq, tvb, offset, 1, sdo.anSdoHeaderUnion.Idq.Ccs); + proto_item_set_text(anItem, "%s", szText); + ecat_sdo_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_sdo); + + switch ( sdo.anSdoHeaderUnion.Idq.Ccs ) + { + case SDO_CCS_INITIATE_DOWNLOAD: + anItem = proto_tree_add_item(ecat_sdo_tree, hf_ecat_mailbox_coe_sdoccsid, tvb, offset, 1, ENC_LITTLE_ENDIAN); + ecat_coe_sdoccs_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_coe_sdoccs); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsid_sizeind, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsid_expedited, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsid_size0, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsid_size1, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsid_complete, tvb, offset, 1, ENC_LITTLE_ENDIAN); + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoidx, tvb, offset+1, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdosub, tvb, offset+3, 1, ENC_LITTLE_ENDIAN); + if ( sdo.anSdoHeaderUnion.Idq.SizeInd && !sdo.anSdoHeaderUnion.Idq.Expedited ) + { + len = coe_length - ETHERCAT_COE_HEADER_LEN - ETHERCAT_SDO_HEADER_LEN; + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdolength, tvb, offset+4, 4, ENC_LITTLE_ENDIAN); + offset+=ETHERCAT_SDO_HEADER_LEN; + if ( len > 0 ) + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoldata, tvb, offset, len, ENC_NA); + } + else + { + if ( sdo.anSdoHeaderUnion.Idq.Size == 3 ) + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdodata1, tvb, offset+4, 1, ENC_LITTLE_ENDIAN); + else if ( sdo.anSdoHeaderUnion.Idq.Size == 2 ) + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdodata2, tvb, offset+4, 2, ENC_LITTLE_ENDIAN); + else + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdodata, tvb, offset+4, 4, ENC_LITTLE_ENDIAN); + } + break; + case SDO_CCS_INITIATE_UPLOAD: + anItem = proto_tree_add_item(ecat_sdo_tree, hf_ecat_mailbox_coe_sdoccsiu, tvb, offset, 1, ENC_LITTLE_ENDIAN); + ecat_coe_sdoccs_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_coe_sdoccs); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsid_complete, tvb, offset, 1, ENC_LITTLE_ENDIAN); + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoidx, tvb, offset+1, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdosub, tvb, offset+3, 1, ENC_LITTLE_ENDIAN); + + break; + case SDO_CCS_DOWNLOAD_SEGMENT: + anItem = proto_tree_add_item(ecat_sdo_tree, hf_ecat_mailbox_coe_sdoccsds, tvb, offset, 1, ENC_LITTLE_ENDIAN); + ecat_coe_sdoccs_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_coe_sdoccs); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsds_lastseg, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsds_size, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsds_toggle, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset+=1; + + if ( coe_length-offset > 0 ) + { + anItem = proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoldata, tvb, offset, coe_length-offset, ENC_NA); + proto_item_append_text(anItem, "(len = %d)", coe_length-offset); + } + break; + case SDO_CCS_UPLOAD_SEGMENT: + anItem = proto_tree_add_item(ecat_sdo_tree, hf_ecat_mailbox_coe_sdoccsus, tvb, offset, 1, ENC_LITTLE_ENDIAN); + ecat_coe_sdoccs_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_coe_sdoccs); + proto_tree_add_item(ecat_coe_sdoccs_tree, hf_ecat_mailbox_coe_sdoccsus_toggle, tvb, offset, 1, ENC_LITTLE_ENDIAN); + break; + case SDO_CCS_ABORT_TRANSFER: + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoabortcode, tvb, offset+4, 4, ENC_LITTLE_ENDIAN); + break; + } + } + } + break; + + case ETHERCAT_COE_TYPE_SDORES: + { + ETHERCAT_SDO_HEADER sdo; + if( coe_length < ETHERCAT_COE_HEADER_LEN + ETHERCAT_SDO_HEADER_LEN ) + { + col_append_str(pinfo->cinfo, COL_INFO, "Sdo Res - invalid length"); + expert_add_info_format(pinfo, ecat_coe_tree, &ei_ecat_mailbox_coe_error, "Sdo Res - invalid length"); + break; + } + + init_sdo_header(&sdo, tvb, offset); + + col_append_fstr(pinfo->cinfo, COL_INFO, "SDO Res: Scs %d", sdo.anSdoHeaderUnion.Ids.Scs); + if( tree ) + { + proto_tree_add_uint_format_value(ecat_coe_tree, hf_ecat_mailbox_coe_sdores, tvb, offset, 1, sdo.anSdoHeaderUnion.Ids.Scs, + "Scs %d", sdo.anSdoHeaderUnion.Ids.Scs); + ecat_sdo_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_sdo); + + switch ( sdo.anSdoHeaderUnion.Ids.Scs ) + { + case SDO_SCS_INITIATE_DOWNLOAD: + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoidx, tvb, offset+1, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdosub, tvb, offset+3, 1, ENC_LITTLE_ENDIAN); + break; + case SDO_SCS_INITIATE_UPLOAD: + anItem = proto_tree_add_item(ecat_sdo_tree, hf_ecat_mailbox_coe_sdoscsiu, tvb, offset, 1, ENC_LITTLE_ENDIAN); + ecat_coe_sdoscs_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_coe_sdoscs); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsiu_sizeind, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsiu_expedited, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsiu_size0, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsiu_size1, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsiu_complete, tvb, offset, 1, ENC_LITTLE_ENDIAN); + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoidx, tvb, offset+1, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdosub, tvb, offset+3, 1, ENC_LITTLE_ENDIAN); + if ( sdo.anSdoHeaderUnion.Ius.SizeInd && !sdo.anSdoHeaderUnion.Ius.Expedited ) + { + len = coe_length - ETHERCAT_COE_HEADER_LEN - ETHERCAT_SDO_HEADER_LEN; + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdolength, tvb, offset+4, 4, ENC_LITTLE_ENDIAN); + offset+=ETHERCAT_SDO_HEADER_LEN; + if ( len > 0 ) + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoldata, tvb, offset, len, ENC_NA); + } + else if ( sdo.anSdoHeaderUnion.Ius.SizeInd && sdo.anSdoHeaderUnion.Ius.Expedited && sdo.anSdoHeaderUnion.Ius.Size == 3 ) + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdodata1, tvb, offset+4, 1, ENC_LITTLE_ENDIAN); + else if ( sdo.anSdoHeaderUnion.Ius.SizeInd && sdo.anSdoHeaderUnion.Ius.Expedited && sdo.anSdoHeaderUnion.Ius.Size == 2 ) + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdodata2, tvb, offset+4, 2, ENC_LITTLE_ENDIAN); + else + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdodata, tvb, offset+4, 4, ENC_LITTLE_ENDIAN); + break; + case SDO_SCS_DOWNLOAD_SEGMENT: + anItem = proto_tree_add_item(ecat_sdo_tree, hf_ecat_mailbox_coe_sdoscsds, tvb, offset, 1, ENC_LITTLE_ENDIAN); + ecat_coe_sdoscs_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_coe_sdoscs); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsds_toggle, tvb, offset, 1, ENC_LITTLE_ENDIAN); + break; + case SDO_SCS_UPLOAD_SEGMENT: + anItem = proto_tree_add_item(ecat_sdo_tree, hf_ecat_mailbox_coe_sdoscsus, tvb, offset, 1, ENC_LITTLE_ENDIAN); + ecat_coe_sdoscs_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_coe_sdoscs); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsus_lastseg, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsus_bytes, tvb, offset, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_sdoscs_tree, hf_ecat_mailbox_coe_sdoscsus_toggle, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset+=1; + + if ( coe_length-offset> 0 ) + { + anItem = proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoldata, tvb, offset, coe_length-offset, ENC_NA); + proto_item_append_text(anItem, "(len = %d)", coe_length-offset); + } + break; + } + } + } + break; + + case ETHERCAT_COE_TYPE_SDOINFO: + { + ETHERCAT_SDO_INFO_HEADER info; + + if( coe_length < ETHERCAT_COE_HEADER_LEN + ETHERCAT_SDO_INFO_LISTREQ_LEN ) + { + col_append_str(pinfo->cinfo, COL_INFO, "Sdo Info - invalid length"); + expert_add_info_format(pinfo, ecat_coe_tree, &ei_ecat_mailbox_coe_error, "Sdo Info - invalid length"); + break; + } + + memset(&info, 0x0, sizeof(info)); + init_sdo_info_header(&info, tvb, offset); + + col_append_str(pinfo->cinfo, COL_INFO, val_to_str(info.anSdoControlUnion.v.OpCode & 0x7F, CANopenSdoInfo, "%d (Unknown)")); + if ( info.anSdoControlUnion.v.InComplete ) + col_append_str(pinfo->cinfo, COL_INFO, " - More Follows"); + + if( tree ) + { + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoopcode, tvb, offset++, 1, ENC_LITTLE_ENDIAN); + offset++; /*Reserved*/ + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfofrag, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + switch ( info.anSdoControlUnion.v.OpCode ) + { + case ECAT_COE_INFO_OPCODE_LIST_Q: + { + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfolisttype, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } + break; + case ECAT_COE_INFO_OPCODE_LIST_S: + { + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfolisttype, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfolist, tvb, offset, coe_length-offset, ENC_NA); + } + break; + case ECAT_COE_INFO_OPCODE_OBJ_Q: + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoindex, tvb, offset, 2, ENC_LITTLE_ENDIAN); + break; + case ECAT_COE_INFO_OPCODE_OBJ_S: + { + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoindex, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfodatatype, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfomaxsub, tvb, offset++, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoobjcode, tvb, offset++, 1, ENC_LITTLE_ENDIAN); + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoname, tvb, offset, coe_length-offset, ENC_ASCII|ENC_NA); + } + break; + case ECAT_COE_INFO_OPCODE_ENTRY_Q: + { + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoindex, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfosubindex, tvb, offset++, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfovalueinfo, tvb, offset, 1, ENC_LITTLE_ENDIAN); + } + break; + case ECAT_COE_INFO_OPCODE_ENTRY_S: + { + guint16 objlen; + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoindex, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfosubindex, tvb, offset++, 1, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfovalueinfo, tvb, offset++, 1, ENC_LITTLE_ENDIAN); + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfodatatype, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfobitlen, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoobjaccess, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + if ( (info.anSdoInfoUnion.Entry.ValueInfo & 0x08) != 0 ) + { + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfounittype, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + } + if ( (info.anSdoInfoUnion.Entry.ValueInfo & 0x10) != 0 ) + { + objlen = BIT2BYTE(info.anSdoInfoUnion.Entry.Res.BitLen); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfodefaultvalue, tvb, offset, objlen, ENC_NA); + offset+=objlen; + } + if ( (info.anSdoInfoUnion.Entry.ValueInfo & 0x20) != 0 ) + { + objlen = BIT2BYTE(info.anSdoInfoUnion.Entry.Res.BitLen); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfominvalue, tvb, offset, objlen, ENC_NA); + offset+=objlen; + } + if ( (info.anSdoInfoUnion.Entry.ValueInfo & 0x40) != 0 ) + { + objlen = BIT2BYTE(info.anSdoInfoUnion.Entry.Res.BitLen); + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfomaxvalue, tvb, offset, objlen, ENC_NA); + offset+=objlen; + } + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoname, tvb, offset, coe_length-offset, ENC_ASCII|ENC_NA); + } + break; + case ECAT_COE_INFO_OPCODE_ERROR_S: + { + proto_tree_add_item(ecat_coe_tree, hf_ecat_mailbox_coe_sdoinfoerrorcode, tvb, offset, 4, ENC_LITTLE_ENDIAN); + } + break; + } + } + } + break; + } + } + else + { + col_append_str(pinfo->cinfo, COL_INFO, "- invalid length"); + expert_add_info(pinfo, tree, &ei_ecat_mailbox_coe_error); + } +} + +static void dissect_ecat_soe(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *ecat_soeflag_tree, *ecat_soe_tree; + + proto_item *anItem = NULL ,*aparent = NULL; + char szText[200]; + int nMax = sizeof(szText)-1; + + guint soe_length = tvb_reported_length(tvb)-offset; + + if( tree ) + { + anItem = proto_tree_add_item(tree, hf_ecat_mailbox_soe, tvb, offset, soe_length, ENC_NA); + + aparent = proto_item_get_parent(anItem); + proto_item_append_text(aparent,":SoE "); + } + + if( soe_length >= ETHERCAT_SOE_HEADER_LEN ) + { + SoeFormatter(tvb, offset, szText, nMax, soe_length); + col_append_str(pinfo->cinfo, COL_INFO, szText); + + if( tree ) + { + ETHERCAT_SOE_HEADER soe; + init_soe_header(&soe, tvb, offset); + + proto_item_append_text(aparent, "%s", szText); + proto_item_set_text(anItem, "%s", szText); + + ecat_soe_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_soe); + anItem = proto_tree_add_item(ecat_soe_tree, hf_ecat_mailbox_soe_header, tvb, offset , 2, ENC_LITTLE_ENDIAN); + + ecat_soeflag_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_soeflag); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_opcode, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_incomplete, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_error, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_driveno, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_datastate, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_name, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_attribute, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_unit, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_min, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_max, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_soeflag_tree, hf_ecat_mailbox_soe_header_reserved, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + if ( !soe.anSoeHeaderControlUnion.v.Error ) + { + if ( !soe.anSoeHeaderControlUnion.v.InComplete ) + { + switch (soe.anSoeHeaderControlUnion.v.OpCode) + { + case ECAT_SOE_OPCODE_RRQ: + case ECAT_SOE_OPCODE_WRS: + proto_tree_add_item(ecat_soe_tree, hf_ecat_mailbox_soe_idn, tvb, offset, 2, ENC_LITTLE_ENDIAN); + break; + case ECAT_SOE_OPCODE_RRS: + case ECAT_SOE_OPCODE_WRQ: + case ECAT_SOE_OPCODE_NFC: + proto_tree_add_item(ecat_soe_tree, hf_ecat_mailbox_soe_idn, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + proto_tree_add_item(tree, hf_ecat_mailbox_soe_data, tvb, offset, soe_length-offset, ENC_NA); + break; + } + } + else + { + proto_tree_add_item(ecat_soe_tree, hf_ecat_mailbox_soe_frag, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(tree, hf_ecat_mailbox_soe_data, tvb, offset, soe_length-offset, ENC_NA); + } + } + else + { + proto_tree_add_item(ecat_soe_tree, hf_ecat_mailbox_soe_idn, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree, hf_ecat_mailbox_soe_error, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } + } + } + else + { + col_append_str(pinfo->cinfo, COL_INFO, "SoE - invalid length"); + expert_add_info(pinfo, tree, &ei_ecat_mailbox_soe_error); + } +} + +static void dissect_ecat_eoe(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *ecat_eoe_tree = 0, *ecat_fraghead_tree, *ecat_eoe_init_tree, *ecat_eoe_macfilter_tree, + *ecat_eoe_macfilter_filter_tree; + tvbuff_t *next_tvb; + proto_item *anItem = NULL, *aparent = NULL; + int nCnt; + + guint eoe_length = tvb_reported_length(tvb)-offset; + + if( tree ) + { + anItem = proto_tree_add_bytes_format(tree, hf_ecat_mailbox_eoe, tvb, offset, eoe_length, NULL, "EoE Fragment"); + + aparent = proto_item_get_parent(anItem); + proto_item_append_text(aparent,":EoE "); + } + + if( eoe_length >= ETHERCAT_EOE_HEADER_LEN ) + { + ETHERCAT_EOE_HEADER eoe; + init_eoe_header(&eoe, tvb, offset); + if ( eoe.anEoeHeaderInfoUnion.v.Type == EOE_TYPE_FRAME_FRAG ) + col_append_fstr(pinfo->cinfo, COL_INFO, "EoE-Frag %d", eoe.anEoeHeaderDataUnion.v.Fragment); + else + col_append_str(pinfo->cinfo, COL_INFO, "EoE"); + + { /* Do the following even 'if (tree == NULL)' since a call_dissector() is done */ + ecat_eoe_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_eoe); + + anItem = proto_tree_add_item(ecat_eoe_tree, hf_ecat_mailbox_eoe_fraghead, tvb, offset, 4, ENC_NA); + ecat_fraghead_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_fraghead); + + proto_tree_add_uint(ecat_fraghead_tree, hf_ecat_mailbox_eoe_type, tvb, offset, 4, eoe.anEoeHeaderInfoUnion.v.Type); + + switch ( eoe.anEoeHeaderInfoUnion.v.Type ) + { + case EOE_TYPE_FRAME_FRAG: + proto_tree_add_uint(ecat_fraghead_tree, hf_ecat_mailbox_eoe_fragno, tvb, offset, 4, eoe.anEoeHeaderDataUnion.v.Fragment); + + if (eoe.anEoeHeaderDataUnion.v.Fragment == 0) + { + proto_tree_add_uint_format(ecat_fraghead_tree, hf_ecat_mailbox_eoe_offset, tvb, offset, 4, 32*eoe.anEoeHeaderDataUnion.v.OffsetBuffer, + "BufferSize: %d", 32*eoe.anEoeHeaderDataUnion.v.OffsetBuffer); + } + else + { + proto_tree_add_uint(ecat_fraghead_tree, hf_ecat_mailbox_eoe_offset, tvb, offset, 4, 32*eoe.anEoeHeaderDataUnion.v.OffsetBuffer); + } + + proto_tree_add_uint(ecat_fraghead_tree, hf_ecat_mailbox_eoe_frame, tvb, offset, 4, eoe.anEoeHeaderDataUnion.v.FrameNo); + + proto_tree_add_uint(ecat_fraghead_tree, hf_ecat_mailbox_eoe_last, tvb, offset, 4, eoe.anEoeHeaderInfoUnion.v.LastFragment); + + if ( eoe.anEoeHeaderInfoUnion.v.TimeStampRequested ) + { + proto_tree_add_uint(ecat_fraghead_tree, hf_ecat_mailbox_eoe_timestampreq, tvb, offset, 4, eoe.anEoeHeaderInfoUnion.v.TimeStampRequested); + } + + if ( eoe.anEoeHeaderInfoUnion.v.TimeStampAppended ) + { + proto_tree_add_uint(ecat_fraghead_tree, hf_ecat_mailbox_eoe_timestampapp, tvb, offset, 4, eoe.anEoeHeaderInfoUnion.v.TimeStampAppended); + } + + offset+=ETHERCAT_EOE_HEADER_LEN; + proto_tree_add_item(ecat_eoe_tree, hf_ecat_mailbox_eoe_fragment, tvb, offset, eoe_length-offset, ENC_NA); + + if ( eoe.anEoeHeaderDataUnion.v.Fragment == 0 ) + { + next_tvb = tvb_new_subset_length(tvb, offset, eoe_length-offset); + call_dissector( eth_handle, next_tvb, pinfo, ecat_eoe_tree); + } + + if ( eoe.anEoeHeaderInfoUnion.v.TimeStampAppended ) + { + proto_tree_add_item(ecat_eoe_tree, hf_ecat_mailbox_eoe_timestamp, tvb, eoe_length-ETHERCAT_EOE_TIMESTAMP_LEN, ETHERCAT_EOE_TIMESTAMP_LEN, ENC_LITTLE_ENDIAN); + } + break; + + case EOE_TYPE_TIMESTAMP_RES: + proto_tree_add_item(ecat_eoe_tree, hf_ecat_mailbox_eoe_timestamp, tvb, offset+ETHERCAT_EOE_HEADER_LEN, ETHERCAT_EOE_TIMESTAMP_LEN, ENC_LITTLE_ENDIAN); + break; + + case EOE_TYPE_INIT_REQ: + offset+=ETHERCAT_EOE_HEADER_LEN; + anItem = proto_tree_add_item(ecat_fraghead_tree, hf_ecat_mailbox_eoe_init, tvb, offset, MIN(eoe_length-offset,ETHERCAT_EOE_INIT_LEN), ENC_NA); + if( eoe_length-offset >= ETHERCAT_EOE_INIT_LEN ) + { + ecat_eoe_init_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_eoe_init); + + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_contains_macaddr, tvb, offset, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_contains_ipaddr, tvb, offset, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_contains_subnetmask, tvb, offset, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_contains_defaultgateway, tvb, offset, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_contains_dnsserver, tvb, offset, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_contains_dnsname, tvb, offset, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_append_timestamp, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=4; + + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_macaddr, tvb, offset, ETHERNET_ADDRESS_LEN, ENC_NA); + offset+=ETHERNET_ADDRESS_LEN; + + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_ipaddr, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=4; + + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_subnetmask, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=4; + + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_defaultgateway, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=4; + + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_dnsserver, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=4; + + proto_tree_add_item(ecat_eoe_init_tree, hf_ecat_mailbox_eoe_init_dnsname, tvb, offset, 32, ENC_ASCII|ENC_NA); + } + else + { + proto_item_append_text(anItem, " - Invalid length!"); + expert_add_info(pinfo, anItem, &ei_ecat_mailbox_eoe_error); + } + break; + + case EOE_TYPE_MACFILTER_REQ: + { + EoeMacFilterOptionsUnion options; + offset+=ETHERCAT_EOE_HEADER_LEN; + anItem = proto_tree_add_item(ecat_fraghead_tree, hf_ecat_mailbox_eoe_macfilter, tvb, offset, MIN(eoe_length-offset, ETHERCAT_EOE_MACFILTER_LEN), ENC_NA); + if( eoe_length-offset >= ETHERCAT_EOE_MACFILTER_LEN ) + { + proto_tree *ecat_eoe_macfilter_filtermask_tree; + + ecat_eoe_macfilter_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_eoe_macfilter); + + /* XXX: Is the field containing EoeMacFilterOptionsUnion 4 bytes or 2 bytes ? */ + /* sizeof EoeMacFilterOptionsUnion = 2 bytes but the code below */ + /* originally used a field width of 4 bytes. */ + /* Given the size of the union, the code below was changed to */ + /* use a field width of 2 bytes. */ + /* The hf[] entries were also changed to match the union struct */ + proto_tree_add_item(ecat_eoe_macfilter_tree, hf_ecat_mailbox_eoe_macfilter_macfiltercount, tvb, offset, /*4*/ 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_eoe_macfilter_tree, hf_ecat_mailbox_eoe_macfilter_maskcount, tvb, offset, /*4*/ 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ecat_eoe_macfilter_tree, hf_ecat_mailbox_eoe_macfilter_nobroadcasts, tvb, offset, /*4*/ 2, ENC_LITTLE_ENDIAN); + options.Options = tvb_get_letohs(tvb, offset); + offset+=/*4*/ 2; + + anItem = proto_tree_add_item(ecat_eoe_macfilter_tree, hf_ecat_mailbox_eoe_macfilter_filter, tvb, offset, 16*ETHERNET_ADDRESS_LEN, ENC_NA); + ecat_eoe_macfilter_filter_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_eoe_macfilter_filter); + for( nCnt=0; nCntcinfo, COL_INFO, "EoE("); + + col_prepend_fstr(pinfo->cinfo, COL_PROTOCOL, "EoE-"); + } + else + { + expert_add_info(pinfo, tree, &ei_ecat_mailbox_eoe_error); + col_append_str(pinfo->cinfo, COL_INFO, "EoE - invalid length!"); + } +} + +static void dissect_ecat_foe(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *ecat_foe_tree,*ecat_foe_efw_tree; + + proto_item *anItem= NULL,*aparent = NULL; + char szText[200]; + int nMax = sizeof(szText)-1; + + guint foe_length = tvb_reported_length(tvb)-offset; + + if( tree ) + { + anItem = proto_tree_add_bytes_format(tree, hf_ecat_mailbox_foe, tvb, offset, foe_length, NULL, "Foe"); + + aparent = proto_item_get_parent(anItem); + proto_item_append_text(aparent,": FoE"); + } + + if( foe_length >= ETHERCAT_FOE_HEADER_LEN ) + { + FoeFormatter(tvb, pinfo->pool, offset, szText, nMax, foe_length); + col_append_str(pinfo->cinfo, COL_INFO, szText); + + if( tree ) + { + ETHERCAT_FOE_HEADER foe; + init_foe_header(&foe, tvb, offset); + + ecat_foe_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_foe); + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_opmode, tvb, offset++, 1, ENC_LITTLE_ENDIAN); + offset++; /*Reserved1;*/ + + switch (foe.OpMode) + { + case ECAT_FOE_OPMODE_RRQ: + case ECAT_FOE_OPMODE_WRQ: + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_filelength, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=4; + + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_filename, tvb, offset, foe_length-offset, ENC_ASCII|ENC_NA); + break; + + case ECAT_FOE_OPMODE_DATA: + { + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_packetno, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=4; /*+2 for Reserved2*/ + + if( foe_length-offset >= sizeof(TEFWUPDATE_HEADER) ) + { + anItem = proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_efw, tvb, offset, foe_length-offset, ENC_NA); + ecat_foe_efw_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox_foe_efw); + proto_tree_add_item(ecat_foe_efw_tree, hf_ecat_mailbox_foe_efw_cmd, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_foe_efw_tree, hf_ecat_mailbox_foe_efw_size, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_foe_efw_tree, hf_ecat_mailbox_foe_efw_addresslw, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_foe_efw_tree, hf_ecat_mailbox_foe_efw_addresshw, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_foe_efw_tree, hf_ecat_mailbox_foe_efw_data, tvb, offset, foe_length-offset, ENC_NA); + } + else + { + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_data, tvb, offset, foe_length-offset, ENC_NA); + } + } + break; + + case ECAT_FOE_OPMODE_ACK: + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_packetno, tvb, offset, 2, ENC_LITTLE_ENDIAN); + break; + + case ECAT_FOE_OPMODE_ERR: + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_errcode, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset+=4; + + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_errtext, tvb, offset, foe_length-offset, ENC_ASCII|ENC_NA); + break; + + case ECAT_FOE_OPMODE_BUSY: + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_busydone, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + proto_tree_add_item(ecat_foe_tree, hf_ecat_mailbox_foe_busyentire, tvb, offset, 2, ENC_LITTLE_ENDIAN); + break; + } + } + } + else + { + col_append_str(pinfo->cinfo, COL_INFO, "FoE - invalid length"); + expert_add_info(pinfo, tree, &ei_ecat_mailbox_foe_error); + } +} + +static int dissect_ecat_mailbox(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_tree *ecat_mailbox_tree = NULL; + proto_tree *ecat_mailbox_header_tree = NULL; + tvbuff_t *next_tvb; + proto_item *anItem; + gint offset = 0; + + gint mailbox_length = tvb_reported_length(tvb); + + if( mailbox_length >= ETHERCAT_MBOX_HEADER_LEN ) + { + ETHERCAT_MBOX_HEADER hdr; + + init_mbx_header(&hdr, tvb, offset); + + col_append_str(pinfo->cinfo, COL_INFO, " Mbx("); + + /* Create the mailbox sub tree */ + anItem = proto_tree_add_item(tree, proto_ecat_mailbox, tvb, 0, ETHERCAT_MBOX_HEADER_LEN+hdr.Length, ENC_NA); + ecat_mailbox_tree = proto_item_add_subtree(anItem, ett_ecat_mailbox); + + /* Create a mailbox header subtree */ + ecat_mailbox_header_tree = proto_tree_add_subtree(ecat_mailbox_tree, tvb, offset, ETHERCAT_MBOX_HEADER_LEN, ett_ecat_mailbox_header, NULL, "Header"); + + /* Add length information to the mailbox header */ + proto_tree_add_item(ecat_mailbox_header_tree, hf_ecat_mailboxlength, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + /* Add address information to the mailbox header */ + proto_tree_add_item(ecat_mailbox_header_tree, hf_ecat_mailboxaddress, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset+=2; + + /* Add priority information to the mailbox header */ + proto_tree_add_item(ecat_mailbox_header_tree, hf_ecat_mailboxpriority, tvb, offset, 1, ENC_LITTLE_ENDIAN); + offset+=1; + + /* Add type information to the mailbox header */ + proto_tree_add_uint(ecat_mailbox_header_tree, hf_ecat_mailboxtype, tvb, offset, 1, hdr.aControlUnion.v.Type); + + /* Add counter information to the mailbox header */ + proto_tree_add_uint(ecat_mailbox_header_tree, hf_ecat_mailboxcounter, tvb, offset, 1, hdr.aControlUnion.v.Counter); + offset++; + + if( mailbox_length >= ETHERCAT_MBOX_HEADER_LEN + hdr.Length ) + { + next_tvb = tvb_new_subset_length (tvb, offset, hdr.Length); + switch ( hdr.aControlUnion.v.Type ) + { + case ETHERCAT_MBOX_TYPE_ADS: + call_dissector(ams_handle, next_tvb, pinfo, ecat_mailbox_tree); + break; + + case ETHERCAT_MBOX_TYPE_EOE: + dissect_ecat_eoe(next_tvb, 0, pinfo, ecat_mailbox_tree); + break; + + case ETHERCAT_MBOX_TYPE_COE: + dissect_ecat_coe(next_tvb, 0, pinfo, ecat_mailbox_tree); + break; + + case ETHERCAT_MBOX_TYPE_FOE: + dissect_ecat_foe(next_tvb, 0, pinfo, ecat_mailbox_tree); + break; + + case ETHERCAT_MBOX_TYPE_SOE: + dissect_ecat_soe(next_tvb, 0, pinfo, ecat_mailbox_tree); + break; + + default: + proto_tree_add_item(ecat_mailbox_tree, hf_ecat_mailboxdata, tvb, offset, hdr.Length, ENC_NA); + } + } + else + { + anItem =proto_tree_add_item(ecat_mailbox_tree, hf_ecat_mailboxdata, tvb, offset, mailbox_length-ETHERCAT_MBOX_HEADER_LEN, ENC_NA); + expert_add_info_format(pinfo, anItem, &ei_ecat_mailbox_error,"Incorrect Mailbox data length(Expected:%d Actual:%d)", hdr.Length, mailbox_length-ETHERCAT_MBOX_HEADER_LEN); + } + col_append_str(pinfo->cinfo, COL_INFO, ")"); + } + return tvb_captured_length(tvb); +} + +void proto_register_ecat_mailbox(void) +{ + static const true_false_string flags_set_truth = + { + "Set", + "Not set" + }; + + static hf_register_info hf[] = + { + { &hf_ecat_mailboxlength, + { "Length", "ecat_mailbox.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailboxaddress, + { "Address", "ecat_mailbox.address", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailboxpriority, + { "Priority", "ecat_mailbox.priority", + FT_UINT8, BASE_DEC, NULL, 0x03, + NULL, HFILL } + }, + { &hf_ecat_mailboxtype, + { "Type", "ecat_mailbox.type", + FT_UINT8, BASE_DEC, VALS(EcMBoxType), 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailboxcounter, + { "Counter", "ecat_mailbox.counter", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe, + { "EoE Fragment", "ecat_mailbox.eoe", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_fraghead, + { "Header", "ecat_mailbox.eoe.fraghead", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_type, + { "Type", "ecat_mailbox.eoe.type", + FT_UINT32, BASE_DEC, VALS(EoEType), 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_fragno, + { "FragNo", "ecat_mailbox.eoe.fragno", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_offset, + { "Offset", "ecat_mailbox.eoe.offset", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { &hf_ecat_mailbox_eoe_frame, + { "FrameNo", "ecat_mailbox.eoe.frame", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_last, + { "Last Fragment", "ecat_mailbox.eoe.last", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_timestampapp, + { "Time Stamp Appended", "ecat_mailbox.eoe.timestampapp", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_timestampreq, + { "Time Stamp Requested", "ecat_mailbox.eoe.timestampreq", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_fragment, + { "EoE Frag Data", "ecat_mailbox.eoe.fragment", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init, + { "Init", "ecat_mailbox.eoe.init", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_contains_macaddr, + { "MacAddr", "ecat_mailbox.eoe.init.contains_macaddr", + FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x00000001, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_contains_ipaddr, + { "IpAddr", "ecat_mailbox.eoe.init.contains_ipaddr", + FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x00000002, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_contains_subnetmask, + { "SubnetMask", "ecat_mailbox.eoe.init.contains_subnetmask", + FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x00000004, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_contains_defaultgateway, + { "DefaultGateway", "ecat_mailbox.eoe.init.contains_defaultgateway", + FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x00000008, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_contains_dnsserver, + { "DnsServer", "ecat_mailbox.eoe.init.contains_dnsserver", + FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x00000010, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_contains_dnsname, + { "DnsName", "ecat_mailbox.eoe.init.contains_dnsname", + FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x00000020, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_append_timestamp, + { "AppendTimeStamp", "ecat_mailbox.eoe.init.append_timestamp", + FT_BOOLEAN, 32, TFS(&flags_set_truth), 0x00010000, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_macaddr, + { "Mac Addr", "ecat_mailbox.eoe.init.macaddr", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_ipaddr, + { "Ip Addr", "ecat_mailbox.eoe.init.ipaddr", + FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_subnetmask, + { "Subnet Mask", "ecat_mailbox.eoe.init.subnetmask", + FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_defaultgateway, + { "Default Gateway", "ecat_mailbox.eoe.init.defaultgateway", + FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_dnsserver, + { "Dns Server", "ecat_mailbox.eoe.init.dnsserver", + FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_init_dnsname, + { "Dns Name", "ecat_mailbox.eoe.init.dnsname", + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter, + { "Mac Filter", "ecat_mailbox.eoe.macfilter", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + + /* XXX: The following 3 fields may not be specified correctly */ + /* See related comment above */ + { &hf_ecat_mailbox_eoe_macfilter_macfiltercount, + { "Mac Filter Count", "ecat_mailbox.eoe.macfilter.macfiltercount", + FT_UINT16, BASE_DEC, NULL, 0xF000, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_maskcount, + { "Mac Filter Mask Count", "ecat_mailbox.eoe.macfilter.maskcount", + FT_UINT16, BASE_DEC, NULL, 0x0C00, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_nobroadcasts, + { "No Broadcasts", "ecat_mailbox.eoe.macfilter.nobroadcasts", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x0100, NULL, HFILL } + }, + /* ... */ + + { &hf_ecat_mailbox_eoe_macfilter_filter, + { "Filter", "ecat_mailbox.eoe.macfilter.filter", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[0], + { "Filter 0", "ecat_mailbox.eoe.macfilter.filter0", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[1], + { "Filter 1", "ecat_mailbox.eoe.macfilter.filter1", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[2], + { "Filter 2", "ecat_mailbox.eoe.macfilter.filter2", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[3], + { "Filter 3", "ecat_mailbox.eoe.macfilter.filter3", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[4], + { "Filter 4", "ecat_mailbox.eoe.macfilter.filter4", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[5], + { "Filter 5", "ecat_mailbox.eoe.macfilter.filter5", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[6], + { "Filter 6", "ecat_mailbox.eoe.macfilter.filter6", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[7], + { "Filter 7", "ecat_mailbox.eoe.macfilter.filter7", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[8], + { "Filter 8", "ecat_mailbox.eoe.macfilter.filter8", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[9], + { "Filter 9", "ecat_mailbox.eoe.macfilter.filter9", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[10], + { "Filter 10", "ecat_mailbox.eoe.macfilter.filter10", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[11], + { "Filter 11", "ecat_mailbox.eoe.macfilter.filter11", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[12], + { "Filter 12", "ecat_mailbox.eoe.macfilter.filter12", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[13], + { "Filter 13", "ecat_mailbox.eoe.macfilter.filter13", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[14], + { "Filter 14", "ecat_mailbox.eoe.macfilter.filter14", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filters[15], + { "Filter 15", "ecat_mailbox.eoe.macfilter.filter15", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filtermask, + { "Filter Mask", "ecat_mailbox.eoe.macfilter.filtermask", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filtermasks[0], + { "Mask 0", "ecat_mailbox.eoe.macfilter.filtermask0", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filtermasks[1], + { "Mask 1", "ecat_mailbox.eoe.macfilter.filtermask1", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filtermasks[2], + { "Mask 2", "ecat_mailbox.eoe.macfilter.filtermask2", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_macfilter_filtermasks[3], + { "Mask 3", "ecat_mailbox.eoe.macfilter.filtermask3", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_eoe_timestamp, + { "Time Stamp", "ecat_mailbox.eoe.timestamp", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_coe, + { "CoE", "ecat_mailbox.coe", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_number, + { "Number", "ecat_mailbox.coe.number", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_type, + { "Type", "ecat_mailbox.coe.type", + FT_UINT16, BASE_DEC, VALS(CANopenType), 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoreq, + { "SDO Req", "ecat_mailbox.coe.sdoreq", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsid, + { "Initiate Download", "ecat_mailbox.coe.sdoccsid", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsid_sizeind, + { "Size Ind.", "ecat_mailbox.coe.sdoccsid.sizeind", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x01, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsid_expedited, + { "Expedited", "ecat_mailbox.coe.sdoccsid.expedited", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x02, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsid_size0, + { "Bytes", "ecat_mailbox.coe.sdoccsid.size0", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x04, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsid_size1, + { "Bytes", "ecat_mailbox.coe.sdoccsid.size1", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x08, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsid_complete, + { "Access", "ecat_mailbox.coe.sdoccsid.complete", + FT_BOOLEAN, 8, TFS(&tfs_complete), 0x10, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsds, + { "Download Segment", "ecat_mailbox.coe.sdoccsds", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsds_lastseg, + { "Last Segment", "ecat_mailbox.coe.sdoccsds.lastseg", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x01, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsds_size, + { "Size", "ecat_mailbox.coe.sdoccsds.size", + FT_UINT8, BASE_DEC, NULL, 0x0E, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsds_toggle, + { "Toggle Bit", "ecat_mailbox.coe.sdoccsds.toggle", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x10, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsiu, + { "Init Upload", "ecat_mailbox.coe.sdoccsiu", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_ecat_mailbox_coe_sdoccsiu_complete, + { "Toggle Bit", "ecat_mailbox.coe.sdoccsiu.complete", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x10, + NULL, HFILL } + }, +#endif + { &hf_ecat_mailbox_coe_sdoccsus, + { "Upload Segment", "ecat_mailbox.coe.sdoccsus", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoccsus_toggle, + { "Toggle Bit", "ecat_mailbox.coe.sdoccsus_toggle", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x10, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoidx, + { "Index", "ecat_mailbox.coe.sdoidx", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoabortcode, + { "Abort code", "ecat_mailbox.coe.abortcode", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdosub, + { "SubIndex", "ecat_mailbox.coe.sdosub", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdodata, + { "Data", "ecat_mailbox.coe.sdodata", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdodata1, + { "Data", "ecat_mailbox.coe.sdodata", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdodata2, + { "Data", "ecat_mailbox.coe.sdodata", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoldata, + { "Data", "ecat_mailbox.coe.dsoldata", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdolength, + { "Length", "ecat_mailbox.coe.sdolength", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_ecat_mailbox_coe_sdoerror, + { "SDO Error", "ecat_mailbox.coe.sdoerror", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_ecat_mailbox_coe_sdores, + { "SDO Res", "ecat_mailbox.coe.sdores", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsiu, + { "Initiate Upload Response", "ecat_mailbox.coe.sdoscsiu", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsiu_sizeind, + { "Size Ind.", "ecat_mailbox.coe.sdoscsiu_sizeind", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x01, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsiu_expedited, + { "Expedited", "ecat_mailbox.coe.sdoscsiu_expedited", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x02, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsiu_size0, + { "Bytes", "ecat_mailbox.coe.sdoscsiu_size0", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x04, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsiu_size1, + { "Bytes", "ecat_mailbox.coe.sdoscsiu_size1", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x08, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsiu_complete, + { "Access", "ecat_mailbox.coe.sdoscsiu_complete", + FT_BOOLEAN, 8, TFS(&tfs_complete), 0x10, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsds, + { "Download Segment Response", "ecat_mailbox.coe.sdoscsds", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsds_toggle, + { "Toggle Bit", "ecat_mailbox.coe.sdoscsds_toggle", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x10, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsus, + { "Upload Segment", "ecat_mailbox.coe.sdoscsus", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsus_lastseg, + { "Last Segment", "ecat_mailbox.coe.sdoscsus_lastseg", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x01, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsus_bytes, + { "Bytes", "ecat_mailbox.coe.sdoscsus_bytes", + FT_UINT8, BASE_DEC, NULL, 0x0E, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoscsus_toggle, + { "Toggle Bit", "ecat_mailbox.coe.sdoscsus_toggle", + FT_BOOLEAN, 8, TFS(&flags_set_truth), 0x10, + NULL, HFILL } + }, + { &hf_ecat_mailbox_coe_sdoinfoopcode, + { "Info OpCode", "ecat_mailbox.coe.sdoinfoopcode", + FT_UINT8, BASE_DEC, VALS(CANopenSdoInfo), 0x0, + NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfofrag, + { "Info Frag Left", "ecat_mailbox.coe.sdoinfofrag", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfolisttype, + { "Info List Type", "ecat_mailbox.coe.sdoinfolisttype", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfolist, + { "Info List", "ecat_mailbox.coe.sdoinfolist", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfoindex, + { "Info Obj Index", "ecat_mailbox.coe.sdoinfoindex", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfosubindex, + { "Info Obj SubIdx", "ecat_mailbox.coe.sdoinfosubindex", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfovalueinfo, + { "Info Obj ValueInfo", "ecat_mailbox.coe.sdoinfovalueinfo", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfoerrorcode, + { "Info Error Code", "ecat_mailbox.coe.sdoinfoerrorcode", + FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfodatatype, + { "Info Data Type", "ecat_mailbox.coe.sdoinfodatatype", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfomaxsub, + { "Info Max SubIdx", "ecat_mailbox.coe.sdoinfomaxsub", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfoobjcode, + { "Info Obj Code", "ecat_mailbox.coe.sdoinfoobjcode", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfoname, + { "Info Name", "ecat_mailbox.coe.sdoinfoname", + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfobitlen, + { "Info Bit Len", "ecat_mailbox.coe.sdoinfobitlen", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfoobjaccess, + { "Info Obj Access", "ecat_mailbox.coe.sdoinfoobjaccess", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfounittype, + { "Info Data Type", "ecat_mailbox.coe.sdoinfounittype", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfodefaultvalue, + { "Info Default Val", "ecat_mailbox.coe.sdoinfodefaultvalue", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfominvalue, + { "Info Min Val", "ecat_mailbox.coe.sdoinfominvalue", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailbox_coe_sdoinfomaxvalue, + { "Info Max Val", "ecat_mailbox.coe.sdoinfomaxvalue", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }, + }, + { &hf_ecat_mailboxdata, + { "MB Data", "ecat_mailbox.data", + FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe, + { "Foe", "ecat_mailbox.foe", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_opmode, + { "Foe OpMode", "ecat_mailbox.foe_opmode", + FT_UINT8, BASE_HEX, VALS(FoEOpMode), 0x0, "Op modes", HFILL } + }, + { &hf_ecat_mailbox_foe_filelength, + { "Foe FileLength", "ecat_mailbox.foe_filelength", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_filename, + { "Foe FileName", "ecat_mailbox.foe_filename", + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_packetno, + { "Foe PacketNo", "ecat_mailbox.foe_packetno", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_errcode, + { "Foe ErrorCode", "ecat_mailbox.foe_errcode", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_errtext, + { "Foe ErrorString", "ecat_mailbox.foe_errtext", + FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_busydone, + { "Foe BusyDone", "ecat_mailbox.foe_busydone", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_busyentire, + { "Foe BusyEntire", "ecat_mailbox.foe_busyentire", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_data, + { "Foe Data", "ecat_mailbox.foe_busydata", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_efw, + { "Firmware", "ecat_mailbox.foe.efw", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_efw_cmd, + { "Cmd", "ecat_mailbox.foe.efw.cmd", + FT_UINT16, BASE_HEX, VALS(FoEEfwCmd), 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_efw_size, + { "Size", "ecat_mailbox.foe.efw.size", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_efw_addresslw, + { "AddressLW", "ecat_mailbox.foe.efw.addresslw", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_efw_addresshw, + { "AddressHW", "ecat_mailbox.foe.efw.addresshw", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_foe_efw_data, + { "Data", "ecat_mailbox.foe.efw.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe, + { "Soe", "ecat_mailbox.soe", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header, + { "Soe Header", "ecat_mailbox.soe_header", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_opcode, + { "SoE OpCode", "ecat_mailbox.soe_opcode", + FT_UINT16, BASE_DEC, VALS(SoeOpcode), 0x0007, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_incomplete, + { "More Follows...", "ecat_mailbox.soe_header_incomplete", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x0008, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_error, + { "Error", "ecat_mailbox.soe_header_error", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x0010, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_driveno, + { "Drive No", "ecat_mailbox.soe_header_driveno", + FT_UINT16, BASE_DEC, NULL, 0x00e0, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_datastate, + { "Datastate", "ecat_mailbox.soe_header_datastate", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x0100, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_name, + { "Name", "ecat_mailbox.soe_header_name", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x0200, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_attribute, + { "Attribute", "ecat_mailbox.soe_header_attribute", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x0400, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_unit, + { "Unit", "ecat_mailbox.soe_header_unit", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x0800, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_min, + { "Min", "ecat_mailbox.soe_header_min", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x1000, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_max, + { "Max", "ecat_mailbox.soe_header_max", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x2000, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_value, + { "Value", "ecat_mailbox.soe_header_value", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x4000, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_header_reserved, + { "Reserved", "ecat_mailbox.soe_header_reserved", + FT_BOOLEAN, 16, TFS(&flags_set_truth), 0x8000, + NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_idn, + { "SoE IDN", "ecat_mailbox.soe_idn", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_data, + { "SoE Data", "ecat_mailbox.soe_data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_frag, + { "SoE FragLeft", "ecat_mailbox.soe_frag", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_mailbox_soe_error, + { "SoE Error", "ecat_mailbox.soe_error", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + } + }; + + static gint *ett[] = + { + &ett_ecat_mailbox, + &ett_ecat_mailbox_eoe, + &ett_ecat_mailbox_eoe_init, + &ett_ecat_mailbox_eoe_macfilter, + &ett_ecat_mailbox_eoe_macfilter_filter, + &ett_ecat_mailbox_eoe_macfilter_filtermask, + &ett_ecat_mailbox_coe, + &ett_ecat_mailbox_sdo, + &ett_ecat_mailbox_coe_sdoccs, + &ett_ecat_mailbox_coe_sdoscs, + &ett_ecat_mailbox_foe, + &ett_ecat_mailbox_foe_efw, + &ett_ecat_mailbox_soeflag, + &ett_ecat_mailbox_soe, + &ett_ecat_mailbox_fraghead, + &ett_ecat_mailbox_header + }; + + static ei_register_info ei[] = + { + { &ei_ecat_mailbox_error, { "ecat_mailbox.invalid", PI_MALFORMED, PI_ERROR, "Malformed mailbox data", EXPFILL } }, + { &ei_ecat_mailbox_coe_error, { "ecat_mailbox.coe.invalid", PI_MALFORMED, PI_ERROR, "Malformed CoE data", EXPFILL } }, + { &ei_ecat_mailbox_foe_error, { "ecat_mailbox.foe.invalid", PI_MALFORMED, PI_ERROR, "Malformed FoE data", EXPFILL } }, + { &ei_ecat_mailbox_soe_error, { "ecat_mailbox.soe.invalid", PI_MALFORMED, PI_ERROR, "Malformed SoE data", EXPFILL } }, + { &ei_ecat_mailbox_eoe_error, { "ecat_mailbox.eoe.invalid", PI_MALFORMED, PI_ERROR, "Malformed EoE data", EXPFILL } }, + }; + + expert_module_t *expert_module; + + proto_ecat_mailbox = proto_register_protocol("EtherCAT Mailbox Protocol", + "ECAT_MAILBOX", "ecat_mailbox"); + + expert_module = expert_register_protocol(proto_ecat_mailbox); + expert_register_field_array(expert_module, ei, array_length(ei)); + + proto_register_field_array(proto_ecat_mailbox, hf,array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + ecat_mailbox_handle = register_dissector("ecat_mailbox", dissect_ecat_mailbox, proto_ecat_mailbox); +} + +void proto_reg_handoff_ecat_mailbox(void) +{ + /* Register this dissector as a sub dissector to E88A4 based on ether type. */ + dissector_add_uint("ecatf.type", 5, ecat_mailbox_handle); + + eth_handle = find_dissector_add_dependency("eth_withoutfcs", proto_ecat_mailbox); + ams_handle = find_dissector_add_dependency("ams", proto_ecat_mailbox); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 3 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=3 tabstop=8 expandtab: + * :indentSize=3:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/packet-ecatmb.h b/plugins/epan/ethercat/packet-ecatmb.h new file mode 100644 index 00000000..54dce708 --- /dev/null +++ b/plugins/epan/ethercat/packet-ecatmb.h @@ -0,0 +1,469 @@ +/* packet-ecatmb.h + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef _PACKET_ECATMAILBOX_H_ +#define _PACKET_ECATMAILBOX_H_ + +#include +DIAG_OFF_PEDANTIC + +/* Ensure the same data layout for all platforms */ + +typedef struct TETHERNET_ADDRESS +{ + guint8 b[6]; +} ETHERNET_ADDRESS, *PETHERNET_ADDRESS; +#define ETHERNET_ADDRESS_LEN ((int) sizeof(ETHERNET_ADDRESS)) + +/* Mailbox*/ +#define ETHERCAT_MBOX_TYPE_ADS 1 /* AMS/ADS header follows*/ +#define ETHERCAT_MBOX_TYPE_EOE 2 /* ETHERCAT_EOE_HEADER follows*/ +#define ETHERCAT_MBOX_TYPE_COE 3 /* ETHERCAT_COE_HEADER follows*/ +#define ETHERCAT_MBOX_TYPE_FOE 4 /* ETHERCAT_FOE_HEADER follows*/ +#define ETHERCAT_MBOX_TYPE_SOE 5 /* ETHERCAT_SOE_HEADER follows*/ + +typedef union tMbxHeaderControlUnion +{ + guint16 Control; + struct + { + guint16 Channel : 6; /* optional communication channels (default = 0)*/ + guint16 Priority : 2; /* optional communication priority (default = 0)*/ + guint16 Type : 4; /* TETHERCAT_MBOX_TYPE_xxx*/ + guint16 Counter : 3; /* 0 = counter not used (old version)*/ + guint16 Unsupported : 1; /* unsupported protocol detected*/ + } v; +} MbxHeaderControlUnion; + +typedef struct TETHERCAT_MBOX_HEADER +{ + guint16 Length; /* following bytes*/ + guint16 Address; /* S->M: phys addr of destination; M->S: phys addr of source; 0 = master*/ + MbxHeaderControlUnion aControlUnion; +} ETHERCAT_MBOX_HEADER, *PETHERCAT_MBOX_HEADER; + +#define ETHERCAT_MBOX_HEADER_LEN ((int) sizeof(ETHERCAT_MBOX_HEADER)) + +/* EoE*/ +#define ETHERNET_FRAMENO_MASK 0x0000000F + +#define EOE_TYPE_FRAME_FRAG 0 /* ETHERCAT_EOE_HEADER followed by frame fragment (ETHERCAT_EOE_TIMESTAMP may included) */ +#define EOE_TYPE_TIMESTAMP_RES 1 /* ETHERCAT_EOE_HEADER followed by ETHERCAT_EOE_TIMESTAMP */ +#define EOE_TYPE_INIT_REQ 2 /* ETHERCAT_EOE_HEADER followed by ETHERCAT_EOE_INIT */ +#define EOE_TYPE_INIT_RES 3 /* ETHERCAT_EOE_HEADER */ +#define EOE_TYPE_MACFILTER_REQ 4 /* ETHERCAT_EOE_HEADER followed by ETHERCAT_EOE_MACFILTER */ +#define EOE_TYPE_MACFILTER_RES 5 /* ETHERCAT_EOE_HEADER */ + +#define EOE_RESULT_NOERROR 0x0000 +#define EOE_RESULT_UNSPECIFIED_ERROR 0x0001 +#define EOE_RESULT_UNSUPPORTED_TYPE 0x0002 +#define EOE_RESULT_NO_IP_SUPPORT 0x0201 +#define EOE_RESULT_NO_MACFILTERMASK_SUPPORT 0x0401 + + +/*typedef struct TETHERCAT_EOE_INIT +{ + guint32 ContainsMacAddr :1; + guint32 ContainsIpAddr :1; + guint32 ContainsSubnetMask :1; + guint32 ContainsDefaultGateway :1; + guint32 ContainsDnsServer :1; + guint32 ContainsDnsName :1; + guint32 Reserved :26; + ETHERNET_ADDRESS MacAddr; + guint32 IpAddr; + guint32 SubnetMask; + guint32 DefaultGateway; + guint32 DnsServer; + char DnsName[32]; +} ETHERCAT_EOE_INIT, *PETHERCAT_EOE_INIT;*/ +#define ETHERCAT_EOE_INIT_LEN 58 /*sizeof(ETHERCAT_EOE_INIT)*/ + +typedef union tEoeMacFilterOptionsUnion +{ + struct + { + guint16 MacFilterCount :4; + guint16 MacFilterMaskCount :2; + guint16 Reserved1 :1; + guint16 NoBroadcasts :1; + guint16 Reserved2 :8; + } v; + guint16 Options; +} EoeMacFilterOptionsUnion; + +typedef struct TETHERCAT_EOE_MACFILTER +{ + EoeMacFilterOptionsUnion anEoeMacFilterOptionsUnion; + ETHERNET_ADDRESS MacFilter[16]; + ETHERNET_ADDRESS MacFilterMask[4]; +} ETHERCAT_EOE_MACFILTER; +#define ETHERCAT_EOE_MACFILTER_LEN ((int) sizeof(ETHERCAT_EOE_MACFILTER)) + +typedef struct TETHERCAT_EOE_TIMESTAMP +{ + guint32 TimeStamp; /* 32 bit time stamp */ +} ETHERCAT_EOE_TIMESTAMP; +#define ETHERCAT_EOE_TIMESTAMP_LEN ((int) sizeof(ETHERCAT_EOE_TIMESTAMP)) + +typedef union tEoeHeaderDataUnion +{ + struct + { /* EOE_TYPE_FRAME_FRAG and EOE_TYPE_TIMESTAMP_RES only */ + guint16 Fragment : 6; /* fragment number (EOE_TYPE_FRAME_FRAG only) */ + guint16 OffsetBuffer : 6; /* byte offset multiplied by 32 (if Fragment != 0) (EOE_TYPE_FRAME_FRAG only) */ + /* buffer size multiplied by 32 (if Fragment == 0) (EOE_TYPE_FRAME_FRAG only) */ + guint16 FrameNo : 4; /* frame number (EOE_TYPE_FRAME_FRAG and EOE_TYPE_TIMESTAMP_RES only) */ + } v; + guint16 Result; /* EOE_TYPE_INIT_RES and EOE_TYPE_MACFILTER_RES only */ +} EoeHeaderDataUnion; + +typedef union tEoeHeaderInfoUnion +{ + struct + { + guint16 Type : 4; /* specifies following data */ + guint16 PortAssign : 4; /* 0 = unspecified, 1 = port 1 */ + guint16 LastFragment : 1; /* TRUE if last fragment (EOE_TYPE_FRAME_FRAG only) */ + guint16 TimeStampAppended : 1; /* 32 bit time stamp appended (EOE_TYPE_FRAME_FRAG with LastFragment=1 only) */ + guint16 TimeStampRequested : 1; /* time stamp response requested (EOE_TYPE_FRAME_FRAG only) */ + guint16 Reserved : 5; + } v; + guint16 Info; +} EoeHeaderInfoUnion; + +typedef struct TETHERCAT_EOE_HEADER +{ + EoeHeaderInfoUnion anEoeHeaderInfoUnion; + EoeHeaderDataUnion anEoeHeaderDataUnion; +} ETHERCAT_EOE_HEADER, *PETHERCAT_EOE_HEADER; +#define ETHERCAT_EOE_HEADER_LEN ((int) sizeof(ETHERCAT_EOE_HEADER)) + +/* CANopen*/ +#define ETHERCAT_COE_TYPE_EMERGENCY 1 +#define ETHERCAT_COE_TYPE_SDOREQ 2 +#define ETHERCAT_COE_TYPE_SDORES 3 +#define ETHERCAT_COE_TYPE_TXPDO 4 +#define ETHERCAT_COE_TYPE_RXPDO 5 +#define ETHERCAT_COE_TYPE_TXPDO_RTR 6 /* Remote transmission request of TXPDO (master requested)*/ +#define ETHERCAT_COE_TYPE_RXPDO_RTR 7 /* Remote transmission request of RXPDO (slave requested) */ +#define ETHERCAT_COE_TYPE_SDOINFO 8 + +typedef union TETHERCAT_COE_HEADER +{ + struct + { + guint16 Number : 9; /* e.g. PDO number*/ + guint16 Reserved : 3; /* = 0*/ + guint16 Type : 4; /* CANopen type*/ + } v; + guint16 header; +} ETHERCAT_COE_HEADER, *PETHERCAT_COE_HEADER; +#define ETHERCAT_COE_HEADER_LEN ((int) sizeof(ETHERCAT_COE_HEADER)) + + +typedef union tSdoHeaderUnion +{ + struct + { /* Initiate Download Request*/ + guint8 SizeInd : 1; + guint8 Expedited : 1; + guint8 Size : 2; + guint8 Complete : 1; + guint8 Ccs : 3; /* = 1*/ + } Idq; + struct + { /* Initiate Download Response*/ + guint8 Reserved : 5; + guint8 Scs : 3; /* = 3*/ + } Ids; + struct + { /* Download Segment Request*/ + guint8 LastSeg : 1; + guint8 Size : 3; + guint8 Toggle : 1; + guint8 Ccs : 3; /* = 0*/ + } Dsq; + struct + { /* Download Segment Response*/ + guint8 Reserved : 4; + guint8 Toggle : 1; + guint8 Scs : 3; /* = 1*/ + } Dss; + struct + { /* Initiate Upload Request*/ + guint8 Reserved : 4; + guint8 Complete : 1; + guint8 Ccs : 3; /* = 2*/ + } Iuq; + struct + { /* Initiate Upload Response*/ + guint8 SizeInd : 1; + guint8 Expedited : 1; + guint8 Size : 2; + guint8 Complete : 1; + guint8 Scs : 3; /* = 2*/ + } Ius; + struct + { /* Upload Segment Request*/ + guint8 Reserved : 4; + guint8 Toggle : 1; + guint8 Ccs : 3; /* = 3*/ + } Usq; + struct + { /* Upload Segment Response*/ + guint8 LastSeg : 1; + guint8 Bytes : 3; + guint8 Toggle : 1; + guint8 Scs : 3; /* = 0*/ + } Uss; + struct + { /* Abort Transfer*/ + guint8 Reserved : 5; + guint8 Ccs : 3; /* = 4*/ + } Abt; + guint8 CS; +} SdoHeaderUnion; + +typedef struct TETHERCAT_SDO_HEADER +{ + SdoHeaderUnion anSdoHeaderUnion; + + guint16 Index; + guint8 SubIndex; + guint32 Data; +} ETHERCAT_SDO_HEADER, *PETHERCAT_SDO_HEADER; + +#define ETHERCAT_SDO_HEADER_LEN 8 /* sizeof(ETHERCAT_SDO_HEADER)*/ + +#define SDO_CCS_DOWNLOAD_SEGMENT 0 +#define SDO_CCS_INITIATE_DOWNLOAD 1 +#define SDO_CCS_INITIATE_UPLOAD 2 +#define SDO_CCS_UPLOAD_SEGMENT 3 +#define SDO_CCS_ABORT_TRANSFER 4 + +#define SDO_SCS_UPLOAD_SEGMENT 0 +#define SDO_SCS_DOWNLOAD_SEGMENT 1 +#define SDO_SCS_INITIATE_UPLOAD 2 +#define SDO_SCS_INITIATE_DOWNLOAD 3 + +/* CoE SDO Information */ +#define ECAT_COE_INFO_OPCODE_LIST_Q 1 +#define ECAT_COE_INFO_OPCODE_LIST_S 2 +#define ECAT_COE_INFO_OPCODE_OBJ_Q 3 +#define ECAT_COE_INFO_OPCODE_OBJ_S 4 +#define ECAT_COE_INFO_OPCODE_ENTRY_Q 5 +#define ECAT_COE_INFO_OPCODE_ENTRY_S 6 +#define ECAT_COE_INFO_OPCODE_ERROR_S 7 + +#define ECAT_COE_INFO_LIST_TYPE_LENGTH 0 +#define ECAT_COE_INFO_LIST_TYPE_ALL 1 +#define ECAT_COE_INFO_LIST_TYPE_PDOMAP 2 +#define ECAT_COE_INFO_LIST_TYPE_BACKUP 3 + +#define ECAT_COE_INFO_OBJCODE_NULL 0 +#define ECAT_COE_INFO_OBJCODE_DOMAIN 2 +#define ECAT_COE_INFO_OBJCODE_DEFTYPE 5 +#define ECAT_COE_INFO_OBJCODE_DEFSTRUCT 6 +#define ECAT_COE_INFO_OBJCODE_VAR 7 +#define ECAT_COE_INFO_OBJCODE_ARRAY 8 +#define ECAT_COE_INFO_OBJCODE_RECORD 9 + +#define ECAT_COE_INFO_OBJCAT_OPTIONAL 0 +#define ECAT_COE_INFO_OBJCAT_MANDATORY 1 + +#define ECAT_COE_INFO_OBJACCESS_RO 0x07 +#define ECAT_COE_INFO_OBJACCESS_RW 0x3f + +typedef struct TETHERCAT_SDO_INFO_LIST +{ + guint16 ListType; /* == SDO_INFO_LIST_TYPE_XXX */ + struct + { + guint16 Index[1]; + } Res; +} ETHERCAT_SDO_INFO_LIST; + +typedef struct TETHERCAT_SDO_INFO_OBJ +{ + guint16 Index; + struct + { + guint16 DataType; /* refer to data type index */ + guint8 MaxSubIndex; /* max subIndex */ + guint8 ObjCode; /* defined in DS 301 (Table 37)*/ + char Name[1]; /* rest of mailbox data*/ + } Res; +} ETHERCAT_SDO_INFO_OBJ; + +typedef struct TETHERCAT_SDO_INFO_ENTRY +{ + guint16 Index; + guint8 SubIdx; + guint8 ValueInfo; /* bit0 = ObjAccess, bit1 = ObjCategory, bit2 = PdoMapping, bit3 = UnitType + bit4 = DefaultValue, bit5 = MinValue, bit6 = MaxValue*/ + struct + { + guint16 DataType; /* refer to data type index */ + guint16 BitLen; + guint16 ObjAccess; /* bit0 = read; bit1 = write; bit2 = const. bit3 = 'PRE-OP'; bit4 = 'SAFE-OP'; bit5 = 'OP'.*/ + } Res; +} ETHERCAT_SDO_INFO_ENTRY; + +typedef struct TETHERCAT_SDO_INFO_ERROR +{ + guint32 ErrorCode; + char ErrorText[1]; /* rest of mailbox data */ +} ETHERCAT_SDO_INFO_ERROR; + +typedef union tSdoInfoUnion +{ + ETHERCAT_SDO_INFO_LIST List; + ETHERCAT_SDO_INFO_OBJ Obj; + ETHERCAT_SDO_INFO_ENTRY Entry; + ETHERCAT_SDO_INFO_ERROR Error; + guint8 Data[1]; +} SdoInfoUnion; + +typedef union tSdoControlUnion +{ + struct + { + guint8 OpCode : 7; /* == SDO_INFO_TYPE_XXX */ + guint8 InComplete : 1; + } v; + guint8 Control; +} SdoControlUnion; + +typedef struct TETHERCAT_SDO_INFO_HEADER +{ + SdoControlUnion anSdoControlUnion; + guint8 Reserved; /* == 0 */ + guint16 FragmentsLeft; + SdoInfoUnion anSdoInfoUnion; +} ETHERCAT_SDO_INFO_HEADER, *PETHERCAT_SDO_INFO_HEADER; + +#define ETHERCAT_SDO_INFO_LISTREQ_LEN 6 /*offsetof(ETHERCAT_SDO_INFO_HEADER, anSdoInfoUnion.List.Res)*/ + +/* FoE (File Access over EtherCAT)*/ +#define ECAT_FOE_OPMODE_RRQ 1 +#define ECAT_FOE_OPMODE_WRQ 2 +#define ECAT_FOE_OPMODE_DATA 3 +#define ECAT_FOE_OPMODE_ACK 4 +#define ECAT_FOE_OPMODE_ERR 5 +#define ECAT_FOE_OPMODE_BUSY 6 + +#define ECAT_FOE_ERRCODE_NOTDEFINED 0 +#define ECAT_FOE_ERRCODE_NOTFOUND 1 +#define ECAT_FOE_ERRCODE_ACCESS 2 +#define ECAT_FOE_ERRCODE_DISKFULL 3 +#define ECAT_FOE_ERRCODE_ILLEAGAL 4 +#define ECAT_FOE_ERRCODE_PACKENO 5 +#define ECAT_FOE_ERRCODE_EXISTS 6 +#define ECAT_FOE_ERRCODE_NOUSER 7 +#define ECAT_FOE_ERRCODE_BOOTSTRAPONLY 8 +#define ECAT_FOE_ERRCODE_NOTINBOOTSTRAP 9 + +typedef union tFoeHeaderDataUnion +{ + guint32 FileLength; /* (RRQ, WRQ) = 0 if unknown */ + struct + { + guint16 PacketNo; /* (DATA, ACK)*/ + guint16 Reserved2; /* (DATA, ACK)*/ + } v; + guint32 ErrorCode; /* (ERR)*/ + struct + { + guint16 Done; /* (BUSY)*/ + guint16 Entire; /* (BUSY)*/ + } v2; +} FoeHeaderDataUnion; + +typedef struct TETHERCAT_FOE_HEADER +{ + guint8 OpMode; /* = 1 (RRQ), = 2 (WRQ), = 3 (DATA), = 4 (ACK), = 5 (ERR), = 6 (BUSY) */ + guint8 Reserved1; /* = 0 */ + + FoeHeaderDataUnion aFoeHeaderDataUnion; + /* typedef union tMailBoxDataUnion + { + char Name[] (RRQ, WRQ) rest of mailbox data + guint8 Data[] (DATA) rest of mailbox data (if OpMode = 3) + char ErrorText[] (ERR) rest of mailbox data + } MailBoxDataUnion;*/ +} ETHERCAT_FOE_HEADER, *PETHERCAT_FOE_HEADER; +#define ETHERCAT_FOE_HEADER_LEN 6 /*sizeof(ETHERCAT_FOE_HEADER)*/ + +typedef struct +{ + guint16 Cmd; + guint16 Size; + guint16 AddressLW; + guint16 AddressHW; +} TEFWUPDATE_HEADER; + + +/* SoE (SOE over EtherCAT)*/ +#define ECAT_SOE_OPCODE_RRQ 1 +#define ECAT_SOE_OPCODE_RRS 2 +#define ECAT_SOE_OPCODE_WRQ 3 +#define ECAT_SOE_OPCODE_WRS 4 +#define ECAT_SOE_OPCODE_NFC 5 + + +typedef union tSoeHeaderControlUnion +{ + struct + { + guint8 OpCode : 3; /* 0 = unused, 1 = readReq, 2 = readRes, 3 = writeReq, 4 = writeRes + 5 = notification (command changed notification)*/ + guint8 InComplete : 1; /* more follows*/ + guint8 Error : 1; /* an error word follows */ + guint8 DriveNo : 3; /* drive number */ + + guint8 DataState : 1; /* follows or requested */ + guint8 Name : 1; /* follows or requested */ + guint8 Attribute : 1; /* follows or requested */ + guint8 Unit : 1; /* follows or requested */ + guint8 Min : 1; /* follows or requested */ + guint8 Max : 1; /* follows or requested */ + guint8 Value : 1; /* follows or requested */ + guint8 Reserved : 1; + } v; + struct + { + guint8 Control; + guint8 Element; + } v2; +} SoeHeaderControlUnion; + +typedef union tSoeHeaderDataUnion +{ + guint16 IDN; /* SOE IDN if (InComplete==0) */ + guint16 FragmentsLeft; /* Pending fragments if (InComplete==1) */ +} SoeHeaderDataUnion; + +typedef struct TETHERCAT_SOE_HEADER +{ + SoeHeaderControlUnion anSoeHeaderControlUnion; + SoeHeaderDataUnion anSoeHeaderDataUnion; + /* typedef union tMailBoxDataUnion + { + guint8 Data[] rest of mailbox data if (Error==0) + guint16 ErrorCode if (Error==1) + } MailBoxDataUnion;*/ +} ETHERCAT_SOE_HEADER, *PETHERCAT_SOE_HEADER; +#define ETHERCAT_SOE_HEADER_LEN ((int) sizeof(ETHERCAT_SOE_HEADER)) + +extern void init_mbx_header(PETHERCAT_MBOX_HEADER pMbox, tvbuff_t *tvb, gint offset); + +DIAG_ON_PEDANTIC +#endif /* _PACKET_ECATMAILBOX_H_ */ diff --git a/plugins/epan/ethercat/packet-esl.c b/plugins/epan/ethercat/packet-esl.c new file mode 100644 index 00000000..75f269b4 --- /dev/null +++ b/plugins/epan/ethercat/packet-esl.c @@ -0,0 +1,372 @@ +/* packet-esl.c + * Routines for EtherCAT Switch Link disassembly + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include + +void proto_register_esl(void); + +#if 0 +/* XXX: using bitfields is compiler dependent: See README.developer */ + +typedef union _EslFlagsUnion +{ + struct + { + guint16 port7 : 1; + guint16 port6 : 1; + guint16 port5 : 1; + guint16 port4 : 1; + guint16 port3 : 1; + guint16 port2 : 1; + guint16 port1 : 1; + guint16 port0 : 1; + guint16 extended : 1; + guint16 port11 : 1; + guint16 port10 : 1; + guint16 alignError : 1; + guint16 crcError : 1; + guint16 timeStampEna : 1; + guint16 port9 : 1; + guint16 port8 : 1; + }d; + struct + { + guint8 loPorts : 1; + guint8 flagsHiPorts : 1; + }lo_hi_flags; + guint flags; +} EslFlagsUnion; +#endif + +#define esl_port7_bitmask 0x0001 +#define esl_port6_bitmask 0x0002 +#define esl_port5_bitmask 0x0004 +#define esl_port4_bitmask 0x0008 +#define esl_port3_bitmask 0x0010 +#define esl_port2_bitmask 0x0020 +#define esl_port1_bitmask 0x0040 +#define esl_port0_bitmask 0x0080 +#define esl_extended_bitmask 0x0100 +#define esl_port11_bitmask 0x0200 +#define esl_port10_bitmask 0x0400 +#define esl_alignError_bitmask 0x0800 +#define esl_crcError_bitmask 0x1000 +#define esl_timeStampEna_bitmask 0x2000 +#define esl_port9_bitmask 0x4000 +#define esl_port8_bitmask 0x8000 + +#if 0 +typedef struct _EslHeader +{ + guint8 eslCookie[6]; /* 01 01 05 10 00 00 */ + EslFlagsUnion flags; + guint64 timeStamp; +} EslHeader, *PEslHeader; +#endif + + +#define SIZEOF_ESLHEADER 16 + +static dissector_handle_t eth_withoutfcs_handle; + +void proto_reg_handoff_esl(void); + +/* Define the esl proto */ +int proto_esl = -1; + +static int ett_esl = -1; + +static int hf_esl_timestamp = -1; +static int hf_esl_port = -1; +static int hf_esl_crcerror = -1; +static int hf_esl_alignerror = -1; + +/* Note: using external tfs strings apparently doesn't work in a plugin */ +static const true_false_string flags_yes_no = { + "yes", + "no" +}; + +#if 0 +/* XXX: using bitfields is compiler dependent: See README.developer */ +static guint16 flags_to_port(guint16 flagsValue) { + EslFlagsUnion flagsUnion; + flagsUnion.flags = flagsValue; + if ( flagsUnion.d.port0 ) + return 0; + else if ( flagsUnion.d.port1 ) + return 1; + else if ( flagsUnion.d.port2 ) + return 2; + else if ( flagsUnion.d.port3 ) + return 3; + else if ( flagsUnion.d.port4 ) + return 4; + else if ( flagsUnion.d.port5 ) + return 5; + else if ( flagsUnion.d.port6 ) + return 6; + else if ( flagsUnion.d.port7 ) + return 7; + else if ( flagsUnion.d.port8 ) + return 8; + else if ( flagsUnion.d.port9 ) + return 9; + + return -1; +} +#endif + +static guint16 flags_to_port(guint16 flagsValue) { + if ( (flagsValue & esl_port0_bitmask) != 0 ) + return 0; + else if ( (flagsValue & esl_port1_bitmask) != 0 ) + return 1; + else if ( (flagsValue & esl_port2_bitmask) != 0 ) + return 2; + else if ( (flagsValue & esl_port3_bitmask) != 0 ) + return 3; + else if ( (flagsValue & esl_port4_bitmask) != 0 ) + return 4; + else if ( (flagsValue & esl_port5_bitmask) != 0 ) + return 5; + else if ( (flagsValue & esl_port6_bitmask) != 0 ) + return 6; + else if ( (flagsValue & esl_port7_bitmask) != 0 ) + return 7; + else if ( (flagsValue & esl_port8_bitmask) != 0 ) + return 8; + else if ( (flagsValue & esl_port9_bitmask) != 0 ) + return 9; + else if ( (flagsValue & esl_port10_bitmask) != 0 ) + return 10; + else if ( (flagsValue & esl_port11_bitmask) != 0 ) + return 11; + + return -1; +} + +/*esl*/ +static int +dissect_esl_header(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) { + + proto_item *ti = NULL; + proto_tree *esl_header_tree; + gint offset = 0; + + guint esl_length = tvb_reported_length(tvb); + if ( esl_length >= SIZEOF_ESLHEADER ) + { + if (tree) + { + guint16 flags; + + ti = proto_tree_add_item(tree, proto_esl, tvb, 0, SIZEOF_ESLHEADER, ENC_NA); + esl_header_tree = proto_item_add_subtree(ti, ett_esl); + offset+=6; + + flags = tvb_get_letohs(tvb, offset); + proto_tree_add_uint(esl_header_tree, hf_esl_port, tvb, offset, 2, flags_to_port(flags)); + + proto_tree_add_item(esl_header_tree, hf_esl_alignerror, tvb, offset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(esl_header_tree, hf_esl_crcerror, tvb, offset, 2, ENC_LITTLE_ENDIAN); + + offset+=2; + + proto_tree_add_item(esl_header_tree, hf_esl_timestamp, tvb, offset, 8, ENC_LITTLE_ENDIAN); + } + } + return tvb_captured_length(tvb); +} + +typedef struct _ref_time_frame_info +{ + frame_data *fd; + guint64 esl_ts; + nstime_t abs_ts; + guint32 num; +} ref_time_frame_info; + +static ref_time_frame_info ref_time_frame; + +static gboolean is_esl_header(tvbuff_t *tvb, gint offset) +{ + return tvb_get_guint8(tvb, offset) == 0x01 && + tvb_get_guint8(tvb, offset+1) == 0x01 && + tvb_get_guint8(tvb, offset+2) == 0x05 && + (tvb_get_guint8(tvb, offset+3) == 0x10 ||tvb_get_guint8(tvb, offset+3) == 0x11)&& + tvb_get_guint8(tvb, offset+4) == 0x00 && + tvb_get_guint8(tvb, offset+5) == 0x00; +} + +static void modify_times(tvbuff_t *tvb, gint offset, packet_info *pinfo) +{ + if ( ref_time_frame.fd == NULL ) + { + ref_time_frame.esl_ts = tvb_get_letoh64(tvb, offset+8); + ref_time_frame.fd = pinfo->fd; + ref_time_frame.num = pinfo->num; + ref_time_frame.abs_ts = pinfo->abs_ts; + } + else if ( !pinfo->fd->visited ) + { + guint64 nsecs = tvb_get_letoh64(tvb, offset+8) - ref_time_frame.esl_ts; + guint64 secs = nsecs/1000000000; + nstime_t ts; + nstime_t ts_delta; + + ts.nsecs = ref_time_frame.abs_ts.nsecs + (int)(nsecs-(secs*1000000000)); + if ( ts.nsecs > 1000000000 ) + { + ts.nsecs-=1000000000; + secs++; + } + + ts.secs = ref_time_frame.abs_ts.secs+(int)secs; + nstime_delta(&ts_delta, &ts, &pinfo->abs_ts); + + pinfo->abs_ts = ts; + pinfo->fd->abs_ts = ts; + nstime_add(&pinfo->rel_ts, &ts_delta); + } +} + +static gboolean +dissect_esl_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + static gboolean in_heur = FALSE; + gboolean result; + tvbuff_t *next_tvb; + guint esl_length = tvb_captured_length(tvb); + + if ( in_heur ) + return FALSE; + + in_heur = TRUE; + /*TRY */ + { + if ( ref_time_frame.fd != NULL && !pinfo->fd->visited && pinfo->num <= ref_time_frame.num ) + ref_time_frame.fd = NULL; + + /* Check that there's enough data */ + if ( esl_length < SIZEOF_ESLHEADER ) + return FALSE; + + /* check for Esl frame, this has a unique destination MAC from Beckhoff range + First 6 bytes must be: 01 01 05 10 00 00 */ + if ( is_esl_header(tvb, 0) ) + { + dissect_esl_header(tvb, pinfo, tree, data); + if ( eth_withoutfcs_handle != NULL ) + { + next_tvb = tvb_new_subset_remaining(tvb, SIZEOF_ESLHEADER); + call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree); + } + modify_times(tvb, 0, pinfo); + result = TRUE; + } + else if ( is_esl_header(tvb, esl_length-SIZEOF_ESLHEADER) ) + { + if ( eth_withoutfcs_handle != NULL ) + { + next_tvb = tvb_new_subset_length(tvb, 0, esl_length-SIZEOF_ESLHEADER); + call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree); + } + next_tvb = tvb_new_subset_length(tvb, esl_length-SIZEOF_ESLHEADER, SIZEOF_ESLHEADER); + dissect_esl_header(next_tvb, pinfo, tree, data); + modify_times(tvb, esl_length-SIZEOF_ESLHEADER, pinfo); + + result = TRUE; + } + else + { + result = FALSE; + } + } + /*CATCH_ALL{ + in_heur = FALSE; + RETHROW; + }ENDTRY;*/ + in_heur = FALSE; + return result; +} + +void +proto_register_esl(void) { + static hf_register_info hf[] = { + { &hf_esl_port, + { "Port", "esl.port", + FT_UINT16, BASE_DEC, NULL, 0x00, + NULL, HFILL } + }, + { &hf_esl_crcerror, + { "Crc Error", "esl.crcerror", + FT_BOOLEAN, 16, TFS(&flags_yes_no), esl_crcError_bitmask, + NULL, HFILL } + }, + { &hf_esl_alignerror, + { "Alignment Error", "esl.alignerror", + FT_BOOLEAN, 16, TFS(&flags_yes_no), esl_alignError_bitmask, + NULL, HFILL } + }, + { &hf_esl_timestamp, + { "timestamp", "esl.timestamp", + FT_UINT64, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + }; + + static gint *ett[] = { + &ett_esl, + }; + + module_t *esl_module; + + proto_esl = proto_register_protocol("EtherCAT Switch Link", + "ESL","esl"); + + esl_module = prefs_register_protocol_obsolete(proto_esl); + + prefs_register_obsolete_preference(esl_module, "enable"); + + proto_register_field_array(proto_esl,hf,array_length(hf)); + proto_register_subtree_array(ett,array_length(ett)); + + register_dissector("esl", dissect_esl_header, proto_esl); +} + +void +proto_reg_handoff_esl(void) { + static gboolean initialized = FALSE; + + if (!initialized) { + eth_withoutfcs_handle = find_dissector_add_dependency("eth_withoutfcs", proto_esl); + heur_dissector_add("eth", dissect_esl_heur, "EtherCAT over Ethernet", "esl_eth", proto_esl, HEURISTIC_DISABLE); + initialized = TRUE; + } +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/packet-ethercat-datagram.c b/plugins/epan/ethercat/packet-ethercat-datagram.c new file mode 100644 index 00000000..6ba7c9e3 --- /dev/null +++ b/plugins/epan/ethercat/packet-ethercat-datagram.c @@ -0,0 +1,3745 @@ +/* packet-ethercat-datagram.c + * Routines for ethercat packet disassembly + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * https://download.beckhoff.com/download/document/io/ethercat-development-products/ethercat_esc_datasheet_sec1_technology_2i3.pdf + */ + +/* Include files */ + +#include "config.h" + +#include + +#include "packet-ethercat-datagram.h" +#include "packet-ecatmb.h" + +void proto_register_ecat(void); +void proto_reg_handoff_ecat(void); + +static heur_dissector_list_t heur_subdissector_list; +static dissector_handle_t ecat_handle; +static dissector_handle_t ecat_mailbox_handle; + +/* Define the EtherCAT proto */ +static int proto_ecat_datagram = -1; + +/* Define the tree for EtherCAT */ +static int ett_ecat = -1; +static int ett_ecat_header = -1; +static int ett_ecat_dc = -1; +static int ett_ecat_length = -1; +static int ett_ecat_padding = -1; +static int ett_ecat_datagram_subtree = -1; +static int ett_ecat_reg_esc_features = -1; +static int ett_ecat_reg_dlctrl1 = -1; +static int ett_ecat_reg_dlctrl2 = -1; +static int ett_ecat_reg_dlctrl3 = -1; +static int ett_ecat_reg_dlctrl4 = -1; +static int ett_ecat_reg_dlstatus1 = -1; +static int ett_ecat_reg_dlstatus2 = -1; +static int ett_ecat_reg_alctrl = -1; +static int ett_ecat_reg_alstatus = -1; +static int ett_ecat_reg_pdictrl1 = -1; +static int ett_ecat_reg_pdictrl2 = -1; +static int ett_ecat_reg_ecat_mask = -1; +static int ett_ecat_reg_pdiL = -1; +static int ett_ecat_reg_ecat = -1; +static int ett_ecat_reg_pdi1 = -1; +static int ett_ecat_reg_crc0 = -1; +static int ett_ecat_reg_crc1 = -1; +static int ett_ecat_reg_crc2 = -1; +static int ett_ecat_reg_crc3 = -1; +static int ett_ecat_reg_wd_status = -1; +static int ett_ecat_reg_eeprom_assign = -1; +static int ett_ecat_reg_ctrlstat = -1; +static int ett_ecat_reg_mio_ctrlstat = -1; +static int ett_ecat_mio_addr = -1; +static int ett_ecat_mio_access = -1; +static int ett_ecat_mio_status0 = -1; +static int ett_ecat_mio_status1 = -1; +static int ett_ecat_mio_status2 = -1; +static int ett_ecat_mio_status3 = -1; +static int ett_ecat_reg_fmmu = -1; +static int ett_ecat_reg_syncman = -1; +static int ett_ecat_reg_syncman_ctrlstatus = -1; +static int ett_ecat_reg_syncman_sm_enable = -1; +static int ett_ecat_reg_dc_cycunitctrl = -1; +static int ett_ecat_dc_activation = -1; +static int ett_ecat_dc_activationstat = -1; +static int ett_ecat_dc_sync0_status = -1; +static int ett_ecat_dc_sync1_status = -1; +static int ett_ecat_dc_latch0_ctrl = -1; +static int ett_ecat_dc_latch1_ctrl = -1; +static int ett_ecat_dc_latch0_status = -1; +static int ett_ecat_dc_latch1_status = -1; + +static int hf_ecat_sub; +static int hf_ecat_sub_data[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_cmd[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_idx[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_cnt[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_ado[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_adp[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_lad[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + +/* static int hf_ecat_header = -1; */ +static int hf_ecat_data = -1; +static int hf_ecat_cnt = -1; +static int hf_ecat_cmd = -1; +static int hf_ecat_idx = -1; +static int hf_ecat_adp = -1; +static int hf_ecat_ado = -1; +static int hf_ecat_lad = -1; +/* static int hf_ecat_len = -1; */ +static int hf_ecat_int = -1; + +static int hf_ecat_sub_dc_diff_da[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_dc_diff_bd[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_dc_diff_cb[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_dc_diff_cd[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_dc_diff_ba[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; +static int hf_ecat_sub_dc_diff_ca[10] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + +static int hf_ecat_dc_diff_da = -1; +static int hf_ecat_dc_diff_bd = -1; +static int hf_ecat_dc_diff_cb = -1; +static int hf_ecat_dc_diff_cd = -1; +static int hf_ecat_dc_diff_ba = -1; +static int hf_ecat_dc_diff_ca = -1; + +static int hf_ecat_length_len = -1; +static int hf_ecat_length_r = -1; +static int hf_ecat_length_c = -1; +static int hf_ecat_length_m = -1; + +static int hf_ecat_padding = -1; + +static int hf_ecat_reg_revision = -1; +static int hf_ecat_reg_esc_type = -1; +static int hf_ecat_reg_esc_build = -1; +static int hf_ecat_reg_esc_fmmucnt = -1; +static int hf_ecat_reg_esc_smcnt = -1; +static int hf_ecat_reg_esc_ports = -1; +static int hf_ecat_reg_esc_dpram = -1; +static int hf_ecat_reg_esc_features = -1; +static int hf_ecat_reg_esc_features_fmmurestrict = -1; +static int hf_ecat_reg_esc_features_smaddrrestrict = -1; +static int hf_ecat_reg_esc_features_dcsupport = -1; +static int hf_ecat_reg_esc_features_dc64support = -1; +static int hf_ecat_reg_esc_features_ebuslowjitter = -1; +static int hf_ecat_reg_esc_features_ebusextlinkdetect = -1; +static int hf_ecat_reg_esc_features_miiextlinkdetect = -1; +static int hf_ecat_reg_esc_features_crcext = -1; +static int hf_ecat_reg_physaddr = -1; +static int hf_ecat_reg_physaddr2 = -1; +static int hf_ecat_reg_dlctrl1 = -1; +static int hf_ecat_reg_dlctrl1_killnonecat = -1; +static int hf_ecat_reg_dlctrl1_port0extlinkdetect = -1; +static int hf_ecat_reg_dlctrl1_port1extlinkdetect = -1; +static int hf_ecat_reg_dlctrl1_port2extlinkdetect = -1; +static int hf_ecat_reg_dlctrl1_port3extlinkdetect = -1; +static int hf_ecat_reg_dlctrl2 = -1; +static int hf_ecat_reg_dlctrl2_port0 = -1; +static int hf_ecat_reg_dlctrl2_port1 = -1; +static int hf_ecat_reg_dlctrl2_port2 = -1; +static int hf_ecat_reg_dlctrl2_port3 = -1; +static int hf_ecat_reg_dlctrl3 = -1; +static int hf_ecat_reg_dlctrl3_fifosize = -1; +static int hf_ecat_reg_dlctrl3_lowebusjit = -1; +static int hf_ecat_reg_dlctrl4 = -1; +static int hf_ecat_reg_dlctrl4_2ndaddress = -1; +static int hf_ecat_reg_dlstatus1 = -1; +static int hf_ecat_reg_dlstatus1_operation = -1; +static int hf_ecat_reg_dlstatus1_pdiwatchdog = -1; +static int hf_ecat_reg_dlstatus1_enhlinkdetect = -1; +static int hf_ecat_reg_dlstatus1_physlink_port0 = -1; +static int hf_ecat_reg_dlstatus1_physlink_port1 = -1; +static int hf_ecat_reg_dlstatus1_physlink_port2 = -1; +static int hf_ecat_reg_dlstatus1_physlink_port3 = -1; +static int hf_ecat_reg_dlstatus2 = -1; +static int hf_ecat_reg_dlstatus2_port0 = -1; +static int hf_ecat_reg_dlstatus2_port1 = -1; +static int hf_ecat_reg_dlstatus2_port2 = -1; +static int hf_ecat_reg_dlstatus2_port3 = -1; +static int hf_ecat_reg_regprotect = -1; +static int hf_ecat_reg_accessprotect = -1; +static int hf_ecat_reg_resetecat = -1; +static int hf_ecat_reg_resetpdi = -1; +static int hf_ecat_reg_regphysrwoffs = -1; +static int hf_ecat_reg_alctrl = -1; +static int hf_ecat_reg_alctrl_ctrl = -1; +static int hf_ecat_reg_alctrl_errack = -1; +static int hf_ecat_reg_alctrl_id = -1; +static int hf_ecat_reg_alstatus = -1; +static int hf_ecat_reg_alstatus_status = -1; +static int hf_ecat_reg_alstatus_err = -1; +static int hf_ecat_reg_alstatus_id = -1; +static int hf_ecat_reg_pdictrl1 = -1; +static int hf_ecat_reg_pdictrl1_pdi = -1; +static int hf_ecat_reg_pdictrl2 = -1; +static int hf_ecat_reg_pdictrl2_devemul = -1; +static int hf_ecat_reg_pdictrl2_enhlnkdetect = -1; +static int hf_ecat_reg_pdictrl2_dcsyncout = -1; +static int hf_ecat_reg_pdictrl2_dcsyncin = -1; +static int hf_ecat_reg_pdictrl2_enhlnkdetect0 = -1; +static int hf_ecat_reg_pdictrl2_enhlnkdetect1 = -1; +static int hf_ecat_reg_pdictrl2_enhlnkdetect2 = -1; +static int hf_ecat_reg_pdictrl2_enhlnkdetect3 = -1; +static int hf_ecat_reg_alstatuscode = -1; +static int hf_ecat_reg_ecat_mask = -1; +static int hf_ecat_reg_ecat_mask_latchevt = -1; +static int hf_ecat_reg_ecat_mask_escstatevt = -1; +static int hf_ecat_reg_ecat_mask_alstatevt = -1; +static int hf_ecat_reg_ecat_mask_sm0irq = -1; +static int hf_ecat_reg_ecat_mask_sm1irq = -1; +static int hf_ecat_reg_ecat_mask_sm2irq = -1; +static int hf_ecat_reg_ecat_mask_sm3irq = -1; +static int hf_ecat_reg_ecat_mask_sm4irq = -1; +static int hf_ecat_reg_ecat_mask_sm5irq = -1; +static int hf_ecat_reg_ecat_mask_sm6irq = -1; +static int hf_ecat_reg_ecat_mask_sm7irq = -1; +static int hf_ecat_reg_pdiL = -1; +static int hf_ecat_reg_pdiL_alctrl = -1; +static int hf_ecat_reg_pdiL_latchin = -1; +static int hf_ecat_reg_pdiL_sync0 = -1; +static int hf_ecat_reg_pdiL_sync1 = -1; +static int hf_ecat_reg_pdiL_smchg = -1; +static int hf_ecat_reg_pdiL_eepromcmdpen = -1; +static int hf_ecat_reg_pdiL_sm0 = -1; +static int hf_ecat_reg_pdiL_sm1 = -1; +static int hf_ecat_reg_pdiL_sm2 = -1; +static int hf_ecat_reg_pdiL_sm3 = -1; +static int hf_ecat_reg_pdiL_sm4 = -1; +static int hf_ecat_reg_pdiL_sm5 = -1; +static int hf_ecat_reg_pdiL_sm6 = -1; +static int hf_ecat_reg_pdiL_sm7 = -1; +static int hf_ecat_reg_pdiH = -1; +static int hf_ecat_reg_ecat = -1; +static int hf_ecat_reg_ecat_latchevt = -1; +static int hf_ecat_reg_ecat_escstatevt = -1; +static int hf_ecat_reg_ecat_alstatevt = -1; +static int hf_ecat_reg_ecat_sm0irq = -1; +static int hf_ecat_reg_ecat_sm1irq = -1; +static int hf_ecat_reg_ecat_sm2irq = -1; +static int hf_ecat_reg_ecat_sm3irq = -1; +static int hf_ecat_reg_ecat_sm4irq = -1; +static int hf_ecat_reg_ecat_sm5irq = -1; +static int hf_ecat_reg_ecat_sm6irq = -1; +static int hf_ecat_reg_ecat_sm7irq = -1; +static int hf_ecat_reg_pdi1 = -1; +static int hf_ecat_reg_pdi1_alctrl = -1; +static int hf_ecat_reg_pdi1_latchin = -1; +static int hf_ecat_reg_pdi1_sync0 = -1; +static int hf_ecat_reg_pdi1_sync1 = -1; +static int hf_ecat_reg_pdi1_smchg = -1; +static int hf_ecat_reg_pdi1_eepromcmdpen = -1; +static int hf_ecat_reg_pdi1_sm0 = -1; +static int hf_ecat_reg_pdi1_sm1 = -1; +static int hf_ecat_reg_pdi1_sm2 = -1; +static int hf_ecat_reg_pdi1_sm3 = -1; +static int hf_ecat_reg_pdi1_sm4 = -1; +static int hf_ecat_reg_pdi1_sm5 = -1; +static int hf_ecat_reg_pdi1_sm6 = -1; +static int hf_ecat_reg_pdi1_sm7 = -1; +static int hf_ecat_reg_pdi2 = -1; +static int hf_ecat_reg_crc0 = -1; +static int hf_ecat_reg_crc0_frame = -1; +static int hf_ecat_reg_crc0_rx = -1; +static int hf_ecat_reg_crc1 = -1; +static int hf_ecat_reg_crc1_frame = -1; +static int hf_ecat_reg_crc1_rx = -1; +static int hf_ecat_reg_crc2 = -1; +static int hf_ecat_reg_crc2_frame = -1; +static int hf_ecat_reg_crc2_rx = -1; +static int hf_ecat_reg_crc3 = -1; +static int hf_ecat_reg_crc3_frame = -1; +static int hf_ecat_reg_crc3_rx = -1; +static int hf_ecat_reg_crc_fwd0 = -1; +static int hf_ecat_reg_crc_fwd1 = -1; +static int hf_ecat_reg_crc_fwd2 = -1; +static int hf_ecat_reg_crc_fwd3 = -1; +static int hf_ecat_reg_processuniterr = -1; +static int hf_ecat_reg_pdierr = -1; +static int hf_ecat_reg_linklost0 = -1; +static int hf_ecat_reg_linklost1 = -1; +static int hf_ecat_reg_linklost2 = -1; +static int hf_ecat_reg_linklost3 = -1; +static int hf_ecat_reg_wd_divisor = -1; +static int hf_ecat_reg_wd_timepdi = -1; +static int hf_ecat_reg_wd_timesm = -1; +static int hf_ecat_reg_wd_status = -1; +static int hf_ecat_reg_wd_status_pdwatchdog = -1; +static int hf_ecat_reg_wd_cntsm = -1; +static int hf_ecat_reg_wd_cntpdi = -1; +static int hf_ecat_reg_eeprom_assign = -1; +static int hf_ecat_reg_eeprom_assign_ctrl = -1; +static int hf_ecat_reg_eeprom_assign_pdiaccess = -1; +static int hf_ecat_reg_eeprom_assign_status = -1; +static int hf_ecat_reg_ctrlstat = -1; +static int hf_ecat_reg_ctrlstat_wraccess = -1; +static int hf_ecat_reg_ctrlstat_eepromemul = -1; +static int hf_ecat_reg_ctrlstat_8bacc = -1; +static int hf_ecat_reg_ctrlstat_2bacc = -1; +static int hf_ecat_reg_ctrlstat_rdacc = -1; +static int hf_ecat_reg_ctrlstat_wracc = -1; +static int hf_ecat_reg_ctrlstat_reloadacc = -1; +static int hf_ecat_reg_ctrlstat_crcerr = -1; +static int hf_ecat_reg_ctrlstat_lderr = -1; +static int hf_ecat_reg_ctrlstat_cmderr = -1; +static int hf_ecat_reg_ctrlstat_wrerr = -1; +static int hf_ecat_reg_ctrlstat_busy = -1; +static int hf_ecat_reg_addrl = -1; +static int hf_ecat_reg_addrh = -1; +static int hf_ecat_reg_data0 = -1; +static int hf_ecat_reg_data1 = -1; +static int hf_ecat_reg_data2 = -1; +static int hf_ecat_reg_data3 = -1; +static int hf_ecat_reg_mio_ctrlstat = -1; +static int hf_ecat_reg_mio_ctrlstat_wracc1 = -1; +static int hf_ecat_reg_mio_ctrlstat_offsphy = -1; +static int hf_ecat_reg_mio_ctrlstat_rdacc = -1; +static int hf_ecat_reg_mio_ctrlstat_wracc2 = -1; +static int hf_ecat_reg_mio_ctrlstat_wrerr = -1; +static int hf_ecat_reg_mio_ctrlstat_busy = -1; +static int hf_ecat_reg_mio_addr = -1; +static int hf_ecat_reg_mio_addr_phyaddr = -1; +static int hf_ecat_reg_mio_addr_mioaddr = -1; +static int hf_ecat_reg_mio_data = -1; +static int hf_ecat_reg_mio_access = -1; +static int hf_ecat_reg_mio_access_ecatacc = -1; +static int hf_ecat_reg_mio_access_pdiacc = -1; +static int hf_ecat_reg_mio_access_forcereset = -1; +static int hf_ecat_reg_mio_status0 = -1; +static int hf_ecat_reg_mio_status0_physlink = -1; +static int hf_ecat_reg_mio_status0_link = -1; +static int hf_ecat_reg_mio_status0_linkstatuserr = -1; +static int hf_ecat_reg_mio_status0_readerr = -1; +static int hf_ecat_reg_mio_status0_linkpartnererr = -1; +static int hf_ecat_reg_mio_status0_phycfgupdated = -1; +static int hf_ecat_reg_mio_status1 = -1; +static int hf_ecat_reg_mio_status1_physlink = -1; +static int hf_ecat_reg_mio_status1_link = -1; +static int hf_ecat_reg_mio_status1_linkstatuserr = -1; +static int hf_ecat_reg_mio_status1_readerr = -1; +static int hf_ecat_reg_mio_status1_linkpartnererr = -1; +static int hf_ecat_reg_mio_status1_phycfgupdated = -1; +static int hf_ecat_reg_mio_status2 = -1; +static int hf_ecat_reg_mio_status2_physlink = -1; +static int hf_ecat_reg_mio_status2_link = -1; +static int hf_ecat_reg_mio_status2_linkstatuserr = -1; +static int hf_ecat_reg_mio_status2_readerr = -1; +static int hf_ecat_reg_mio_status2_linkpartnererr = -1; +static int hf_ecat_reg_mio_status2_phycfgupdated = -1; +static int hf_ecat_reg_mio_status3 = -1; +static int hf_ecat_reg_mio_status3_physlink = -1; +static int hf_ecat_reg_mio_status3_link = -1; +static int hf_ecat_reg_mio_status3_linkstatuserr = -1; +static int hf_ecat_reg_mio_status3_readerr = -1; +static int hf_ecat_reg_mio_status3_linkpartnererr = -1; +static int hf_ecat_reg_mio_status3_phycfgupdated = -1; +static int hf_ecat_reg_fmmu = -1; +static int hf_ecat_reg_fmmu_lstart = -1; +static int hf_ecat_reg_fmmu_llen = -1; +static int hf_ecat_reg_fmmu_lstartbit = -1; +static int hf_ecat_reg_fmmu_lendbit = -1; +static int hf_ecat_reg_fmmu_pstart = -1; +static int hf_ecat_reg_fmmu_pstartbit = -1; +static int hf_ecat_reg_fmmu_type = -1; +static int hf_ecat_reg_fmmu_typeread = -1; +static int hf_ecat_reg_fmmu_typewrite = -1; +static int hf_ecat_reg_fmmu_activate = -1; +static int hf_ecat_reg_fmmu_activate0 = -1; +static int hf_ecat_reg_syncman_ctrlstatus = -1; +static int hf_ecat_reg_syncman_pmode = -1; +static int hf_ecat_reg_syncman_access = -1; +static int hf_ecat_reg_syncman_irq_ecat = -1; +static int hf_ecat_reg_syncman_irq_pdi = -1; +static int hf_ecat_reg_syncman_wdt = -1; +static int hf_ecat_reg_syncman_irq_write = -1; +static int hf_ecat_reg_syncman_irq_read = -1; +static int hf_ecat_reg_syncman_1bufstate = -1; +static int hf_ecat_reg_syncman_3bufstate = -1; +static int hf_ecat_reg_syncman_sm_enable = -1; +static int hf_ecat_reg_syncman_enable = -1; +static int hf_ecat_reg_syncman_repeatreq = -1; +static int hf_ecat_reg_syncman_latchsmchg_ecat = -1; +static int hf_ecat_reg_syncman_latchsmchg_pdi = -1; +static int hf_ecat_reg_syncman_deactivate = -1; +static int hf_ecat_reg_syncman_repeatack = -1; +static int hf_ecat_reg_syncman = -1; +static int hf_ecat_reg_syncman_start = -1; +static int hf_ecat_reg_syncman_len = -1; +static int hf_ecat_reg_dc_recv0 = -1; +static int hf_ecat_reg_dc_recv1 = -1; +static int hf_ecat_reg_dc_recv2 = -1; +static int hf_ecat_reg_dc_recv3 = -1; +static int hf_ecat_reg_dc_systime = -1; +static int hf_ecat_reg_dc_systimeL = -1; +static int hf_ecat_reg_dc_systimeH = -1; +static int hf_ecat_reg_dc_recvtime64 = -1; +static int hf_ecat_reg_dc_systimeoffs = -1; +static int hf_ecat_reg_dc_systimeoffsl = -1; +static int hf_ecat_reg_dc_systimeoffsh = -1; +static int hf_ecat_reg_dc_systimedelay = -1; +static int hf_ecat_reg_dc_ctrlerr = -1; +static int hf_ecat_reg_dc_speedstart = -1; +static int hf_ecat_reg_dc_speeddiff = -1; +static int hf_ecat_reg_dc_fltdepth_systimediff = -1; +static int hf_ecat_reg_dc_fltdepth_speedcnt = -1; +static int hf_ecat_reg_dc_cycunitctrl = -1; +static int hf_ecat_reg_dc_cycunitctrl_access_cyclic = -1; +static int hf_ecat_reg_dc_cycunitctrl_access_latch0 = -1; +static int hf_ecat_reg_dc_cycunitctrl_access_latch1 = -1; +static int hf_ecat_reg_dc_activation = -1; +static int hf_ecat_reg_dc_activation_enablecyclic = -1; +static int hf_ecat_reg_dc_activation_gen_sync0 = -1; +static int hf_ecat_reg_dc_activation_gen_sync1 = -1; +static int hf_ecat_reg_dc_activation_autoactivation = -1; +static int hf_ecat_reg_dc_activation_stimeext = -1; +static int hf_ecat_reg_dc_activation_stimecheck = -1; +static int hf_ecat_reg_dc_activation_hlfrange = -1; +static int hf_ecat_reg_dc_activation_dblrange = -1; +static int hf_ecat_reg_dc_cycimpuls = -1; +static int hf_ecat_reg_dc_activationstat = -1; +static int hf_ecat_reg_dc_activationstat_sync0pend = -1; +static int hf_ecat_reg_dc_activationstat_sync1pend = -1; +static int hf_ecat_reg_dc_activationstat_stimeoutofrange = -1; +static int hf_ecat_reg_dc_sync0_status = -1; +static int hf_ecat_reg_dc_sync0_status_triggered = -1; +static int hf_ecat_reg_dc_sync1_status = -1; +static int hf_ecat_reg_dc_sync1_status_triggered = -1; +static int hf_ecat_reg_dc_starttime0 = -1; +static int hf_ecat_reg_dc_starttime1 = -1; +static int hf_ecat_reg_dc_cyctime0 = -1; +static int hf_ecat_reg_dc_cyctime1 = -1; +static int hf_ecat_reg_dc_latch0_ctrl_pos = -1; +static int hf_ecat_reg_dc_latch0_ctrl_neg = -1; +static int hf_ecat_reg_dc_latch1_ctrl_pos = -1; +static int hf_ecat_reg_dc_latch1_ctrl_neg = -1; +static int hf_ecat_reg_dc_latch0_status_eventpos = -1; +static int hf_ecat_reg_dc_latch0_status_eventneg = -1; +static int hf_ecat_reg_dc_latch0_status_pinstate = -1; +static int hf_ecat_reg_dc_latch1_status_eventpos = -1; +static int hf_ecat_reg_dc_latch1_status_eventneg = -1; +static int hf_ecat_reg_dc_latch1_status_pinstate = -1; +static int hf_ecat_reg_dc_latch0_ctrl = -1; +static int hf_ecat_reg_dc_latch1_ctrl = -1; +static int hf_ecat_reg_dc_latch0_status = -1; +static int hf_ecat_reg_dc_latch1_status = -1; +static int hf_ecat_reg_dc_latch0_pos = -1; +static int hf_ecat_reg_dc_latch0_neg = -1; +static int hf_ecat_reg_dc_latch1_pos = -1; +static int hf_ecat_reg_dc_latch1_neg = -1; +static int hf_ecat_reg_dc_rcvsyncmanchg = -1; +static int hf_ecat_reg_dc_pdismstart = -1; +static int hf_ecat_reg_dc_pdismchg = -1; + + +static const value_string EcCmdShort[] = +{ + { 0, "NOP" }, + { 1, "APRD" }, + { 2, "APWR" }, + { 3, "APRW" }, + { 4, "FPRD" }, + { 5, "FPWR" }, + { 6, "FPRW" }, + { 7, "BRD" }, + { 8, "BWR" }, + { 9, "BRW" }, + { 10, "LRD" }, + { 11, "LWR" }, + { 12, "LRW" }, + { 13, "ARMW" }, + { 14, "FRMW" }, + { 255, "EXT" }, + { 0, NULL } +}; + +static const value_string EcCmdLong[] = +{ + { 0, "No operation" }, + { 1, "Auto Increment Physical Read" }, + { 2, "Auto Increment Physical Write" }, + { 3, "Auto Increment Physical ReadWrite" }, + { 4, "Configured address Physical Read" }, + { 5, "Configured address Physical Write" }, + { 6, "Configured address Physical ReadWrite" }, + { 7, "Broadcast Read" }, + { 8, "Broadcast Write" }, + { 9, "Broadcast ReadWrite" }, + { 10, "Logical Read" }, + { 11, "Logical Write" }, + { 12, "Logical ReadWrite" }, + { 13, "Auto Increment Physical Read Multiple Write" }, + { 14, "Configured Address Physical Read Multiple Write" }, + { 255, "EXT" }, + { 0, NULL } +}; + +static const value_string ecat_subframe_reserved_vals[] = +{ + { 0, "Valid"}, + { 0, NULL} +}; + +static const true_false_string tfs_ecat_subframe_circulating_vals = +{ + "Frame has circulated once", "Frame is not circulating" +}; + +static const true_false_string tfs_ecat_subframe_more_vals = +{ + "More EtherCAT datagrams will follow", "Last EtherCAT datagram" +}; + +static const true_false_string tfs_ecat_fmmu_typeread = +{ + "Read in use", "Read ignore" +}; + +static const true_false_string tfs_ecat_fmmu_typewrite = +{ + "Write in use", "Write ignore" +}; + +static const true_false_string tfs_local_true_false = +{ + "True", "False", +}; + +static const true_false_string tfs_local_disabled_enabled = +{ + "Enabled", "Disabled", +}; + +static const true_false_string tfs_local_disable_enable = +{ + "Enable", "Disable", +}; + +static const true_false_string tfs_esc_reg_watchdog = +{ + "Okay", "Run out", +}; + + +static const char* convertEcCmdToText(int cmd, const value_string ec_cmd[]) +{ + return val_to_str(cmd, ec_cmd, ""); +} + +#define ENDOF(p) ((p)+1) /* pointer to end of *p*/ + +typedef enum +{ + EC_CMD_TYPE_NOP = 0, + EC_CMD_TYPE_APRD = 1, + EC_CMD_TYPE_APWR = 2, + EC_CMD_TYPE_APRW = 3, + EC_CMD_TYPE_FPRD = 4, + EC_CMD_TYPE_FPWR = 5, + EC_CMD_TYPE_FPRW = 6, + EC_CMD_TYPE_BRD = 7, + EC_CMD_TYPE_BWR = 8, + EC_CMD_TYPE_BRW = 9, + EC_CMD_TYPE_LRD = 10, + EC_CMD_TYPE_LWR = 11, + EC_CMD_TYPE_LRW = 12, + EC_CMD_TYPE_ARMW = 13, + EC_CMD_TYPE_FRMW = 14, + EC_CMD_TYPE_EXT = 255 +} EC_CMD_TYPE; + +/* Esc Feature Reg 8 */ +static int * const ecat_esc_reg_8[] = { + &hf_ecat_reg_esc_features_fmmurestrict, + &hf_ecat_reg_esc_features_smaddrrestrict, + &hf_ecat_reg_esc_features_dcsupport, + &hf_ecat_reg_esc_features_dc64support, + &hf_ecat_reg_esc_features_ebuslowjitter, + &hf_ecat_reg_esc_features_ebusextlinkdetect, + &hf_ecat_reg_esc_features_miiextlinkdetect, + &hf_ecat_reg_esc_features_crcext, + NULL +}; + +/* Esc Status Reg 100 */ +static int * const ecat_esc_reg_100[] = +{ + &hf_ecat_reg_dlctrl1_killnonecat, + &hf_ecat_reg_dlctrl1_port0extlinkdetect, + &hf_ecat_reg_dlctrl1_port1extlinkdetect, + &hf_ecat_reg_dlctrl1_port2extlinkdetect, + &hf_ecat_reg_dlctrl1_port3extlinkdetect, + NULL +}; + +/* Esc Status Reg 101 */ +static const value_string vals_esc_reg_101[] = { + { 0, "Auto loop" }, + { 1, "Auto close only" }, + { 2, "Loop open" }, + { 3, "Loop closed" }, + { 0, NULL }, +}; + +static int * const ecat_esc_reg_101[] = +{ + &hf_ecat_reg_dlctrl2_port0, + &hf_ecat_reg_dlctrl2_port1, + &hf_ecat_reg_dlctrl2_port2, + &hf_ecat_reg_dlctrl2_port3, + NULL +}; + +static int * const ecat_esc_reg_102[] = { + &hf_ecat_reg_dlctrl3_fifosize, + &hf_ecat_reg_dlctrl3_lowebusjit, + NULL +}; + +static int * const ecat_esc_reg_103[] = { + &hf_ecat_reg_dlctrl4_2ndaddress, + NULL +}; + +/* Esc Status Reg 110 */ +static int * const ecat_esc_reg_110[] = +{ + &hf_ecat_reg_dlstatus1_operation, + &hf_ecat_reg_dlstatus1_pdiwatchdog, + &hf_ecat_reg_dlstatus1_enhlinkdetect, + &hf_ecat_reg_dlstatus1_physlink_port0, + &hf_ecat_reg_dlstatus1_physlink_port1, + &hf_ecat_reg_dlstatus1_physlink_port2, + &hf_ecat_reg_dlstatus1_physlink_port3, + NULL +}; + +/* Esc Status Reg 111 */ +static const value_string vals_esc_reg_111[] = { + { 0, "Loop open, no link" }, + { 1, "Loop closed, no link" }, + { 2, "Loop open, with link" }, + { 3, "Loop closed, with link" }, + { 0, NULL}, +}; + +static int * const ecat_esc_reg_111[] = +{ + &hf_ecat_reg_dlstatus2_port0, + &hf_ecat_reg_dlstatus2_port1, + &hf_ecat_reg_dlstatus2_port2, + &hf_ecat_reg_dlstatus2_port3, + NULL +}; + +static const value_string vals_esc_reg_120[] = { + { 1, "INIT" }, + { 2, "PREOP" }, + { 3, "BOOTSTRAP" }, + { 4, "SAFEOP" }, + { 8, "OP" }, + { 0, NULL}, +}; + +static int * const ecat_esc_reg_120[] = { + &hf_ecat_reg_alctrl_ctrl, + &hf_ecat_reg_alctrl_errack, + &hf_ecat_reg_alctrl_id, + NULL +}; + +static int * const ecat_esc_reg_130[] = { + &hf_ecat_reg_alstatus_status, + &hf_ecat_reg_alstatus_err, + &hf_ecat_reg_alstatus_id, + NULL +}; + +static const value_string vals_esc_reg_140[] = { + { 0, "None" }, + { 1, "4 bit dig. input" }, + { 2, "4 bit dig. output" }, + { 3, "2 bit dig. in/output" }, + { 4, "dig. in/output" }, + { 5, "SPI slave" }, + { 7, "EtherCAT bridge" }, + { 8, "16 bit uC (async)" }, + { 9, "8 bit uC (async)" }, + { 10, "16 bit uC (sync)" }, + { 11, "8 bit uC (sync)" }, + { 16, "32/0 bit dig. in/output" }, + { 17, "24/8 bit dig. in/output" }, + { 18, "16/16 bit dig. in/output" }, + { 19, "8/24 bit dig. in/output" }, + { 20, "0/32 bit dig. in/output" }, + { 128, "On chip bus" }, + { 0, NULL}, +}; + +static int * const ecat_esc_reg_140[] = { + &hf_ecat_reg_pdictrl1_pdi, + NULL +}; + +static int * const ecat_esc_reg_141[] = { + &hf_ecat_reg_pdictrl2_devemul, + &hf_ecat_reg_pdictrl2_enhlnkdetect, + &hf_ecat_reg_pdictrl2_dcsyncout, + &hf_ecat_reg_pdictrl2_dcsyncin, + &hf_ecat_reg_pdictrl2_enhlnkdetect0, + &hf_ecat_reg_pdictrl2_enhlnkdetect1, + &hf_ecat_reg_pdictrl2_enhlnkdetect2, + &hf_ecat_reg_pdictrl2_enhlnkdetect3, + NULL +}; + +static int * const ecat_esc_reg_200[] = { + &hf_ecat_reg_ecat_mask_latchevt, + &hf_ecat_reg_ecat_mask_escstatevt, + &hf_ecat_reg_ecat_mask_alstatevt, + &hf_ecat_reg_ecat_mask_sm0irq, + &hf_ecat_reg_ecat_mask_sm1irq, + &hf_ecat_reg_ecat_mask_sm2irq, + &hf_ecat_reg_ecat_mask_sm3irq, + &hf_ecat_reg_ecat_mask_sm4irq, + &hf_ecat_reg_ecat_mask_sm5irq, + &hf_ecat_reg_ecat_mask_sm6irq, + &hf_ecat_reg_ecat_mask_sm7irq, + NULL +}; + +static int * const ecat_esc_reg_204[] = { + &hf_ecat_reg_pdiL_alctrl, + &hf_ecat_reg_pdiL_latchin, + &hf_ecat_reg_pdiL_sync0, + &hf_ecat_reg_pdiL_sync1, + &hf_ecat_reg_pdiL_smchg, + &hf_ecat_reg_pdiL_eepromcmdpen, + &hf_ecat_reg_pdiL_sm0, + &hf_ecat_reg_pdiL_sm1, + &hf_ecat_reg_pdiL_sm2, + &hf_ecat_reg_pdiL_sm3, + &hf_ecat_reg_pdiL_sm4, + &hf_ecat_reg_pdiL_sm5, + &hf_ecat_reg_pdiL_sm6, + &hf_ecat_reg_pdiL_sm7, + NULL +}; + +static int * const ecat_esc_reg_210[] = { + &hf_ecat_reg_ecat_latchevt, + &hf_ecat_reg_ecat_escstatevt, + &hf_ecat_reg_ecat_alstatevt, + &hf_ecat_reg_ecat_sm0irq, + &hf_ecat_reg_ecat_sm1irq, + &hf_ecat_reg_ecat_sm2irq, + &hf_ecat_reg_ecat_sm3irq, + &hf_ecat_reg_ecat_sm4irq, + &hf_ecat_reg_ecat_sm5irq, + &hf_ecat_reg_ecat_sm6irq, + &hf_ecat_reg_ecat_sm7irq, + NULL +}; + +static int * const ecat_esc_reg_220[] = { + &hf_ecat_reg_pdi1_alctrl, + &hf_ecat_reg_pdi1_latchin, + &hf_ecat_reg_pdi1_sync0, + &hf_ecat_reg_pdi1_sync1, + &hf_ecat_reg_pdi1_smchg, + &hf_ecat_reg_pdi1_eepromcmdpen, + &hf_ecat_reg_pdi1_sm0, + &hf_ecat_reg_pdi1_sm1, + &hf_ecat_reg_pdi1_sm2, + &hf_ecat_reg_pdi1_sm3, + &hf_ecat_reg_pdi1_sm4, + &hf_ecat_reg_pdi1_sm5, + &hf_ecat_reg_pdi1_sm6, + &hf_ecat_reg_pdi1_sm7, + NULL +}; + +static int * const ecat_esc_reg_300[] = { + &hf_ecat_reg_crc0_frame, + &hf_ecat_reg_crc0_rx, + NULL +}; + +static int * const ecat_esc_reg_302[] = { + &hf_ecat_reg_crc1_frame, + &hf_ecat_reg_crc1_rx, + NULL +}; + +static int * const ecat_esc_reg_304[] = { + &hf_ecat_reg_crc2_frame, + &hf_ecat_reg_crc2_rx, + NULL +}; + +static int * const ecat_esc_reg_306[] = { + &hf_ecat_reg_crc3_frame, + &hf_ecat_reg_crc3_rx, + NULL +}; + +static int * const ecat_esc_reg_440[] = { + &hf_ecat_reg_wd_status_pdwatchdog, + NULL +}; + +static const true_false_string tfs_esc_reg_500_0 = { + "Local uC", "ECAT" +}; + +static const true_false_string tfs_esc_reg_500_1 = { + "Reset Bit 501.0 to 0", "Do not change Bit 501.0" +}; + +static int * const ecat_esc_reg_500[] = { + &hf_ecat_reg_eeprom_assign_ctrl, + &hf_ecat_reg_eeprom_assign_pdiaccess, + &hf_ecat_reg_eeprom_assign_status, + NULL +}; + +static const true_false_string tfs_esc_reg_502_5 = { + "PDI emulates EEPROM", "Normal operation" +}; + +static int * const ecat_esc_reg_502[] = { + &hf_ecat_reg_ctrlstat_wraccess, + &hf_ecat_reg_ctrlstat_eepromemul, + &hf_ecat_reg_ctrlstat_8bacc, + &hf_ecat_reg_ctrlstat_2bacc, + &hf_ecat_reg_ctrlstat_rdacc, + &hf_ecat_reg_ctrlstat_wracc, + &hf_ecat_reg_ctrlstat_reloadacc, + &hf_ecat_reg_ctrlstat_crcerr, + &hf_ecat_reg_ctrlstat_lderr, + &hf_ecat_reg_ctrlstat_cmderr, + &hf_ecat_reg_ctrlstat_wrerr, + &hf_ecat_reg_ctrlstat_busy, + NULL +}; + +static int * const ecat_esc_reg_510[] = { + &hf_ecat_reg_mio_ctrlstat_wracc1, + &hf_ecat_reg_mio_ctrlstat_offsphy, + &hf_ecat_reg_mio_ctrlstat_rdacc, + &hf_ecat_reg_mio_ctrlstat_wracc2, + &hf_ecat_reg_mio_ctrlstat_wrerr, + &hf_ecat_reg_mio_ctrlstat_busy, + NULL +}; + +static int * const ecat_esc_reg_512[] = { + &hf_ecat_reg_mio_addr_phyaddr, + &hf_ecat_reg_mio_addr_mioaddr, + NULL +}; + +static int * const ecat_esc_reg_516[] = { + &hf_ecat_reg_mio_access_ecatacc, + &hf_ecat_reg_mio_access_pdiacc, + &hf_ecat_reg_mio_access_forcereset, + NULL +}; + +static int * const ecat_esc_reg_518[] = { + &hf_ecat_reg_mio_status0_physlink, + &hf_ecat_reg_mio_status0_link, + &hf_ecat_reg_mio_status0_linkstatuserr, + &hf_ecat_reg_mio_status0_readerr, + &hf_ecat_reg_mio_status0_linkpartnererr, + &hf_ecat_reg_mio_status0_phycfgupdated, + NULL +}; + +static int * const ecat_esc_reg_519[] = { + &hf_ecat_reg_mio_status1_physlink, + &hf_ecat_reg_mio_status1_link, + &hf_ecat_reg_mio_status1_linkstatuserr, + &hf_ecat_reg_mio_status1_readerr, + &hf_ecat_reg_mio_status1_linkpartnererr, + &hf_ecat_reg_mio_status1_phycfgupdated, + NULL +}; + +static int * const ecat_esc_reg_51A[] = { + &hf_ecat_reg_mio_status2_physlink, + &hf_ecat_reg_mio_status2_link, + &hf_ecat_reg_mio_status2_linkstatuserr, + &hf_ecat_reg_mio_status2_readerr, + &hf_ecat_reg_mio_status2_linkpartnererr, + &hf_ecat_reg_mio_status2_phycfgupdated, + NULL +}; + +static int * const ecat_esc_reg_51B[] = { + &hf_ecat_reg_mio_status3_physlink, + &hf_ecat_reg_mio_status3_link, + &hf_ecat_reg_mio_status3_linkstatuserr, + &hf_ecat_reg_mio_status3_readerr, + &hf_ecat_reg_mio_status3_linkpartnererr, + &hf_ecat_reg_mio_status3_phycfgupdated, + NULL +}; + +static const true_false_string tfs_ecat_fmmu_activate = +{ + "activated", "deactivated" +}; + +static int ecat_reg_600(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item* item; + proto_tree* subtree; + + item = proto_tree_add_item(tree, hf_ecat_reg_fmmu, tvb, offset, 16, ENC_NA); + subtree = proto_item_add_subtree(item, ett_ecat_reg_fmmu); + + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_lstart, tvb, offset, 4, ENC_LITTLE_ENDIAN); + offset += 4; + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_llen, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_lstartbit, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_lendbit, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_pstart, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_pstartbit, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_type, tvb, offset, 1, ENC_NA); + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_typeread, tvb, offset, 1, ENC_NA); + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_typewrite, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_activate, tvb, offset, 1, ENC_NA); + proto_tree_add_item(subtree, hf_ecat_reg_fmmu_activate0, tvb, offset, 1, ENC_NA); + + return 16; +} + +static int ecat_reg_800(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item* item; + proto_tree* subtree; + + static int * const reg4[] = { + &hf_ecat_reg_syncman_pmode, + &hf_ecat_reg_syncman_access, + &hf_ecat_reg_syncman_irq_ecat, + &hf_ecat_reg_syncman_irq_pdi, + &hf_ecat_reg_syncman_wdt, + &hf_ecat_reg_syncman_irq_write, + &hf_ecat_reg_syncman_irq_read, + &hf_ecat_reg_syncman_1bufstate, + &hf_ecat_reg_syncman_3bufstate, + NULL + }; + static int * const reg6[] = { + &hf_ecat_reg_syncman_enable, + &hf_ecat_reg_syncman_repeatreq, + &hf_ecat_reg_syncman_latchsmchg_ecat, + &hf_ecat_reg_syncman_latchsmchg_pdi, + &hf_ecat_reg_syncman_deactivate, + &hf_ecat_reg_syncman_repeatack, + NULL + }; + + item = proto_tree_add_item(tree, hf_ecat_reg_syncman, tvb, offset, 8, ENC_NA); + subtree = proto_item_add_subtree(item, ett_ecat_reg_syncman); + + proto_tree_add_item(subtree, hf_ecat_reg_syncman_start, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_item(subtree, hf_ecat_reg_syncman_len, tvb, offset, 2, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_bitmask(subtree, tvb, offset, hf_ecat_reg_syncman_ctrlstatus, ett_ecat_reg_syncman_ctrlstatus, reg4, ENC_LITTLE_ENDIAN); + offset += 2; + proto_tree_add_bitmask(subtree, tvb, offset, hf_ecat_reg_syncman_sm_enable, ett_ecat_reg_syncman_sm_enable, reg6, ENC_LITTLE_ENDIAN); + + return 8; +} + +static const value_string vals_esc_reg_8041[] = { + { 0, "3 buffer" }, + { 2, "1 buffer" }, + { 3, "1 buffer direct" }, + { 0, NULL}, +}; + +static const value_string vals_esc_reg_8042[] = { + { 0, "Read" }, + { 1, "Write" }, + { 0, NULL}, +}; + +static const true_false_string tfs_esc_reg_8051 = { + "Written", "Read" +}; + +static const value_string vals_esc_reg_8052[] = { + { 0, "1. buffer" }, + { 1, "2. buffer" }, + { 2, "3. buffer" }, + { 3, "blocked (start)" }, + { 0, NULL}, +}; + + +static const true_false_string tfs_esc_reg_9801 = { + "PDI", "ECAT" +}; + +static int * const ecat_esc_reg_980[] = { + &hf_ecat_reg_dc_cycunitctrl_access_cyclic, + &hf_ecat_reg_dc_cycunitctrl_access_latch0, + &hf_ecat_reg_dc_cycunitctrl_access_latch1, + NULL +}; + +static int * const ecat_esc_reg_981[] = { + &hf_ecat_reg_dc_activation_enablecyclic, + &hf_ecat_reg_dc_activation_gen_sync0, + &hf_ecat_reg_dc_activation_gen_sync1, + &hf_ecat_reg_dc_activation_autoactivation, + &hf_ecat_reg_dc_activation_stimeext, + &hf_ecat_reg_dc_activation_stimecheck, + &hf_ecat_reg_dc_activation_hlfrange, + &hf_ecat_reg_dc_activation_dblrange, + NULL +}; + +static int * const ecat_esc_reg_984[] = { + &hf_ecat_reg_dc_activationstat_sync0pend, + &hf_ecat_reg_dc_activationstat_sync1pend, + &hf_ecat_reg_dc_activationstat_stimeoutofrange, + NULL +}; + +static int * const ecat_esc_reg_98e[] = { + &hf_ecat_reg_dc_sync0_status_triggered, + NULL +}; + +static int * const ecat_esc_reg_98f[] = { + &hf_ecat_reg_dc_sync1_status_triggered, + NULL +}; + +static const true_false_string tfs_esc_reg_9A8E1 = { + "Single event", "Continuous" +}; + +static int * const ecat_esc_reg_9a8[] = { + &hf_ecat_reg_dc_latch0_ctrl_pos, + &hf_ecat_reg_dc_latch0_ctrl_neg, + NULL +}; +static int * const ecat_esc_reg_9a9[] = { + &hf_ecat_reg_dc_latch1_ctrl_pos, + &hf_ecat_reg_dc_latch1_ctrl_neg, + NULL +}; + +static int * const ecat_esc_reg_9ae[] = { + &hf_ecat_reg_dc_latch0_status_eventpos, + &hf_ecat_reg_dc_latch0_status_eventneg, + &hf_ecat_reg_dc_latch0_status_pinstate, + NULL +}; +static int * const ecat_esc_reg_9af[] = { + &hf_ecat_reg_dc_latch1_status_eventpos, + &hf_ecat_reg_dc_latch1_status_eventneg, + &hf_ecat_reg_dc_latch1_status_pinstate, + NULL +}; + +typedef int register_dissect_func(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset); + +/* esc registers */ +typedef struct +{ + guint16 reg; + guint16 length; + guint16 repeat; + int* phf; + int* const *bitmask_info; + gint* pett; + register_dissect_func *dissect; +} ecat_esc_reg_info; + + +#define NO_SUBTREE_FILL NULL, NULL, NULL + +static ecat_esc_reg_info ecat_esc_registers [] = +{ + { 0x0000, 1, 1, &hf_ecat_reg_revision, NO_SUBTREE_FILL}, + { 0x0001, 1, 1, &hf_ecat_reg_esc_type, NO_SUBTREE_FILL}, + { 0x0002, 2, 1, &hf_ecat_reg_esc_build, NO_SUBTREE_FILL}, + { 0x0004, 1, 1, &hf_ecat_reg_esc_fmmucnt, NO_SUBTREE_FILL}, + { 0x0005, 1, 1, &hf_ecat_reg_esc_smcnt, NO_SUBTREE_FILL}, + { 0x0006, 1, 1, &hf_ecat_reg_esc_ports, NO_SUBTREE_FILL}, + { 0x0007, 1, 1, &hf_ecat_reg_esc_dpram, NO_SUBTREE_FILL}, + { 0x0008, 2, 1, &hf_ecat_reg_esc_features, ecat_esc_reg_8, &ett_ecat_reg_esc_features, NULL}, + { 0x0010, 2, 1, &hf_ecat_reg_physaddr, NO_SUBTREE_FILL}, + { 0x0012, 2, 1, &hf_ecat_reg_physaddr2, NO_SUBTREE_FILL}, + { 0x0020, 2, 1, &hf_ecat_reg_regprotect, NO_SUBTREE_FILL}, + { 0x0030, 2, 1, &hf_ecat_reg_accessprotect, NO_SUBTREE_FILL}, + { 0x0040, 1, 1, &hf_ecat_reg_resetecat, NO_SUBTREE_FILL}, + { 0x0041, 1, 1, &hf_ecat_reg_resetpdi, NO_SUBTREE_FILL}, + { 0x0100, 1, 1, &hf_ecat_reg_dlctrl1, ecat_esc_reg_100, &ett_ecat_reg_dlctrl1, NULL}, + { 0x0101, 1, 1, &hf_ecat_reg_dlctrl2, ecat_esc_reg_101, &ett_ecat_reg_dlctrl2, NULL}, + { 0x0102, 1, 1, &hf_ecat_reg_dlctrl3, ecat_esc_reg_102, &ett_ecat_reg_dlctrl3, NULL}, + { 0x0103, 1, 1, &hf_ecat_reg_dlctrl4, ecat_esc_reg_103, &ett_ecat_reg_dlctrl4, NULL}, + { 0x0108, 2, 1, &hf_ecat_reg_regphysrwoffs, NO_SUBTREE_FILL}, + { 0x0110, 1, 1, &hf_ecat_reg_dlstatus1, ecat_esc_reg_110, &ett_ecat_reg_dlstatus1, NULL}, + { 0x0111, 1, 1, &hf_ecat_reg_dlstatus2, ecat_esc_reg_111, &ett_ecat_reg_dlstatus2, NULL}, + { 0x0120, 2, 1, &hf_ecat_reg_alctrl, ecat_esc_reg_120, &ett_ecat_reg_alctrl, NULL}, + { 0x0130, 2, 1, &hf_ecat_reg_alstatus, ecat_esc_reg_130, &ett_ecat_reg_alstatus, NULL}, + { 0x0134, 2, 1, &hf_ecat_reg_alstatuscode, NO_SUBTREE_FILL}, + { 0x0140, 1, 1, &hf_ecat_reg_pdictrl1, ecat_esc_reg_140, &ett_ecat_reg_pdictrl1, NULL}, + { 0x0141, 1, 1, &hf_ecat_reg_pdictrl2, ecat_esc_reg_141, &ett_ecat_reg_pdictrl2, NULL}, + { 0x0200, 2, 1, &hf_ecat_reg_ecat_mask, ecat_esc_reg_200, &ett_ecat_reg_ecat_mask, NULL}, + { 0x0204, 2, 1, &hf_ecat_reg_pdiL, ecat_esc_reg_204, &ett_ecat_reg_pdiL, NULL}, + { 0x0206, 2, 1, &hf_ecat_reg_pdiH, NO_SUBTREE_FILL}, + { 0x0210, 2, 1, &hf_ecat_reg_ecat, ecat_esc_reg_210, &ett_ecat_reg_ecat, NULL}, + { 0x0220, 2, 1, &hf_ecat_reg_pdi1, ecat_esc_reg_220, &ett_ecat_reg_pdi1, NULL}, + { 0x0222, 2, 1, &hf_ecat_reg_pdi2, NO_SUBTREE_FILL}, + { 0x0300, 2, 1, &hf_ecat_reg_crc0, ecat_esc_reg_300, &ett_ecat_reg_crc0, NULL}, + { 0x0302, 2, 1, &hf_ecat_reg_crc1, ecat_esc_reg_302, &ett_ecat_reg_crc1, NULL}, + { 0x0304, 2, 1, &hf_ecat_reg_crc2, ecat_esc_reg_304, &ett_ecat_reg_crc2, NULL}, + { 0x0306, 2, 1, &hf_ecat_reg_crc3, ecat_esc_reg_306, &ett_ecat_reg_crc3, NULL}, + { 0x0308, 1, 1, &hf_ecat_reg_crc_fwd0, NO_SUBTREE_FILL}, + { 0x0309, 1, 1, &hf_ecat_reg_crc_fwd1, NO_SUBTREE_FILL}, + { 0x030A, 1, 1, &hf_ecat_reg_crc_fwd2, NO_SUBTREE_FILL}, + { 0x030B, 1, 1, &hf_ecat_reg_crc_fwd3, NO_SUBTREE_FILL}, + { 0x030C, 1, 1, &hf_ecat_reg_processuniterr, NO_SUBTREE_FILL}, + { 0x030D, 1, 1, &hf_ecat_reg_pdierr, NO_SUBTREE_FILL}, + { 0x0310, 1, 1, &hf_ecat_reg_linklost0, NO_SUBTREE_FILL}, + { 0x0311, 1, 1, &hf_ecat_reg_linklost1, NO_SUBTREE_FILL}, + { 0x0312, 1, 1, &hf_ecat_reg_linklost2, NO_SUBTREE_FILL}, + { 0x0313, 1, 1, &hf_ecat_reg_linklost3, NO_SUBTREE_FILL}, + { 0x0400, 2, 1, &hf_ecat_reg_wd_divisor, NO_SUBTREE_FILL}, + { 0x0410, 2, 1, &hf_ecat_reg_wd_timepdi, NO_SUBTREE_FILL}, + { 0x0420, 2, 1, &hf_ecat_reg_wd_timesm, NO_SUBTREE_FILL}, + { 0x0440, 1, 1, &hf_ecat_reg_wd_status, ecat_esc_reg_440, &ett_ecat_reg_wd_status, NULL}, + { 0x0442, 1, 1, &hf_ecat_reg_wd_cntsm, NO_SUBTREE_FILL}, + { 0x0443, 1, 1, &hf_ecat_reg_wd_cntpdi, NO_SUBTREE_FILL}, + { 0x0500, 2, 1, &hf_ecat_reg_eeprom_assign, ecat_esc_reg_500, &ett_ecat_reg_eeprom_assign, NULL}, + { 0x0502, 2, 1, &hf_ecat_reg_ctrlstat, ecat_esc_reg_502, &ett_ecat_reg_ctrlstat, NULL}, + { 0x0504, 2, 1, &hf_ecat_reg_addrl, NO_SUBTREE_FILL}, + { 0x0506, 2, 1, &hf_ecat_reg_addrh, NO_SUBTREE_FILL}, + { 0x0508, 2, 1, &hf_ecat_reg_data0, NO_SUBTREE_FILL}, + { 0x050a, 2, 1, &hf_ecat_reg_data1, NO_SUBTREE_FILL}, + { 0x050c, 2, 1, &hf_ecat_reg_data2, NO_SUBTREE_FILL}, + { 0x050e, 2, 1, &hf_ecat_reg_data3, NO_SUBTREE_FILL}, + { 0x0510, 2, 1, &hf_ecat_reg_mio_ctrlstat, ecat_esc_reg_510, &ett_ecat_reg_mio_ctrlstat, NULL}, + { 0x0512, 2, 1, &hf_ecat_reg_mio_addr, ecat_esc_reg_512, &ett_ecat_mio_addr, NULL}, + { 0x0514, 2, 1, &hf_ecat_reg_mio_data, NO_SUBTREE_FILL}, + { 0x0516, 2, 1, &hf_ecat_reg_mio_access, ecat_esc_reg_516, &ett_ecat_mio_access, NULL}, + { 0x0518, 1, 1, &hf_ecat_reg_mio_status0, ecat_esc_reg_518, &ett_ecat_mio_status0, NULL}, + { 0x0519, 1, 1, &hf_ecat_reg_mio_status1, ecat_esc_reg_519, &ett_ecat_mio_status1, NULL}, + { 0x051A, 1, 1, &hf_ecat_reg_mio_status2, ecat_esc_reg_51A, &ett_ecat_mio_status2, NULL}, + { 0x051B, 1, 1, &hf_ecat_reg_mio_status3, ecat_esc_reg_51B, &ett_ecat_mio_status3, NULL}, + { 0x0600, 16, 16, &hf_ecat_reg_fmmu, NULL, NULL, ecat_reg_600}, + { 0x0800, 8, 8, &hf_ecat_reg_syncman, NULL, NULL, ecat_reg_800}, + { 0x0900, 4, 1, &hf_ecat_reg_dc_recv0, NO_SUBTREE_FILL}, + { 0x0904, 4, 1, &hf_ecat_reg_dc_recv1, NO_SUBTREE_FILL}, + { 0x0908, 4, 1, &hf_ecat_reg_dc_recv2, NO_SUBTREE_FILL}, + { 0x090c, 4, 1, &hf_ecat_reg_dc_recv3, NO_SUBTREE_FILL}, + { 0x0910, 8, 1, &hf_ecat_reg_dc_systime, NO_SUBTREE_FILL}, + { 0x0910, 4, 1, &hf_ecat_reg_dc_systimeL, NO_SUBTREE_FILL}, + { 0x0914, 4, 1, &hf_ecat_reg_dc_systimeH, NO_SUBTREE_FILL}, + { 0x0918, 8, 1, &hf_ecat_reg_dc_recvtime64, NO_SUBTREE_FILL}, + { 0x0920, 8, 1, &hf_ecat_reg_dc_systimeoffs, NO_SUBTREE_FILL}, + { 0x0920, 4, 1, &hf_ecat_reg_dc_systimeoffsl, NO_SUBTREE_FILL}, + { 0x0924, 4, 1, &hf_ecat_reg_dc_systimeoffsh, NO_SUBTREE_FILL}, + { 0x0928, 4, 1, &hf_ecat_reg_dc_systimedelay, NO_SUBTREE_FILL}, + { 0x092c, 4, 1, &hf_ecat_reg_dc_ctrlerr, NO_SUBTREE_FILL}, + { 0x0930, 2, 1, &hf_ecat_reg_dc_speedstart, NO_SUBTREE_FILL}, + { 0x0932, 2, 1, &hf_ecat_reg_dc_speeddiff, NO_SUBTREE_FILL}, + { 0x0934, 1, 1, &hf_ecat_reg_dc_fltdepth_systimediff, NO_SUBTREE_FILL}, + { 0x0935, 1, 1, &hf_ecat_reg_dc_fltdepth_speedcnt, NO_SUBTREE_FILL}, + { 0x0980, 1, 1, &hf_ecat_reg_dc_cycunitctrl, ecat_esc_reg_980, &ett_ecat_reg_dc_cycunitctrl, NULL}, + { 0x0981, 1, 1, &hf_ecat_reg_dc_activation, ecat_esc_reg_981, &ett_ecat_dc_activation, NULL}, + { 0x0982, 2, 1, &hf_ecat_reg_dc_cycimpuls, NO_SUBTREE_FILL}, + { 0x0984, 1, 1, &hf_ecat_reg_dc_activationstat, ecat_esc_reg_984, &ett_ecat_dc_activationstat, NULL}, + { 0x098e, 1, 1, &hf_ecat_reg_dc_sync0_status, ecat_esc_reg_98e, &ett_ecat_dc_sync0_status, NULL}, + { 0x098f, 1, 1, &hf_ecat_reg_dc_sync1_status, ecat_esc_reg_98f, &ett_ecat_dc_sync1_status, NULL}, + { 0x0990, 8, 1, &hf_ecat_reg_dc_starttime0, NO_SUBTREE_FILL}, + { 0x0998, 8, 1, &hf_ecat_reg_dc_starttime1, NO_SUBTREE_FILL}, + { 0x09a0, 4, 1, &hf_ecat_reg_dc_cyctime0, NO_SUBTREE_FILL}, + { 0x09a4, 4, 1, &hf_ecat_reg_dc_cyctime1, NO_SUBTREE_FILL}, + { 0x09a8, 1, 1, &hf_ecat_reg_dc_latch0_ctrl, ecat_esc_reg_9a8, &ett_ecat_dc_latch0_ctrl, NULL}, + { 0x09a9, 1, 1, &hf_ecat_reg_dc_latch1_ctrl, ecat_esc_reg_9a9, &ett_ecat_dc_latch1_ctrl, NULL}, + { 0x09ae, 1, 1, &hf_ecat_reg_dc_latch0_status, ecat_esc_reg_9ae, &ett_ecat_dc_latch0_status, NULL}, + { 0x09af, 1, 1, &hf_ecat_reg_dc_latch1_status, ecat_esc_reg_9af, &ett_ecat_dc_latch1_status, NULL}, + { 0x09b0, 8, 1, &hf_ecat_reg_dc_latch0_pos, NO_SUBTREE_FILL}, + { 0x09b8, 8, 1, &hf_ecat_reg_dc_latch0_neg, NO_SUBTREE_FILL}, + { 0x09c0, 8, 1, &hf_ecat_reg_dc_latch1_pos, NO_SUBTREE_FILL}, + { 0x09c8, 8, 1, &hf_ecat_reg_dc_latch1_neg, NO_SUBTREE_FILL}, + { 0x09f0, 4, 1, &hf_ecat_reg_dc_rcvsyncmanchg, NO_SUBTREE_FILL}, + { 0x09f8, 4, 1, &hf_ecat_reg_dc_pdismstart, NO_SUBTREE_FILL}, + { 0x09fc, 4, 1, &hf_ecat_reg_dc_pdismchg, NO_SUBTREE_FILL}, + +}; + +/* esc dissector */ +static int dissect_esc_register(packet_info* pinfo, proto_tree *tree, tvbuff_t *tvb, gint offset, guint32 len, EcParserHDR* hdr, guint16 cnt) +{ + guint i; + gint r; + gint res = -1; + gint regOffset; + gint read = 0; + + if (len > 0 ) + { + switch ( hdr->cmd ) + { + case EC_CMD_TYPE_APRD: + case EC_CMD_TYPE_BRD: + case EC_CMD_TYPE_FPRD: + read = 1; + /* Fall through */ + case EC_CMD_TYPE_APWR: + case EC_CMD_TYPE_APRW: + case EC_CMD_TYPE_FPWR: + case EC_CMD_TYPE_FPRW: + case EC_CMD_TYPE_BWR: + case EC_CMD_TYPE_BRW: + case EC_CMD_TYPE_ARMW: + case EC_CMD_TYPE_FRMW: + for ( i=0; ianAddrUnion.a.ado + len< ecat_esc_registers[i].reg ) + break; + + regOffset = ecat_esc_registers[i].reg; + for ( r=0; r= hdr->anAddrUnion.a.ado && regOffset+ecat_esc_registers[i].length <= (guint16)(hdr->anAddrUnion.a.ado + len) ) + { + if ( cnt > 0 || !read ) + { + if (ecat_esc_registers[i].dissect != NULL) + { + ecat_esc_registers[i].dissect(pinfo, tree, tvb, offset+(regOffset-hdr->anAddrUnion.a.ado)); + } + else if (ecat_esc_registers[i].bitmask_info != NULL) + { + proto_tree_add_bitmask(tree, tvb, offset+(regOffset-hdr->anAddrUnion.a.ado), *ecat_esc_registers[i].phf, + *ecat_esc_registers[i].pett, ecat_esc_registers[i].bitmask_info, ENC_LITTLE_ENDIAN); + } + else + { + proto_tree_add_item(tree, *ecat_esc_registers[i].phf, tvb, offset+(regOffset-hdr->anAddrUnion.a.ado), ecat_esc_registers[i].length, ENC_LITTLE_ENDIAN); + } + } + res = 0; + } + regOffset+=ecat_esc_registers[i].length; + } + } + break; + } + } + + return res; +} +static void init_EcParserHDR(EcParserHDR* pHdr, tvbuff_t *tvb, gint offset) +{ + pHdr->cmd = tvb_get_guint8(tvb, offset++); + pHdr->idx = tvb_get_guint8(tvb, offset++); + pHdr->anAddrUnion.a.adp = tvb_get_letohs(tvb, offset); offset+=2; + pHdr->anAddrUnion.a.ado = tvb_get_letohs(tvb, offset); offset+=2; + pHdr->len = tvb_get_letohs(tvb, offset); offset+=2; + pHdr->intr = tvb_get_letohs(tvb, offset); +} + +static void init_dc_measure(guint32* pDC, tvbuff_t *tvb, gint offset) +{ + int i; + for ( i=0; i<4; i++ ) + { + pDC[i] = tvb_get_letohl(tvb, offset); + offset+=4; + } +} + +static guint16 get_wc(EcParserHDR* pHdr, tvbuff_t *tvb, gint offset) +{ + return tvb_get_letohs(tvb, offset+EcParserHDR_Len+(pHdr->len&0x07ff)); +} + +static guint16 get_cmd_len(EcParserHDR* pHdr) +{ + return (EcParserHDR_Len+(pHdr->len&0x07ff)+2); /*Header + data + wc*/ +} + + +static void EcSummaryFormater(guint32 datalength, tvbuff_t *tvb, gint offset, char *szText, gint nMax) +{ + guint nSub=0; + guint nLen=0; + guint8 nCmds[4]; + guint nLens[4]; + EcParserHDR ecFirst; + EcParserHDR ecParser; + + guint suboffset=0; + + init_EcParserHDR(&ecFirst, tvb, offset); + + while ( suboffset < datalength ) + { + PEcParserHDR pEcParser; + if ( nSub > 0 ) + { + init_EcParserHDR(&ecParser, tvb, offset+suboffset); + pEcParser = &ecParser; + } + else + pEcParser = &ecFirst; + + if ( nSub < 4 ) + { + nCmds[nSub] = pEcParser->cmd; + nLens[nSub] = pEcParser->len&0x07ff; + } + nSub++; + nLen += (pEcParser->len&0x07ff); + /* bit 14 -- roundtrip */ + + if ( (pEcParser->len&0x8000) == 0 ) + break; + + suboffset+=get_cmd_len(pEcParser); + } + if ( nSub == 1 ) + { + guint16 len = ecFirst.len&0x07ff; + guint16 cnt = get_wc(&ecFirst, tvb, offset); + snprintf ( szText, nMax, "'%s': Len: %d, Adp 0x%x, Ado 0x%x, Wc %d ", + convertEcCmdToText(ecFirst.cmd, EcCmdShort), len, ecFirst.anAddrUnion.a.adp, ecFirst.anAddrUnion.a.ado, cnt ); + } + else if ( nSub == 2 ) + { + snprintf ( szText, nMax, "%d Cmds, '%s': len %d, '%s': len %d ", + nSub, convertEcCmdToText(nCmds[0], EcCmdShort), nLens[0], convertEcCmdToText(nCmds[1], EcCmdShort), nLens[1]); + } + else if ( nSub == 3 ) + { + snprintf ( szText, nMax, "%d Cmds, '%s': len %d, '%s': len %d, '%s': len %d", + nSub, convertEcCmdToText(nCmds[0], EcCmdShort), nLens[0], convertEcCmdToText(nCmds[1], EcCmdShort), nLens[1], convertEcCmdToText(nCmds[2], EcCmdShort), nLens[2]); + } + else if ( nSub == 4 ) + { + snprintf ( szText, nMax, "%d Cmds, '%s': len %d, '%s': len %d, '%s': len %d, '%s': len %d", + nSub, convertEcCmdToText(nCmds[0], EcCmdShort), nLens[0], convertEcCmdToText(nCmds[1], EcCmdShort), nLens[1], convertEcCmdToText(nCmds[2], EcCmdShort), nLens[2], convertEcCmdToText(nCmds[3], EcCmdShort), nLens[3]); + } + else + snprintf ( szText, nMax, "%d Cmds, SumLen %d, '%s'... ", + nSub, nLen, convertEcCmdToText(ecFirst.cmd, EcCmdShort)); +} + +static void EcCmdFormatter(guint8 cmd, char *szText, gint nMax) +{ + gint idx=0; + const gchar *szCmd = try_val_to_str_idx((guint32)cmd, EcCmdLong, &idx); + + if ( idx != -1 ) + snprintf(szText, nMax, "Cmd : %d (%s)", cmd, szCmd); + else + snprintf(szText, nMax, "Cmd : %d (Unknown command)", cmd); +} + + +static void EcSubFormatter(tvbuff_t *tvb, gint offset, char *szText, gint nMax) +{ + EcParserHDR ecParser; + guint16 len, cnt; + + init_EcParserHDR(&ecParser, tvb, offset); + len = ecParser.len&0x07ff; + cnt = get_wc(&ecParser, tvb, offset); + + switch ( ecParser.cmd ) + { + case EC_CMD_TYPE_NOP: + case EC_CMD_TYPE_APRD: + case EC_CMD_TYPE_APWR: + case EC_CMD_TYPE_APRW: + case EC_CMD_TYPE_FPRD: + case EC_CMD_TYPE_FPWR: + case EC_CMD_TYPE_FPRW: + case EC_CMD_TYPE_BRD: + case EC_CMD_TYPE_BWR: + case EC_CMD_TYPE_BRW: + case EC_CMD_TYPE_ARMW: + case EC_CMD_TYPE_FRMW: + snprintf ( szText, nMax, "EtherCAT datagram: Cmd: '%s' (%d), Len: %d, Adp 0x%x, Ado 0x%x, Cnt %d", + convertEcCmdToText(ecParser.cmd, EcCmdShort), ecParser.cmd, len, ecParser.anAddrUnion.a.adp, ecParser.anAddrUnion.a.ado, cnt); + break; + case EC_CMD_TYPE_LRD: + case EC_CMD_TYPE_LWR: + case EC_CMD_TYPE_LRW: + snprintf ( szText, nMax, "EtherCAT datagram: Cmd: '%s' (%d), Len: %d, Addr 0x%x, Cnt %d", + convertEcCmdToText(ecParser.cmd, EcCmdShort), ecParser.cmd, len, ecParser.anAddrUnion.addr, cnt); + break; + case EC_CMD_TYPE_EXT: + snprintf ( szText, nMax, "EtherCAT datagram: Cmd: 'EXT' (%d), Len: %d", ecParser.cmd, len); + break; + default: + snprintf ( szText, nMax, "EtherCAT datagram: Cmd: 'Unknown' (%d), Len: %d", ecParser.cmd, len); + } +} + +/* Ethercat Datagram */ +static int dissect_ecat_datagram(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + tvbuff_t *next_tvb; + proto_item *ti, *aitem = NULL; + proto_tree *ecat_datagrams_tree = NULL; + guint offset = 0; + char szText[200]; + int nMax = sizeof(szText)-1; + + guint ecLength=0; + guint subCount = 0; + const guint datagram_length = tvb_captured_length(tvb); + guint datagram_padding_bytes = 0; + EcParserHDR ecHdr; + heur_dtbl_entry_t *hdtbl_entry; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "ECAT"); + + col_clear(pinfo->cinfo, COL_INFO); + + /* If the data portion of an EtherCAT datagram is less than 44 bytes, then + it must have been padded with an additional n number of bytes to reach a + total Ethernet frame length of 64 bytes (Ethernet header + Ethernet Data + + FCS). Hence at least 44 bytes data shall always be available in any + EtherCAT datagram. */ + /* tvb_ensure_bytes_exist(tvb, offset, 44); + this is not correct, because the frame might have been captured before the + os added the padding bytes. E.g. in Windows the frames are captured on the + protocol layer. When another protocol driver sends a frame this frame does + not include the padding bytes. + */ + + /* Count the length of the individual EtherCAT datagrams (sub datagrams) + that are part of this EtherCAT frame. Stop counting when the current + sub datagram header tells that there are no more sub datagrams or when + there is no more data available in the PDU. */ + do + { + init_EcParserHDR(&ecHdr, tvb, ecLength); + ecLength += get_cmd_len(&ecHdr); + } while ((ecLength < datagram_length) && + (ecHdr.len & 0x8000)); + + /* Calculate the amount of padding data available in the PDU */ + datagram_padding_bytes = datagram_length - ecLength; + + EcSummaryFormater(ecLength, tvb, offset, szText, nMax); + col_append_str(pinfo->cinfo, COL_INFO, szText); + + if( tree ) + { + /* Create the EtherCAT datagram(s) subtree */ + ti = proto_tree_add_item(tree, proto_ecat_datagram, tvb, 0, -1, ENC_NA); + ecat_datagrams_tree = proto_item_add_subtree(ti, ett_ecat); + + proto_item_append_text(ti,": %s", szText); + } + + /* Dissect all sub frames of this EtherCAT PDU */ + do + { + proto_tree *ecat_datagram_tree = NULL, *ecat_header_tree = NULL, *ecat_dc_tree = NULL; + + proto_item *hidden_item; + guint32 subsize; + guint32 suboffset; + guint32 len; + guint16 cnt; + ETHERCAT_MBOX_HEADER mbox; + + suboffset = offset; + init_EcParserHDR(&ecHdr, tvb, suboffset); + + subsize = get_cmd_len(&ecHdr); + len = ecHdr.len & 0x07ff; + cnt = get_wc(&ecHdr, tvb, suboffset); + + if( tree ) + { + /* Create the sub tree for the current datagram */ + EcSubFormatter(tvb, suboffset, szText, nMax); + ecat_datagram_tree = proto_tree_add_subtree(ecat_datagrams_tree, tvb, suboffset, subsize, ett_ecat_datagram_subtree, NULL, szText); + + /* Create a subtree placeholder for the Header */ + ecat_header_tree = proto_tree_add_subtree(ecat_datagram_tree, tvb, offset, EcParserHDR_Len, ett_ecat_header, NULL, "Header"); + + EcCmdFormatter(ecHdr.cmd, szText, nMax); + aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_cmd, tvb, suboffset, 1, ENC_LITTLE_ENDIAN); + proto_item_set_text(aitem, "%s", szText); + if( subCount < 10 ){ + aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_cmd[subCount], tvb, suboffset, 1, ENC_LITTLE_ENDIAN); + proto_item_set_hidden(aitem); + } + suboffset+=1; + + proto_tree_add_item(ecat_header_tree, hf_ecat_idx, tvb, suboffset, 1, ENC_LITTLE_ENDIAN); + if( subCount < 10 ){ + aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_idx[subCount], tvb, suboffset, 1, ENC_LITTLE_ENDIAN); + proto_item_set_hidden(aitem); + } + suboffset+=1; + + switch ( ecHdr.cmd ) + { + case 10: + case 11: + case 12: + proto_tree_add_item(ecat_header_tree, hf_ecat_lad, tvb, suboffset, 4, ENC_LITTLE_ENDIAN); + if( subCount < 10 ){ + aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_lad[subCount], tvb, suboffset, 4, ENC_LITTLE_ENDIAN); + proto_item_set_hidden(aitem); + } + + suboffset+=4; + break; + default: + proto_tree_add_item(ecat_header_tree, hf_ecat_adp, tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + if( subCount < 10 ){ + aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_adp[subCount], tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + proto_item_set_hidden(aitem); + } + + suboffset+=2; + proto_tree_add_item(ecat_header_tree, hf_ecat_ado, tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + if( subCount < 10 ){ + aitem = proto_tree_add_item(ecat_header_tree, hf_ecat_sub_ado[subCount], tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + proto_item_set_hidden(aitem); + } + + suboffset+=2; + } + + { + proto_tree *length_sub_tree; + + /* Add information about the length field (11 bit length, 3 bits + reserved, 1 bit circulating frame and 1 bit more in a sub tree */ + length_sub_tree = proto_tree_add_subtree_format(ecat_header_tree, tvb, suboffset, 2, + ett_ecat_length, NULL, "Length : %d (0x%x) - %s - %s", + len, len, ecHdr.len & 0x4000 ? "Roundtrip" : "No Roundtrip", ecHdr.len & 0x8000 ? "More Follows..." : "Last Sub Command"); + + proto_tree_add_item(length_sub_tree, hf_ecat_length_len, tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(length_sub_tree, hf_ecat_length_r, tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(length_sub_tree, hf_ecat_length_c, tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(length_sub_tree, hf_ecat_length_m, tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + + suboffset+=2; + } + + proto_tree_add_item(ecat_header_tree, hf_ecat_int, tvb, suboffset, 2, ENC_LITTLE_ENDIAN); + suboffset+=2; + } + else + { + suboffset+=EcParserHDR_Len; + } + + if ( (ecHdr.cmd == 1 || ecHdr.cmd == 4) && ecHdr.anAddrUnion.a.ado == 0x900 && ecHdr.len >= 16 && cnt > 0 ) + { + guint32 pDC[4]; + init_dc_measure(pDC, tvb, suboffset); + + ecat_dc_tree = proto_tree_add_subtree(ecat_datagram_tree, tvb, suboffset, len, ett_ecat_dc, NULL, "Dc"); + dissect_esc_register(pinfo, ecat_dc_tree, tvb, suboffset, len, &ecHdr, cnt); + + if( subCount < 10 ){ + aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_sub_data[subCount], tvb, offset + EcParserHDR_Len, len, ENC_NA); + proto_item_set_hidden(aitem); + } + + if ( pDC[3] != 0 ) + { + proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_da, tvb, suboffset, 4, pDC[3] - pDC[0]); + if( subCount < 10 ){ + hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_da[subCount], tvb, suboffset, 4, pDC[3] - pDC[0]); + proto_item_set_hidden(hidden_item); + } + + if ( pDC[1] != 0 ) + { + proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_bd, tvb, suboffset, 4, pDC[1] - pDC[3]); + if( subCount < 10 ){ + hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_bd[subCount], tvb, suboffset, 4, pDC[1] - pDC[3]); + proto_item_set_hidden(hidden_item); + } + } + else if ( pDC[2] != 0 ) + { + proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_cd, tvb, suboffset, 4, pDC[2] - pDC[3]); + if( subCount < 10 ){ + hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_cd[subCount], tvb, suboffset, 4, pDC[2] - pDC[3]); + proto_item_set_hidden(hidden_item); + } + } + } + if ( pDC[1] != 0 ) + { + proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_ba, tvb, suboffset, 4, pDC[1] - pDC[0]); + if( subCount < 10 ){ + hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_ba[subCount], tvb, suboffset, 4, pDC[1] - pDC[0]); + proto_item_set_hidden(hidden_item); + } + if ( pDC[2] != 0 ) + { + proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_cb, tvb, suboffset, 4, pDC[2] - pDC[1]); + if( subCount < 10 ){ + hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_cb[subCount], tvb, suboffset, 4, pDC[2] - pDC[1]); + proto_item_set_hidden(hidden_item); + } + } + } + else if ( pDC[2] != 0 ) + { + proto_tree_add_uint(ecat_dc_tree, hf_ecat_dc_diff_ca, tvb, suboffset, 4, pDC[2] - pDC[0]); + if( subCount < 10 ){ + hidden_item = proto_tree_add_uint(ecat_dc_tree, hf_ecat_sub_dc_diff_ca[subCount], tvb, suboffset, 4, pDC[2] - pDC[0]); + proto_item_set_hidden(hidden_item); + } + } + } + else if (dissect_esc_register(pinfo, ecat_datagram_tree, tvb, suboffset, len, &ecHdr, cnt) != 0) + { + guint startOfData = offset + EcParserHDR_Len; + guint dataLength = len; + + if ( len >= ETHERCAT_MBOX_HEADER_LEN && + ((ecHdr.cmd==EC_CMD_TYPE_FPWR || ecHdr.cmd == EC_CMD_TYPE_APWR || ecHdr.cmd == EC_CMD_TYPE_APRW || ecHdr.cmd == EC_CMD_TYPE_FPRW) || ((ecHdr.cmd==EC_CMD_TYPE_FPRD || ecHdr.cmd==EC_CMD_TYPE_APRD) && cnt==1) ) && + ecHdr.anAddrUnion.a.ado>=0x1000 + ) + { + init_mbx_header(&mbox, tvb, startOfData); + switch ( mbox.aControlUnion.v.Type ) + { + case ETHERCAT_MBOX_TYPE_EOE: + case ETHERCAT_MBOX_TYPE_ADS: + case ETHERCAT_MBOX_TYPE_FOE: + case ETHERCAT_MBOX_TYPE_COE: + case ETHERCAT_MBOX_TYPE_SOE: + if ( mbox.Length <= 1500 ) + { + guint MBoxLength = mbox.Length + ETHERCAT_MBOX_HEADER_LEN; + if ( MBoxLength > len ) + MBoxLength = len; + + next_tvb = tvb_new_subset_length(tvb, startOfData, MBoxLength); + call_dissector_only(ecat_mailbox_handle, next_tvb, pinfo, ecat_datagram_tree, NULL); + + startOfData += MBoxLength; + dataLength -= MBoxLength; + } + break; + } + } + if( dataLength > 0 ) + { + /* Allow sub dissectors to have a chance with this data */ + if(!dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, ecat_datagram_tree, &hdtbl_entry, NULL)) + { + /* No sub dissector did recognize this data, dissect it as data only */ + proto_tree_add_item(ecat_datagram_tree, hf_ecat_data, tvb, startOfData, dataLength, ENC_NA); + } + + if( subCount < 10 ){ + aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_sub_data[subCount], tvb, startOfData, dataLength, ENC_NA); + proto_item_set_hidden(aitem); + } + } + } + + if( tree ) + { + proto_tree_add_item(ecat_datagram_tree, hf_ecat_cnt, tvb, offset + EcParserHDR_Len + len , 2, ENC_LITTLE_ENDIAN); + if( subCount < 10 ){ + aitem = proto_tree_add_item(ecat_datagram_tree, hf_ecat_sub_cnt[subCount], tvb, offset + EcParserHDR_Len + len , 2, ENC_LITTLE_ENDIAN); + proto_item_set_hidden(aitem); + } + } + + offset+=subsize; + subCount++; + } while((offset < datagram_length) && + (ecHdr.len & 0x8000)); + + /* Add information that states which portion of the PDU that is pad bytes. + These are added just to get an Ethernet frame size of at least 64 bytes, + which is required by the protocol specification */ + if(datagram_padding_bytes > 0) + { + proto_tree_add_item(tree, hf_ecat_padding, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_NA); + } + return tvb_captured_length(tvb); +} + +void proto_register_ecat(void) +{ + static hf_register_info hf[] = + { + { &hf_ecat_sub, + { "EtherCAT Frame", "ecat.sub", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_ecat_header, + { "header", "ecat.header", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, +#endif + { &hf_ecat_sub_data[0], + { "Data", "ecat.sub1.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[1], + { "Data", "ecat.sub2.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[2], + { "Data", "ecat.sub3.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[3], + { "Data", "ecat.sub4.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[4], + { "Data", "ecat.sub5.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[5], + { "Data", "ecat.sub6.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[6], + { "Data", "ecat.sub7.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[7], + { "Data", "ecat.sub8.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[8], + { "Data", "ecat.sub9.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_data[9], + { "Data", "ecat.sub10.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_data, + { "Data", "ecat.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_cnt, + { "Working Cnt", "ecat.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, "The working counter is increased once for each addressed device if at least one byte/bit of the data was successfully read and/or written by that device, it is increased once for every operation made by that device - read/write/read and write", HFILL } + }, + { &hf_ecat_sub_cnt[0], + { "Working Cnt", "ecat.sub1.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[1], + { "Working Cnt", "ecat.sub2.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[2], + { "Working Cnt", "ecat.sub3.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[3], + { "Working Cnt", "ecat.sub4.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[4], + { "Working Cnt", "ecat.sub5.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[5], + { "Working Cnt", "ecat.sub6.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[6], + { "Working Cnt", "ecat.sub7.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[7], + { "Working Cnt", "ecat.sub8.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[8], + { "Working Cnt", "ecat.sub9.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cnt[9], + { "Working Cnt", "ecat.sub10.cnt", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_cmd, + { "Command", "ecat.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[0], + { "Command", "ecat.sub1.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[1], + { "Command", "ecat.sub2.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[2], + { "Command", "ecat.sub3.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[3], + { "Command", "ecat.sub4.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[4], + { "Command", "ecat.sub5.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[5], + { "Command", "ecat.sub6.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[6], + { "Command", "ecat.sub7.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[7], + { "Command", "ecat.sub8.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[8], + { "Command", "ecat.sub9.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_cmd[9], + { "Command", "ecat.sub10.cmd", + FT_UINT8, BASE_HEX, VALS(EcCmdShort), 0x0, NULL, HFILL } + }, + { &hf_ecat_idx, + { "Index", "ecat.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[0], + { "Index", "ecat.sub1.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[1], + { "Index", "ecat.sub2.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[2], + { "Index", "ecat.sub3.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[3], + { "Index", "ecat.sub4.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[4], + { "Index", "ecat.sub5.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[5], + { "Index", "ecat.sub6.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[6], + { "Index", "ecat.sub7.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[7], + { "Index", "ecat.sub8.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[8], + { "Index", "ecat.sub9.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_idx[9], + { "Index", "ecat.sub10.idx", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_adp, + { "Slave Addr", "ecat.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[0], + { "Slave Addr", "ecat.sub1.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[1], + { "Slave Addr", "ecat.sub2.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[2], + { "Slave Addr", "ecat.sub3.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[3], + { "Slave Addr", "ecat.sub4.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[4], + { "Slave Addr", "ecat.sub5.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[5], + { "Slave Addr", "ecat.sub6.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[6], + { "Slave Addr", "ecat.sub7.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[7], + { "Slave Addr", "ecat.sub8.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[8], + { "Slave Addr", "ecat.sub9.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_adp[9], + { "Slave Addr", "ecat.sub10.adp", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_ado, + { "Offset Addr", "ecat.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[0], + { "Offset Addr", "ecat.sub1.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[1], + { "Offset Addr", "ecat.sub2.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[2], + { "Offset Addr", "ecat.sub3.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[3], + { "Offset Addr", "ecat.sub4.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[4], + { "Offset Addr", "ecat.sub5.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[5], + { "Offset Addr", "ecat.sub6.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[6], + { "Offset Addr", "ecat.sub7.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[7], + { "Offset Addr", "ecat.sub8.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[8], + { "Offset Addr", "ecat.sub9.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_ado[9], + { "Offset Addr", "ecat.sub10.ado", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_lad, + { "Log Addr", "ecat.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[0], + { "Log Addr", "ecat.sub1.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[1], + { "Log Addr", "ecat.sub2.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[2], + { "Log Addr", "ecat.sub3.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[3], + { "Log Addr", "ecat.sub4.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[4], + { "Log Addr", "ecat.sub5.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[5], + { "Log Addr", "ecat.sub6.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[6], + { "Log Addr", "ecat.sub7.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[7], + { "Log Addr", "ecat.sub8.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[8], + { "Log Addr", "ecat.sub9.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_lad[9], + { "Log Addr", "ecat.sub10.lad", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_ecat_len, + { "Length", "ecat.len", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_ecat_int, + { "Interrupt", "ecat.int", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_dc_diff_da, + { "DC D-A", "ecat.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_dc_diff_bd, + { "DC B-D", "ecat.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_dc_diff_cb, + { "DC C-B", "ecat.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_dc_diff_cd, + { "DC C-D", "ecat.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_dc_diff_ba, + { "DC B-A", "ecat.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_dc_diff_ca, + { "DC C-A", "ecat.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[0], + { "DC D-A", "ecat.sub1.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[1], + { "DC D-A", "ecat.sub2.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[2], + { "DC D-A", "ecat.sub3.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[3], + { "DC D-A", "ecat.sub4.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[4], + { "DC D-A", "ecat.sub5.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[5], + { "DC D-A", "ecat.sub6.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[6], + { "DC D-A", "ecat.sub7.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[7], + { "DC D-A", "ecat.sub8.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[8], + { "DC D-A", "ecat.sub9.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_da[9], + { "DC D-A", "ecat.sub10.dc.dif.da", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + + { &hf_ecat_sub_dc_diff_bd[0], + { "DC B-C", "ecat.sub1.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[1], + { "DC B-C", "ecat.sub2.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[2], + { "DC B-C", "ecat.sub3.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[3], + { "DC B-C", "ecat.sub4.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[4], + { "DC B-C", "ecat.sub5.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[5], + { "DC B-C", "ecat.sub6.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[6], + { "DC B-C", "ecat.sub7.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[7], + { "DC B-C", "ecat.sub8.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[8], + { "DC B-C", "ecat.sub9.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_bd[9], + { "DC B-D", "ecat.sub10.dc.dif.bd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + + { &hf_ecat_sub_dc_diff_cb[0], + { "DC C-B", "ecat.sub1.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[1], + { "DC C-B", "ecat.sub2.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[2], + { "DC C-B", "ecat.sub3.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[3], + { "DC C-B", "ecat.sub4.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[4], + { "DC C-B", "ecat.sub5.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[5], + { "DC C-B", "ecat.sub6.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[6], + { "DC C-B", "ecat.sub7.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[7], + { "DC C-B", "ecat.sub8.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[8], + { "DC C-B", "ecat.sub9.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cb[9], + { "DC C-B", "ecat.sub10.dc.dif.cb", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + + { &hf_ecat_sub_dc_diff_cd[0], + { "DC C-D", "ecat.sub1.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[1], + { "DC C-D", "ecat.sub2.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[2], + { "DC C-D", "ecat.sub3.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[3], + { "DC C-D", "ecat.sub4.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[4], + { "DC C-D", "ecat.sub5.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[5], + { "DC C-D", "ecat.sub6.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[6], + { "DC C-D", "ecat.sub7.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[7], + { "DC C-D", "ecat.sub8.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[8], + { "DC C-D", "ecat.sub9.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_cd[9], + { "DC C-D", "ecat.sub10.dc.dif.cd", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + + { &hf_ecat_sub_dc_diff_ba[0], + { "DC B-A", "ecat.sub1.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[1], + { "DC B-A", "ecat.sub2.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[2], + { "DC B-A", "ecat.sub3.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[3], + { "DC B-A", "ecat.sub4.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[4], + { "DC B-A", "ecat.sub5.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[5], + { "DC B-A", "ecat.sub6.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[6], + { "DC B-A", "ecat.sub7.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[7], + { "DC B-A", "ecat.sub8.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[8], + { "DC B-A", "ecat.sub9.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ba[9], + { "DC B-A", "ecat.sub10.dc.dif.ba", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + + { &hf_ecat_sub_dc_diff_ca[0], + { "DC C-A", "ecat.sub1.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[1], + { "DC C-A", "ecat.sub2.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[2], + { "DC C-A", "ecat.sub3.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[3], + { "DC C-A", "ecat.sub4.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[4], + { "DC C-A", "ecat.sub5.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[5], + { "DC C-A", "ecat.sub6.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[6], + { "DC C-A", "ecat.sub7.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[7], + { "DC C-A", "ecat.sub8.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[8], + { "DC C-A", "ecat.sub9.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_sub_dc_diff_ca[9], + { "DC C-A", "ecat.sub10.dc.dif.ca", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_length_len, + { "Length", "ecat.subframe.length", + FT_UINT16, BASE_DEC, NULL, 0x07ff, NULL, HFILL} + }, + { &hf_ecat_length_r, + { "Reserved", "ecat.subframe.reserved", + FT_UINT16, BASE_DEC, VALS(ecat_subframe_reserved_vals), 0x3800, NULL, HFILL} + }, + { &hf_ecat_length_c, + { "Round trip", "ecat.subframe.circulating", + FT_BOOLEAN, 16, TFS(&tfs_ecat_subframe_circulating_vals), 0x4000, NULL, HFILL} + }, + { &hf_ecat_length_m, + { "Last indicator", "ecat.subframe.more", + FT_BOOLEAN, 16, TFS(&tfs_ecat_subframe_more_vals), 0x8000, NULL, HFILL} + }, + { &hf_ecat_padding, + { "Pad bytes", "ecat.subframe.pad_bytes", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + + /* Registers */ + { &hf_ecat_reg_revision, + {"ESC Revision (0x0)", "ecat.reg.revision", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_esc_type, + {"ESC Type (0x1)", "ecat.reg.type", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_esc_build, + {"ESC Build (0x2)", "ecat.reg.build", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_esc_fmmucnt, + {"ESC FMMU Cnt (0x4)", "ecat.reg.fmmucnt", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_esc_smcnt, + {"ESC SM Cnt (0x5)", "ecat.reg.smcnt", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_esc_ports, + {"ESC Ports (0x6)", "ecat.reg.ports", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_esc_dpram, + {"ESC DPRAM (0x7)", "ecat.reg.dpram", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features, + {"ESC Features (0x8)", "ecat.reg.features", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features_fmmurestrict, + {"FMMU bytewise restriction", "ecat.reg.features.fmmurestrict", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0001, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features_smaddrrestrict, + {"SM addressing restriction", "ecat.reg.features.smaddrrestrict", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0002, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features_dcsupport, + {"DC support", "ecat.reg.features.dcsupport", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0004, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features_dc64support, + {"DC 64 bit support", "ecat.reg.features.dc64support", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0008, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features_ebuslowjitter, + {"E-Bus low jitter", "ecat.reg.features.ebuslowjitter", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0010, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features_ebusextlinkdetect, + {"E-Bus ext. link detection", "ecat.reg.features.ebusextlinkdetect", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0020, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features_miiextlinkdetect, + {"MII ext. link detection", "ecat.reg.features.miiextlinkdetect", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0040, NULL, HFILL } + }, + { &hf_ecat_reg_esc_features_crcext, + {"CRC ext. detection", "ecat.reg.features.crcext", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0080, NULL, HFILL } + }, + { &hf_ecat_reg_physaddr, + {"Phys Addr (0x10)", "ecat.reg.physaddr", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_physaddr2, + {"Phys Addr 2nd (0x12)", "ecat.reg.physaddr2", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl1, + {"ESC Ctrl (0x100)", "ecat.reg.dlctrl1", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl1_killnonecat, + {"Kill non EtherCAT frames", "ecat.reg.dlctrl1.killnonecat", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl1_port0extlinkdetect, + {"Port 0 ext. link detection", "ecat.reg.dlctrl1.port0extlinkdetect", + FT_BOOLEAN, 8, TFS(&tfs_local_disabled_enabled), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl1_port1extlinkdetect, + {"Port 1 ext. link detection", "ecat.reg.dlctrl1.port1extlinkdetect", + FT_BOOLEAN, 8, TFS(&tfs_local_disabled_enabled), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl1_port2extlinkdetect, + {"Port 2 ext. link detection", "ecat.reg.dlctrl1.port2extlinkdetect", + FT_BOOLEAN, 8, TFS(&tfs_local_disabled_enabled), 0x40, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl1_port3extlinkdetect, + {"Port 3 ext. link detection", "ecat.reg.dlctrl1.port3extlinkdetect", + FT_BOOLEAN, 8, TFS(&tfs_local_disabled_enabled), 0x80, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl2, + {"ESC Ctrl (0x101)", "ecat.reg.dlcrtl2", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl2_port0, + {"Port 0", "ecat.reg.dlcrtl2.port0", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_101), 0x03, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl2_port1, + {"Port 1", "ecat.reg.dlcrtl2.port1", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_101), 0x0C, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl2_port2, + {"Port 2", "ecat.reg.dlcrtl2.port2", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_101), 0x30, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl2_port3, + {"Port 3", "ecat.reg.dlcrtl2.port3", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_101), 0xC0, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl3, + {"ESC Ctrl (0x102)", "ecat.reg.dlctrl3", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl3_fifosize, + {"Fifo size", "ecat.reg.dlctrl3.fifosize", + FT_UINT8, BASE_HEX, NULL, 0x07, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl3_lowebusjit, + {"Low E-Bus jitter", "ecat.reg.dlctrl3.lowebusjit", + FT_BOOLEAN, 8, TFS(&tfs_local_disabled_enabled), 0x08, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl4, + {"ESC Ctrl (0x103)", "ecat.reg.dlctrl4", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dlctrl4_2ndaddress, + {"Second address", "ecat.reg.dlctrl4.2ndaddress", + FT_BOOLEAN, 8, TFS(&tfs_local_disabled_enabled), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus1, + {"ESC Status (0x110)", "ecat.reg.dlstatus1", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus1_operation, + {"Operation", "ecat.reg.dlstatus1.operation", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus1_pdiwatchdog, + {"PDI watchdog", "ecat.reg.dlstatus1.pdiwatchdog", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_watchdog), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus1_enhlinkdetect, + {"Enh. Link Detection", "ecat.reg.dlstatus1.enhlinkdetect", + FT_BOOLEAN, 8, TFS(&tfs_local_disabled_enabled), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus1_physlink_port0, + {"Physical link Port 0", "ecat.reg.dlstatus1.physlink.port0", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus1_physlink_port1, + {"Physical link Port 1", "ecat.reg.dlstatus1.physlink.port1", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus1_physlink_port2, + {"Physical link Port 2", "ecat.reg.dlstatus1.physlink.port2", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x40, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus1_physlink_port3, + {"Physical link Port 3", "ecat.reg.dlstatus1.physlink.port3", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x80, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus2, + {"ESC Status (0x111)", "ecat.reg.dlstatus2", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus2_port0, + {"Port 0", "ecat.reg.dlstatus2.port0", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_111), 0x03, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus2_port1, + {"Port 1", "ecat.reg.dlstatus2.port1", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_111), 0x0C, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus2_port2, + {"Port 2", "ecat.reg.dlstatus2.port2", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_111), 0x30, NULL, HFILL } + }, + { &hf_ecat_reg_dlstatus2_port3, + {"Port 3", "ecat.reg.dlstatus2.port3", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_111), 0xC0, NULL, HFILL } + }, + { &hf_ecat_reg_regprotect, + {"Write Register Protect (0x20)", "ecat.reg.regprotect", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_accessprotect, + {"Access Protect (0x30)", "ecat.reg.accessprotect", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_resetecat, + {"ESC reset Ecat (0x40)", "ecat.reg.resetecat", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_resetpdi, + {"ESC reset Pdi (0x41)", "ecat.reg.resetpdi", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_regphysrwoffs, + {"Phys. RW Offset (0x108)", "ecat.regphysrwoffs", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_alctrl, + {"AL Ctrl (0x120)", "ecat.reg.alctrl", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_alctrl_ctrl, + {"Al Ctrl", "ecat.reg.alctrl.ctrl", + FT_UINT16, BASE_HEX, VALS(vals_esc_reg_120), 0x0f, NULL, HFILL } + }, + { &hf_ecat_reg_alctrl_errack, + {"Error Ack", "ecat.reg.alctrl.errack", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0010, NULL, HFILL } + }, + { &hf_ecat_reg_alctrl_id, + {"Id", "ecat.reg.alctrl.id", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0020, NULL, HFILL } + }, + { &hf_ecat_reg_alstatus, + {"AL Status (0x130)", "ecat.reg.alstatus", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_alstatus_status, + {"Al Status", "ecat.reg.alstatus.status", + FT_UINT16, BASE_HEX, VALS(vals_esc_reg_120), 0x000f, NULL, HFILL } + }, + { &hf_ecat_reg_alstatus_err, + {"Error", "ecat.reg.alstatus.err", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0010, NULL, HFILL } + }, + { &hf_ecat_reg_alstatus_id, + {"Id", "ecat.reg.alstatus.id", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0020, NULL, HFILL } + }, + { &hf_ecat_reg_alstatuscode, + {"AL Status Code (0x134)", "ecat.reg.alstatuscode", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl1, + {"PDI Ctrl (0x140)", "ecat.reg.pdictrl1", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl1_pdi, + {"PDI", "ecat.reg.pdictrl1.pdi", + FT_UINT8, BASE_HEX, VALS(vals_esc_reg_140), 0xff, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2, + {"PDI Ctrl (0x141)", "ecat.reg.pdictrl2", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2_devemul, + {"Device emulation", "ecat.reg.pdictrl2.devemul", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2_enhlnkdetect, + {"Enhanced link detection", "ecat.reg.pdictrl2.enhlnkdetect", + FT_BOOLEAN, 8, TFS(&tfs_local_disable_enable), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2_dcsyncout, + {"Enable DC sync out", "ecat.reg.pdictrl2.dcsyncout", + FT_BOOLEAN, 8, TFS(&tfs_local_disable_enable), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2_dcsyncin, + {"Enable DC latch in", "ecat.reg.pdictrl2.dcsyncin", + FT_BOOLEAN, 8, TFS(&tfs_local_disable_enable), 0x08, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2_enhlnkdetect0, + {"Enhanced link detection port 0", "ecat.reg.pdictrl2.enhlnkdetect0", + FT_BOOLEAN, 8, TFS(&tfs_local_disable_enable), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2_enhlnkdetect1, + {"Enhanced link detection port 1", "ecat.reg.pdictrl2.enhlnkdetect1", + FT_BOOLEAN, 8, TFS(&tfs_local_disable_enable), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2_enhlnkdetect2, + {"Enhanced link detection port 2", "ecat.reg.pdictrl2.enhlnkdetect2", + FT_BOOLEAN, 8, TFS(&tfs_local_disable_enable), 0x40, NULL, HFILL } + }, + { &hf_ecat_reg_pdictrl2_enhlnkdetect3, + {"Enhanced link detection port 3", "ecat.reg.pdictrl2.enhlnkdetect3", + FT_BOOLEAN, 8, TFS(&tfs_local_disable_enable), 0x80, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask, + {"ECAT IRQ Mask (0x200)", "ecat.reg.irqmask.ecat_mask", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_latchevt, + {"Latch event", "ecat.reg.irqmask.ecat_mask.latchevt", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0001, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_escstatevt, + {"ESC Status event", "ecat.reg.irqmask.ecat_mask.escstatevt", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0004, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_alstatevt, + {"AL Status event", "ecat.reg.irqmask.ecat_mask.alstatevt", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0008, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_sm0irq, + {"SM 0 IRQ", "ecat.reg.irqmask.ecat_mask.sm0irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_sm1irq, + {"SM 1 IRQ", "ecat.reg.irqmask.ecat_mask.sm1irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_sm2irq, + {"SM 2 IRQ", "ecat.reg.irqmask.ecat_mask.sm2irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0400, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_sm3irq, + {"SM 3 IRQ", "ecat.reg.irqmask.ecat_mask.sm3irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0800, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_sm4irq, + {"SM 4 IRQ", "ecat.reg.irqmask.ecat_mask.sm4irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x1000, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_sm5irq, + {"SM 5 IRQ", "ecat.reg.irqmask.ecat_mask.sm5irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x2000, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_sm6irq, + {"SM 6 IRQ", "ecat.reg.irqmask.ecat_mask.sm6irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x4000, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_mask_sm7irq, + {"SM 7 IRQ", "ecat.reg.irqmask.ecat_mask.sm7irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x8000, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL, + {"PDI IRQ Mask L (0x204)", "ecat.reg.irqmask.pdiL", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_alctrl, + {"AL Ctrl", "ecat.reg.irqmask.pdiL.alctrl", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x1, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_latchin, + {"Latch input", "ecat.reg.irqmask.pdiL.latchin", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0002, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sync0, + {"SYNC 0", "ecat.reg.irqmask.pdiL.sync0", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0004, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sync1, + {"SYNC 1", "ecat.reg.irqmask.pdiL.sync1", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0008, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_smchg, + {"SM changed", "ecat.reg.irqmask.pdiL.smchg", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0010, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_eepromcmdpen, + {"EEPROM command pending", "ecat.reg.irqmask.pdiL.eepromcmdpen", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0020, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sm0, + {"SM 0", "ecat.reg.irqmask.pdiL.sm0", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sm1, + {"SM 1", "ecat.reg.irqmask.pdiL.sm1", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sm2, + {"SM 2", "ecat.reg.irqmask.pdiL.sm2", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0400, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sm3, + {"SM 3", "ecat.reg.irqmask.pdiL.sm3", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0800, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sm4, + {"SM 4", "ecat.reg.irqmask.pdiL.sm4", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x1000, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sm5, + {"SM 5", "ecat.reg.irqmask.pdiL.sm5", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x2000, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sm6, + {"SM 6", "ecat.reg.irqmask.pdiL.sm6", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x4000, NULL, HFILL } + }, + { &hf_ecat_reg_pdiL_sm7, + {"SM 7", "ecat.reg.irqmask.pdiL.sm7", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x8000, NULL, HFILL } + }, + { &hf_ecat_reg_pdiH, + {"PDI IRQ Mask H (0x206)", "ecat.reg.irqmask.pdiH", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_ecat, + {"ECAT IRQ (0x210)", "ecat.reg.irq.ecat", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_latchevt, + {"Latch event", "ecat.reg.irq.ecat.latchevt", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0001, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_escstatevt, + {"ESC Status event", "ecat.reg.irq.ecat.escstatevt", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0004, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_alstatevt, + {"AL Status event", "ecat.reg.irq.ecat.alstatevt", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0008, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_sm0irq, + {"SM 0 IRQ", "ecat.reg.irq.ecat.sm0irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_sm1irq, + {"SM 1 IRQ", "ecat.reg.irq.ecat.sm1irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_sm2irq, + {"SM 2 IRQ", "ecat.reg.irq.ecat.sm2irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0400, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_sm3irq, + {"SM 3 IRQ", "ecat.reg.irq.ecat.sm3irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0800, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_sm4irq, + {"SM 4 IRQ", "ecat.reg.irq.ecat.sm4irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x1000, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_sm5irq, + {"SM 5 IRQ", "ecat.reg.irq.ecat.sm5irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x2000, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_sm6irq, + {"SM 6 IRQ", "ecat.reg.irq.ecat.sm6irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x4000, NULL, HFILL } + }, + { &hf_ecat_reg_ecat_sm7irq, + {"SM 7 IRQ", "ecat.reg.irq.ecat.sm7irq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x8000, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1, + {"PDI IRQ 1 (0x220)", "ecat.reg.irq.pdi1", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_alctrl, + {"AL Ctrl", "ecat.reg.irq.pdi1.alctrl", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0001, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_latchin, + {"Latch input", "ecat.reg.irq.pdi1.latchin", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0002, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sync0, + {"SYNC 0", "ecat.reg.irq.pdi1.sync0", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0004, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sync1, + {"SYNC 1", "ecat.reg.irq.pdi1.sync1", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0008, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_smchg, + {"SM changed", "ecat.reg.irq.pdi1.smchg", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0010, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_eepromcmdpen, + {"EEPROM command pending", "ecat.reg.irq.pdi1.eepromcmdpen", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0020, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sm0, + {"SM 0", "ecat.reg.irq.pdi1.sm0", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sm1, + {"SM 1", "ecat.reg.irq.pdi1.sm1", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sm2, + {"SM 2", "ecat.reg.irq.pdi1.sm2", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0400, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sm3, + {"SM 3", "ecat.reg.irq.pdi1.sm3", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0800, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sm4, + {"SM 4", "ecat.reg.irq.pdi1.sm4", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x1000, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sm5, + {"SM 5", "ecat.reg.irq.pdi1.sm5", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x2000, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sm6, + {"SM 6", "ecat.reg.irq.pdi1.sm6", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x4000, NULL, HFILL } + }, + { &hf_ecat_reg_pdi1_sm7, + {"SM 7", "ecat.reg.irq.pdi1.sm7", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x8000, NULL, HFILL } + }, + { &hf_ecat_reg_pdi2, + {"PDI IRQ 2 (0x222)", "ecat.reg.irq.pdi2", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_crc0, + {"CRC 0 (0x300)", "ecat.reg.crc0", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_crc1, + {"CRC 1 (0x302)", "ecat.reg.crc1", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_crc2, + {"CRC 2 (0x304)", "ecat.reg.crc2", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_crc3, + {"CRC 3 (0x306)", "ecat.reg.crc3", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_crc0_frame, + {"Invalid frame", "ecat.reg.crc0.frame", + FT_UINT16, BASE_HEX, NULL, 0x00ff, NULL, HFILL } + }, + { &hf_ecat_reg_crc0_rx, + {"RX error", "ecat.reg.crc0.rx", + FT_UINT16, BASE_HEX, NULL, 0xff00, NULL, HFILL } + }, + { &hf_ecat_reg_crc1_frame, + {"Invalid frame", "ecat.reg.crc1.frame", + FT_UINT16, BASE_HEX, NULL, 0x00ff, NULL, HFILL } + }, + { &hf_ecat_reg_crc1_rx, + {"RX error", "ecat.reg.crc1.rx", + FT_UINT16, BASE_HEX, NULL, 0xff00, NULL, HFILL } + }, + { &hf_ecat_reg_crc2_frame, + {"Invalid frame", "ecat.reg.crc2.frame", + FT_UINT16, BASE_HEX, NULL, 0x00ff, NULL, HFILL } + }, + { &hf_ecat_reg_crc2_rx, + {"RX error", "ecat.reg.crc2.rx", + FT_UINT16, BASE_HEX, NULL, 0xff00, NULL, HFILL } + }, + { &hf_ecat_reg_crc3_frame, + {"Invalid frame", "ecat.reg.crc3.frame", + FT_UINT16, BASE_HEX, NULL, 0x00ff, NULL, HFILL } + }, + { &hf_ecat_reg_crc3_rx, + {"RX error", "ecat.reg.crc3.rx", + FT_UINT16, BASE_HEX, NULL, 0xff00, NULL, HFILL } + }, + { &hf_ecat_reg_crc_fwd0, + {"Forw. CRC 0 (0x308)", "ecat.reg.crc.fwd0", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_crc_fwd1, + {"Forw. CRC 1 (0x309)", "ecat.reg.crc.fwd1", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_crc_fwd2, + {"Forw. CRC 2 (0x30A)", "ecat.reg.crc.fwd2", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_crc_fwd3, + {"Forw. CRC 3 (0x30B)", "ecat.reg.crc.fwd3", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_processuniterr, + {"Process unit error (0x30C)", "ecat.reg.processuniterr", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_pdierr, + {"PDI error (0x30D)", "ecat.reg.pdierr", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_linklost0, + {"Link Lost 0 (0x310)", "ecat.reg.linklost0", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_linklost1, + {"Link Lost 1 (0x311)", "ecat.reg.linklost1", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_linklost2, + {"Link Lost 2 (0x312)", "ecat.reg.linklost2", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_linklost3, + {"Link Lost 3 (0x313)", "ecat.reg.linklost3", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_wd_divisor, + {"WD Divisor (0x400)", "ecat.reg.wd.divisor", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_wd_timepdi, + {"WD Time PDI (0x410)", "ecat.reg.wd.timepdi", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_wd_timesm, + {"WD Time SM (0x420)", "ecat.reg.wd.timesm", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_wd_status, + {"WD Status (0x440)", "ecat.reg.wd.status", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_wd_status_pdwatchdog, + {"PD watchdog", "ecat.reg.wd.status.pdwatchdog", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_watchdog), 0x1, NULL, HFILL } + }, + { &hf_ecat_reg_wd_cntsm, + {"WD SM Counter (0x442)", "ecat.reg.wd.cntsm", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_wd_cntpdi, + {"WD PDI Counter (0x443)", "ecat.reg.wd.cntpdi", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_eeprom_assign, + {"EEPROM Assign (0x500)", "ecat.reg.eeprom.assign", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_eeprom_assign_ctrl, + {"EEPROM access ctrl", "ecat.reg.eeprom.assign.ctrl", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_500_0), 0x1, NULL, HFILL } + }, + { &hf_ecat_reg_eeprom_assign_pdiaccess, + {"Reset PDI access", "ecat.reg.eeprom.assign.pdiaccess", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_500_1), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_eeprom_assign_status, + {"EEPROM access status", "ecat.reg.eeprom.assign.status", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_500_0), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat, + {"EEPROM Ctrl/Status (0x502)", "ecat.reg.ctrlstat", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_wraccess, + {"Write access", "ecat.reg.ctrlstat.wraccess", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0001, NULL, HFILL } + }, + /* Next 4 bits reserved */ + { &hf_ecat_reg_ctrlstat_eepromemul, + {"EEPROM emulation", "ecat.reg.ctrlstat.eepromemul", + FT_BOOLEAN, 16, TFS(&tfs_esc_reg_502_5), 0x0020, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_8bacc, + {"8 byte access", "ecat.reg.ctrlstat.8bacc", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0040, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_2bacc, + {"2 byte address", "ecat.reg.ctrlstat.2bacc", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0080, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_rdacc, + {"Read access", "ecat.reg.ctrlstat.rdacc", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_wracc, + {"Write access", "ecat.reg.ctrlstat.wracc", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_reloadacc, + {"Reload access", "ecat.reg.ctrlstat.reloadacc", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0400, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_crcerr, + {"CRC error", "ecat.reg.ctrlstat.crcerr", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0800, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_lderr, + {"Load error", "ecat.reg.ctrlstat.lderr", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x1000, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_cmderr, + {"Cmd error", "ecat.reg.ctrlstat.cmderr", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x2000, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_wrerr, + {"Write error", "ecat.reg.ctrlstat.wrerr", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x4000, NULL, HFILL } + }, + { &hf_ecat_reg_ctrlstat_busy, + {"Busy", "ecat.reg.ctrlstat.busy", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x8000, NULL, HFILL } + }, + { &hf_ecat_reg_addrl, + {"EEPROM Address Lo (0x504)", "ecat.reg.addrl", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_addrh, + {"EEPROM Address Hi (0x506)", "ecat.reg.addrh", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_data0, + {"EEPROM Data 0 (0x508)", "ecat.reg.data0", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_data1, + {"EEPROM Data 1 (0x50A)", "ecat.reg.data1", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_data2, + {"EEPROM Data 2 (0x50c)", "ecat.reg.data2", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_data3, + {"EEPROM Data 3 (0x50e)", "ecat.reg.data3", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + + { &hf_ecat_reg_mio_ctrlstat, + {"Phy MIO Ctrl/Status (0x510)", "ecat.reg.mio.ctrlstat", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + /* TODO: check these masks (ecat_esc_reg_510) against spec. + * In particular hf_ecat_reg_mio_ctrlstat_offsphy is non-contiguous and overlaps wracc1 */ + { &hf_ecat_reg_mio_ctrlstat_wracc1, + {"Write access", "ecat.reg.mio.ctrlstat.wracc1", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0001, NULL, HFILL } + }, + { &hf_ecat_reg_mio_ctrlstat_offsphy, + {"Offset Phy offset", "ecat.reg.mio.ctrlstat.offsphy", + FT_UINT16, BASE_HEX, NULL, 0x008f, NULL, HFILL } + }, + { &hf_ecat_reg_mio_ctrlstat_rdacc, + {"Read access", "ecat.reg.mio.ctrlstat.rdacc", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_mio_ctrlstat_wracc2, + {"Write access", "ecat.reg.mio.ctrlstat.wracc2", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_mio_ctrlstat_wrerr, + {"Write error", "ecat.reg.mio.ctrlstat.wrerr", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x4000, NULL, HFILL } + }, + { &hf_ecat_reg_mio_ctrlstat_busy, + {"Busy", "ecat.reg.mio.ctrlstat.busy", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x8000, NULL, HFILL } + }, + + { &hf_ecat_reg_mio_addr, + {"Phy MIO Address (0x512)", "ecat.reg.mio.addr", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_mio_addr_phyaddr, + {"Phy address", "ecat.reg.mio.addr.phyaddr", + FT_UINT16, BASE_HEX, NULL, 0x000F, NULL, HFILL } + }, + { &hf_ecat_reg_mio_addr_mioaddr, + {"MIO address", "ecat.reg.mio.addr.mioaddr", + FT_UINT16, BASE_HEX, NULL, 0x0F00, NULL, HFILL } + }, + { &hf_ecat_reg_mio_data, + {"Phy MIO Data (0x514)", "ecat.reg.mio.data", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_mio_access, + {"MIO access (0x516)", "ecat.reg.mio.access", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_mio_access_ecatacc, + {"ECAT claims exclusive access", "ecat.reg.mio.access.ecatacc", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0001, NULL, HFILL } + }, + { &hf_ecat_reg_mio_access_pdiacc, + {"PDI has access to MII management", "ecat.reg.mio.access.pdiacc", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_mio_access_forcereset, + {"Force PDI to reset 0517.0", "ecat.reg.mio.access.forcereset", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status0, + {"MIO port status 0 (0x518)", "ecat.reg.mio.status0", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status0_physlink, + {"Physical link detected", "ecat.reg.mio.status0.physlink", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status0_link, + {"Link detected", "ecat.reg.mio.status0.link", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status0_linkstatuserr, + {"Link status error", "ecat.reg.mio.status0.linkstatuserr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status0_readerr, + {"Read error", "ecat.reg.mio.status0.readerr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x08, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status0_linkpartnererr, + {"Link partner error", "ecat.reg.mio.status0.linkpartnererr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status0_phycfgupdated, + {"Phy config updated", "ecat.reg.mio.status0.phycfgupdated", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status1, + {"MIO port status 1 (0x519)", "ecat.reg.mio.status1", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status1_physlink, + {"Physical link detected", "ecat.reg.mio.status1.physlink", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status1_link, + {"Link detected", "ecat.reg.mio.status1.link", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status1_linkstatuserr, + {"Link status error", "ecat.reg.mio.status1.linkstatuserr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status1_readerr, + {"Read error", "ecat.reg.mio.status1.readerr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x08, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status1_linkpartnererr, + {"Link partner error", "ecat.reg.mio.status1.linkpartnererr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status1_phycfgupdated, + {"Phy config updated", "ecat.reg.mio.status1.phycfgupdated", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status2, + {"MIO port status 2 (0x51A)", "ecat.reg.mio.status2", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status2_physlink, + {"Physical link detected", "ecat.reg.mio.status2.physlink", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status2_link, + {"Link detected", "ecat.reg.mio.status2.link", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status2_linkstatuserr, + {"Link status error", "ecat.reg.mio.status2.linkstatuserr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status2_readerr, + {"Read error", "ecat.reg.mio.status2.readerr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x08, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status2_linkpartnererr, + {"Link partner error", "ecat.reg.mio.status2.linkpartnererr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status2_phycfgupdated, + {"Phy config updated", "ecat.reg.mio.status2.phycfgupdated", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status3, + {"MIO port status 3 (0x51B)", "ecat.reg.mio.status3", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status3_physlink, + {"Physical link detected", "ecat.reg.mio.status3.physlink", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status3_link, + {"Link detected", "ecat.reg.mio.status3.link", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status3_linkstatuserr, + {"Link status error", "ecat.reg.mio.status3.linkstatuserr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status3_readerr, + {"Read error", "ecat.reg.mio.status3.readerr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x08, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status3_linkpartnererr, + {"Link partner error", "ecat.reg.mio.status3.linkpartnererr", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_mio_status3_phycfgupdated, + {"Phy config updated", "ecat.reg.mio.status3.phycfgupdated", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu, + {"FMMU", "ecat.fmmu", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_lstart, + { "Log Start", "ecat.fmmu.lstart", + FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_llen, + { "Log Length", "ecat.fmmu.llen", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_lstartbit, + { "Log StartBit", "ecat.fmmu.lstartbit", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_lendbit, + { "Log EndBit", "ecat.fmmu.lendbit", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_pstart, + { "Phys Start", "ecat.fmmu.pstart", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_pstartbit, + { "Phys StartBit", "ecat.fmmu.pstartbit", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_type, + { "Type", "ecat.fmmu.type", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_typeread, + { "Type", "ecat.fmmu.typeread", + FT_BOOLEAN, 8, TFS(&tfs_ecat_fmmu_typeread), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_typewrite, + { "Type", "ecat.fmmu.typewrite", + FT_BOOLEAN, 8, TFS(&tfs_ecat_fmmu_typewrite), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_activate, + { "Activate", "ecat.fmmu.activate", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_fmmu_activate0, + { "FMMU", "ecat.fmmu.activate0", + FT_BOOLEAN, 8, TFS(&tfs_ecat_fmmu_activate), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_syncman, + {"SyncManager", "ecat.syncman", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_start, + {"SM Start", "ecat.syncman.start", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_len, + {"SM Length", "ecat.syncman.len", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_ctrlstatus, + {"SM Ctrl/Status", "ecat.syncman.ctrlstatus", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_pmode, + {"OpMode", "ecat.syncman.opmode", + FT_UINT16, BASE_HEX, VALS(vals_esc_reg_8041), 0x0003, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_access, + {"Access", "ecat.syncman.access", + FT_UINT16, BASE_HEX, VALS(vals_esc_reg_8042), 0x000c, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_irq_ecat, + {"ECAT IRQ", "ecat.syncman.irq.ecat", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0010, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_irq_pdi, + {"PDI IRQ", "ecat.syncman.irq.pdi", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0020, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_wdt, + {"Watchdog trigger", "ecat.syncman.wdt", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0040, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_irq_write, + {"IRQ write", "ecat.syncman.irq.write", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_irq_read, + {"IRQ read", "ecat.syncman.irq.read", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_1bufstate, + {"1 buffer state", "ecat.syncman.1bufstate", + FT_BOOLEAN, 16, TFS(&tfs_esc_reg_8051), 0x0800, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_3bufstate, + {"3 buffer state", "ecat.syncman.3bufstate", + FT_UINT16, BASE_HEX, VALS(vals_esc_reg_8052), 0x3000, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_sm_enable, + {"SM Enable", "ecat.syncman.smenable", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_enable, + {"Enable", "ecat.syncman.enable", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0001, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_repeatreq, + {"Repeat request", "ecat.syncman.repeatreq", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0002, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_latchsmchg_ecat, + {"Latch SyncMan Change ECAT", "ecat.syncman.latchsmchg.ecat", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0040, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_latchsmchg_pdi, + {"Latch SyncMan Change PDI", "ecat.syncman.latchsmchg.pdi", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0080, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_deactivate, + {"Deactivate", "ecat.syncman.deactivate", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0100, NULL, HFILL } + }, + { &hf_ecat_reg_syncman_repeatack, + {"Repeat acknowledge", "ecat.syncman.repeatack", + FT_BOOLEAN, 16, TFS(&tfs_local_true_false), 0x0200, NULL, HFILL } + }, + { &hf_ecat_reg_dc_recv0, + {"DC RecvTime_0 (0x900)", "ecat.reg.dc.recv0", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_recv1, + {"DC RecvTime_1 (0x904)", "ecat.reg.dc.recv1", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_recv2, + {"DC RecvTime_2 (0x908)", "ecat.reg.dc.recv2", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_recv3, + {"DC RecvTime_3 (0x90c)", "ecat.reg.dc.recv3", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_systime, + {"DC SysTime (0x910)", "ecat.reg.dc.systime", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_systimeL, + {"DC SysTime L (0x910)", "ecat.reg.dc.systimeL", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_systimeH, + {"DC SysTime H (0x914)", "ecat.reg.dc.systimeH", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_recvtime64, + {"DC RecvTime (0x918)", "ecat.reg.dc.recvtime64", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_systimeoffs, + {"DC SysTimeOffs (0x920)", "ecat.reg.dc.systimeoffs", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_systimeoffsl, + {"DC SysTimeOffs L (0x920)", "ecat.reg.dc.systimeoffsl", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_systimeoffsh, + {"DC SysTimeOffs H (0x924)", "ecat.reg.dc.systimeoffsh", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_systimedelay, + {"DC SysTimeDelay (0x928)", "ecat.reg.dc.systimedelay", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_ctrlerr, + {"DC CtrlError (0x92c)", "ecat.reg.dc.ctrlerr", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_speedstart, + {"DC SpeedStart (0x930)", "ecat.reg.dc.speedstart", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_speeddiff, + {"DC SpeedDiff (0x932)", "ecat.reg.dc.speeddiff", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_fltdepth_systimediff, + {"DC Filter Depth System Time difference (0x934)", "ecat.reg.dc.fltdepth.systimediff", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_fltdepth_speedcnt, + {"DC Filter Depth Speed counter (0x935)", "ecat.reg.dc.fltdepth.speedcnt", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_cycunitctrl, + {"DC Cyclic Unit Control (0x980)", "ecat.reg.dc.cycunitctrl", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_cycunitctrl_access_cyclic, + {"Write access cyclic", "ecat.reg.dc.cycunitctrl.access_cyclic", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_9801), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_cycunitctrl_access_latch0, + {"Write access latch 0", "ecat.reg.dc.cycunitctrl.access_latch0", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_9801), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_dc_cycunitctrl_access_latch1, + {"Write access latch 1", "ecat.reg.dc.cycunitctrl.access_latch1", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_9801), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation, + {"DC Activation (0x981)", "ecat.reg.dc.activation", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation_enablecyclic, + {"Enable cyclic", "ecat.reg.dc.activation.enablecyclic", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation_gen_sync0, + {"Generate SYNC 0", "ecat.reg.dc.activation.gen_sync0", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation_gen_sync1, + {"Generate SYNC 1", "ecat.reg.dc.activation.gen_sync1", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation_autoactivation, + {"Auto activation", "ecat.reg.dc.activation.autoactivation", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x08, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation_stimeext, + {"Start time extension 32->64", "ecat.reg.dc.activation.stimeext", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x10, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation_stimecheck, + {"Start time chheck", "ecat.reg.dc.activation.stimecheck", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x20, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation_hlfrange, + {"Half range", "ecat.reg.dc.activation.hlfrange", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x40, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activation_dblrange, + {"Debug pulse", "ecat.reg.dc.activation.dblrange", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x80, NULL, HFILL } + }, + { &hf_ecat_reg_dc_cycimpuls, + {"DC CycImpulse (0x982)", "ecat.reg.dc.cycimpuls", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activationstat, + {"DC Activation status (0x984)", "ecat.reg.dc.activationstat", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activationstat_sync0pend, + {"SYNC 0 pending", "ecat.reg.dc.activationstat.sync0pend", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activationstat_sync1pend, + {"SYNC 1 pending", "ecat.reg.dc.activationstat.sync1pend", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_dc_activationstat_stimeoutofrange, + {"Start time out of range", "ecat.reg.dc.activationstat.stimeoutofrange", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_dc_sync0_status, + {"DC Sync0 Status (0x98e)", "ecat.reg.dc.sync0.status", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_sync0_status_triggered, + {"triggered", "ecat.reg.dc.sync0.status.triggered", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_sync1_status, + {"DC Sync0 Status1 (0x98f)", "ecat.reg.dc.sync1.status", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_sync1_status_triggered, + {"triggered", "ecat.reg.dc.sync1.status.triggered", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_starttime0, + {"DC StartTime0 (0x990)", "ecat.reg.dc.starttime0", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_starttime1, + {"DC StartTime1 (0x998)", "ecat.reg.dc.starttime1", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_cyctime0, + {"DC CycTime0 (0x9a0)", "ecat.reg.dc.cyctime0", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_cyctime1, + {"DC CycTime1 (0x9a4)", "ecat.reg.dc.cyctime1", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_ctrl, + {"DC Latch0 Ctrl (0x9a8)", "ecat.reg.dc.latch0.ctrl", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_ctrl_pos, + {"pos", "ecat.reg.dc.latch0.ctrl.pos", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_9A8E1), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_ctrl_neg, + {"neg", "ecat.reg.dc.latch0.ctrl.neg", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_9A8E1), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_ctrl, + {"DC Latch1 Ctrl (0x9a9)", "ecat.reg.dc.latch1.ctrl", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_ctrl_pos, + {"pos", "ecat.reg.dc.latch1.ctrl.pos", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_9A8E1), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_ctrl_neg, + {"neg", "ecat.reg.dc.latch1.ctrl.neg", + FT_BOOLEAN, 8, TFS(&tfs_esc_reg_9A8E1), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_status, + {"DC Latch0 Status (0x9ae)", "ecat.reg.dc.latch0.status", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_status_eventpos, + {"Event pos", "ecat.reg.dc.latch0.status.eventpos", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_status_eventneg, + {"Event neg", "ecat.reg.dc.latch0.status.eventneg", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_status_pinstate, + {"pin state", "ecat.reg.dc.latch0.status.pinstate", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_status, + {"DC Latch1 Status (0x9af)", "ecat.reg.dc.latch1.status", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_status_eventpos, + {"Event pos", "ecat.reg.dc.latch1.status.eventpos", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x01, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_status_eventneg, + {"Event neg", "ecat.reg.dc.latch1.status.eventneg", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x02, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_status_pinstate, + {"pin state", "ecat.reg.dc.latch1.status.pinstate", + FT_BOOLEAN, 8, TFS(&tfs_local_true_false), 0x04, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_pos, + {"DC Latch0 Pos (0x9b0)", "ecat.reg.dc.latch0.pos", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch0_neg, + {"DC Latch0 Neg (0x9b8)", "ecat.reg.dc.latch0.neg", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_pos, + {"DC Latch1 Pos (0x9c0)", "ecat.reg.dc.latch1.pos", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_latch1_neg, + {"DC Latch1 Neg (0x9c8)", "ecat.reg.dc.latch1.neg", + FT_UINT64, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_rcvsyncmanchg, + {"DC RecvSyncManChange (0x9f0)", "ecat.reg.dc.rcvsyncmanchg", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_pdismstart, + {"DC PdiSyncManStart (0x9f8)", "ecat.reg.dc.pdismstart", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + { &hf_ecat_reg_dc_pdismchg, + {"DC PdiSyncManChange (0x9fc)", "ecat.reg.dc.pdismchg", + FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL } + }, + }; + + static gint *ett[] = + { + &ett_ecat, + &ett_ecat_header, + &ett_ecat_dc, + &ett_ecat_length, + &ett_ecat_padding, + &ett_ecat_datagram_subtree, + &ett_ecat_reg_esc_features, + &ett_ecat_reg_dlctrl1, + &ett_ecat_reg_dlctrl2, + &ett_ecat_reg_dlctrl3, + &ett_ecat_reg_dlctrl4, + &ett_ecat_reg_dlstatus1, + &ett_ecat_reg_dlstatus2, + &ett_ecat_reg_alctrl, + &ett_ecat_reg_alstatus, + &ett_ecat_reg_pdictrl1, + &ett_ecat_reg_pdictrl2, + &ett_ecat_reg_ecat_mask, + &ett_ecat_reg_pdiL, + &ett_ecat_reg_ecat, + &ett_ecat_reg_pdi1, + &ett_ecat_reg_crc0, + &ett_ecat_reg_crc1, + &ett_ecat_reg_crc2, + &ett_ecat_reg_crc3, + &ett_ecat_reg_wd_status, + &ett_ecat_reg_eeprom_assign, + &ett_ecat_reg_ctrlstat, + &ett_ecat_reg_mio_ctrlstat, + &ett_ecat_mio_addr, + &ett_ecat_mio_access, + &ett_ecat_mio_status0, + &ett_ecat_mio_status1, + &ett_ecat_mio_status2, + &ett_ecat_mio_status3, + &ett_ecat_reg_fmmu, + &ett_ecat_reg_syncman, + &ett_ecat_reg_syncman_ctrlstatus, + &ett_ecat_reg_syncman_sm_enable, + &ett_ecat_reg_dc_cycunitctrl, + &ett_ecat_dc_activation, + &ett_ecat_dc_activationstat, + &ett_ecat_dc_sync0_status, + &ett_ecat_dc_sync1_status, + &ett_ecat_dc_latch0_ctrl, + &ett_ecat_dc_latch1_ctrl, + &ett_ecat_dc_latch0_status, + &ett_ecat_dc_latch1_status, + }; + + proto_ecat_datagram = proto_register_protocol("EtherCAT datagram(s)", "ECAT", "ecat"); + proto_register_field_array(proto_ecat_datagram, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + ecat_handle = register_dissector("ecat", dissect_ecat_datagram, proto_ecat_datagram); + + /* Sub dissector code */ + heur_subdissector_list = register_heur_dissector_list("ecat.data", proto_ecat_datagram); +} + +/* The registration hand-off routing */ +void proto_reg_handoff_ecat(void) +{ + /* Register this dissector as a sub dissector to EtherCAT frame based on + ether type. */ + dissector_add_uint("ecatf.type", 1 /* EtherCAT type */, ecat_handle); + + ecat_mailbox_handle = find_dissector_add_dependency("ecat_mailbox", proto_ecat_datagram); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 3 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=3 tabstop=8 expandtab: + * :indentSize=3:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/packet-ethercat-datagram.h b/plugins/epan/ethercat/packet-ethercat-datagram.h new file mode 100644 index 00000000..b1565cfe --- /dev/null +++ b/plugins/epan/ethercat/packet-ethercat-datagram.h @@ -0,0 +1,36 @@ +/* packet-ethercat-datagram.h + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef _PACKET_ETHERCAT_DATAGRAM_ +#define _PACKET_ETHERCAT_DATAGRAM_ + +/* structure for decoding the header -----------------------------------------*/ +typedef union +{ + struct + { + guint16 adp; + guint16 ado; + } a; + guint32 addr; +} EcParserAddrUnion; + +typedef struct _EcParser +{ + guint8 cmd; + guint8 idx; + EcParserAddrUnion anAddrUnion; + guint16 len; + guint16 intr; +} EcParserHDR, *PEcParserHDR; + +#define EcParserHDR_Len 10/*sizeof(EcParserHDR)*/ + +#endif /* _PACKET_ETHERCAT_DATAGRAM_ */ diff --git a/plugins/epan/ethercat/packet-ethercat-frame.c b/plugins/epan/ethercat/packet-ethercat-frame.c new file mode 100644 index 00000000..3de05942 --- /dev/null +++ b/plugins/epan/ethercat/packet-ethercat-frame.c @@ -0,0 +1,153 @@ +/* packet-ethercat-frame.c + * Routines for ethercat packet disassembly + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include + +#include "packet-ethercat-frame.h" + +void proto_register_ethercat_frame(void); +void proto_reg_handoff_ethercat_frame(void); + +/* Define the Ethercat frame proto */ +static int proto_ethercat_frame = -1; + +static dissector_table_t ethercat_frame_dissector_table; + +static dissector_handle_t ethercat_frame_handle; + +/* Define the tree for the EtherCAT frame */ +static int ett_ethercat_frame = -1; +static int hf_ethercat_frame_length = -1; +static int hf_ethercat_frame_reserved = -1; +static int hf_ethercat_frame_type = -1; + +static const value_string EthercatFrameTypes[] = +{ + { 1, "EtherCAT command", }, + { 2, "ADS", }, + { 3, "RAW-IO", }, + { 4, "NV", }, + { 5, "Mailbox"}, + { 0, NULL } +}; + +static const value_string ethercat_frame_reserved_vals[] = +{ + { 0, "Valid"}, + { 1, "Invalid (must be zero for conformance with the protocol specification)"}, + { 0, NULL} +}; + +/* Ethercat Frame */ +static int dissect_ethercat_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + tvbuff_t *next_tvb; + proto_item *ti; + proto_tree *ethercat_frame_tree; + gint offset = 0; + EtherCATFrameParserHDR hdr; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "ECATF"); + + col_clear(pinfo->cinfo, COL_INFO); + + if (tree) + { + ti = proto_tree_add_item(tree, proto_ethercat_frame, tvb, offset, EtherCATFrameParserHDR_Len, ENC_NA); + ethercat_frame_tree = proto_item_add_subtree(ti, ett_ethercat_frame); + + proto_tree_add_item(ethercat_frame_tree, hf_ethercat_frame_length, tvb, offset, EtherCATFrameParserHDR_Len, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ethercat_frame_tree, hf_ethercat_frame_reserved, tvb, offset, EtherCATFrameParserHDR_Len, ENC_LITTLE_ENDIAN); + proto_tree_add_item(ethercat_frame_tree, hf_ethercat_frame_type, tvb, offset, EtherCATFrameParserHDR_Len, ENC_LITTLE_ENDIAN); + } + hdr.hdr = tvb_get_letohs(tvb, offset); + offset = EtherCATFrameParserHDR_Len; + + /* The EtherCAT frame header has now been processed, allow sub dissectors to + handle the rest of the PDU. */ + next_tvb = tvb_new_subset_remaining (tvb, offset); + + if (!dissector_try_uint(ethercat_frame_dissector_table, hdr.v.protocol, + next_tvb, pinfo, tree)) + { + col_add_fstr (pinfo->cinfo, COL_PROTOCOL, "0x%04x", hdr.v.protocol); + /* No sub dissector wanted to handle this payload, decode it as general + data instead. */ + call_data_dissector(next_tvb, pinfo, tree); + } + return tvb_captured_length(tvb); +} + +void proto_register_ethercat_frame(void) +{ + static hf_register_info hf[] = + { + { &hf_ethercat_frame_length, + { "Length", "ecatf.length", + FT_UINT16, BASE_HEX, NULL, 0x07FF, + NULL, HFILL } + }, + + { &hf_ethercat_frame_reserved, + { "Reserved", "ecatf.reserved", + FT_UINT16, BASE_HEX, VALS(ethercat_frame_reserved_vals), 0x0800, + NULL, HFILL} + }, + + { &hf_ethercat_frame_type, + { "Type", "ecatf.type", + FT_UINT16, BASE_HEX, VALS(EthercatFrameTypes), 0xF000, + "E88A4 Types", HFILL } + } + }; + + static gint *ett[] = + { + &ett_ethercat_frame + }; + + proto_ethercat_frame = proto_register_protocol("EtherCAT frame header", "ETHERCAT", "ecatf"); + proto_register_field_array(proto_ethercat_frame,hf,array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + ethercat_frame_handle = register_dissector("ecatf", dissect_ethercat_frame, proto_ethercat_frame); + + /* Define a handle (ecatf.type) for sub dissectors that want to dissect + the Ethercat frame ether type (E88A4) payload. */ + ethercat_frame_dissector_table = register_dissector_table("ecatf.type", "EtherCAT frame type", + proto_ethercat_frame, FT_UINT8, BASE_DEC); +} + +void proto_reg_handoff_ethercat_frame(void) +{ + dissector_add_uint("ethertype", ETHERTYPE_ECATF, ethercat_frame_handle); + dissector_add_uint_with_preference("udp.port", ETHERTYPE_ECATF, ethercat_frame_handle); + dissector_add_uint_with_preference("tcp.port", ETHERTYPE_ECATF, ethercat_frame_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 3 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=3 tabstop=8 expandtab: + * :indentSize=3:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/packet-ethercat-frame.h b/plugins/epan/ethercat/packet-ethercat-frame.h new file mode 100644 index 00000000..2bb8c19b --- /dev/null +++ b/plugins/epan/ethercat/packet-ethercat-frame.h @@ -0,0 +1,33 @@ +/* paket-ethercat-frame.h + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef _PACKET_ETHERCAT_FRAME_H +#define _PACKET_ETHERCAT_FRAME_H + +#include + +/* structure for decoding the header -----------------------------------------*/ +DIAG_OFF_PEDANTIC +typedef union _EtherCATFrameParser +{ + struct + { + guint16 length : 11; + guint16 reserved : 1; + guint16 protocol : 4; + } v; + guint16 hdr; +} EtherCATFrameParserHDR; +DIAG_ON_PEDANTIC +typedef EtherCATFrameParserHDR *PEtherCATFrameParserHDR; + +#define EtherCATFrameParserHDR_Len (int)sizeof(EtherCATFrameParserHDR) + +#endif /* _PACKET_ETHERCAT_FRAME_H */ diff --git a/plugins/epan/ethercat/packet-ioraw.c b/plugins/epan/ethercat/packet-ioraw.c new file mode 100644 index 00000000..846ae01c --- /dev/null +++ b/plugins/epan/ethercat/packet-ioraw.c @@ -0,0 +1,119 @@ +/* packet-ioraw.c + * Routines for ethercat packet disassembly + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include + +#include "packet-ioraw.h" + +void proto_register_ioraw(void); +void proto_reg_handoff_ioraw(void); + +/* Define the ioraw proto */ +int proto_ioraw = -1; + +static int ett_ioraw = -1; + +static dissector_handle_t ioraw_handle; + +/* static int hf_ioraw_summary = -1; */ +static int hf_ioraw_header = -1; +static int hf_ioraw_data = -1; + +/*ioraw*/ +static void IoRawSummaryFormater( char *szText, int nMax) +{ + snprintf ( szText, nMax, "Raw IO Data" ); +} + +static int dissect_ioraw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_item *ti; + proto_tree *ioraw_tree; + gint offset = 0; + char szText[200]; + int nMax = sizeof(szText)-1; + + guint ioraw_length = tvb_reported_length(tvb); + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IO-RAW"); + + IoRawSummaryFormater(szText, nMax); + col_add_str(pinfo->cinfo, COL_INFO, szText); + + if (tree) + { + ti = proto_tree_add_item(tree, proto_ioraw, tvb, 0, -1, ENC_NA); + ioraw_tree = proto_item_add_subtree(ti, ett_ioraw); + + proto_item_append_text(ti,": %s",szText); + proto_tree_add_item(ioraw_tree, hf_ioraw_header, tvb, offset, IoRawParserHDR_Len, ENC_NA); + offset+=IoRawParserHDR_Len; + + proto_tree_add_item(ioraw_tree, hf_ioraw_data, tvb, offset, ioraw_length - offset, ENC_NA); + } + return tvb_captured_length(tvb); +} + +void proto_register_ioraw(void) +{ + static hf_register_info hf[] = + { +#if 0 + { &hf_ioraw_summary, + { "Summary of the IoRaw Packet", "ioraw.summary", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_ioraw_header, { "Header", "ioraw.header", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_ioraw_data, { "VarData", "ioraw.data", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + } + }; + + static gint *ett[] = + { + &ett_ioraw + }; + + proto_ioraw = proto_register_protocol("TwinCAT IO-RAW", + "IO-RAW","ioraw"); + proto_register_field_array(proto_ioraw,hf,array_length(hf)); + proto_register_subtree_array(ett,array_length(ett)); + ioraw_handle = register_dissector("ioraw", dissect_ioraw, proto_ioraw); +} + +void proto_reg_handoff_ioraw(void) +{ + dissector_add_uint("ecatf.type", 3, ioraw_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 3 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=3 tabstop=8 expandtab: + * :indentSize=3:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/packet-ioraw.h b/plugins/epan/ethercat/packet-ioraw.h new file mode 100644 index 00000000..48f942ef --- /dev/null +++ b/plugins/epan/ethercat/packet-ioraw.h @@ -0,0 +1,21 @@ +/* packet-ioraw.h + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef _PACKET_IORAW_H_ +#define _PACKET_IORAW_H_ + +/* headers are only used for size and offset calculation*/ +typedef struct _IoRawParser +{ + guint32 head; +} IoRawParserHDR, *PIoRawParserHDR; +#define IoRawParserHDR_Len (int)sizeof(IoRawParserHDR) + +#endif /* _PACKET_IORAW_H_*/ diff --git a/plugins/epan/ethercat/packet-nv.c b/plugins/epan/ethercat/packet-nv.c new file mode 100644 index 00000000..b9f5c0ce --- /dev/null +++ b/plugins/epan/ethercat/packet-nv.c @@ -0,0 +1,240 @@ +/* packet-nv.c + * Routines for ethercat packet disassembly + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include + +#include "packet-nv.h" + +void proto_register_nv(void); +void proto_reg_handoff_nv(void); + +/* Define the nv proto */ +int proto_nv = -1; + +static dissector_handle_t nv_handle; + +static int ett_nv = -1; +static int ett_nv_header = -1; +static int ett_nv_var = -1; +static int ett_nv_varheader = -1; + +/* static int hf_nv_summary = -1; */ +static int hf_nv_header = -1; +static int hf_nv_publisher = -1; +static int hf_nv_count = -1; +static int hf_nv_cycleindex = -1; +static int hf_nv_variable = -1; +static int hf_nv_varheader = -1; +static int hf_nv_id = -1; +static int hf_nv_hash = -1; +static int hf_nv_length = -1; +static int hf_nv_quality = -1; +static int hf_nv_data = -1; + +/*nv*/ +static void NvSummaryFormater(tvbuff_t *tvb, gint offset, char *szText, int nMax) +{ + guint32 nvOffset = offset; + + snprintf ( szText, nMax, "Network Vars from %d.%d.%d.%d.%d.%d - %d Var(s)", + tvb_get_guint8(tvb, nvOffset), + tvb_get_guint8(tvb, nvOffset+1), + tvb_get_guint8(tvb, nvOffset+2), + tvb_get_guint8(tvb, nvOffset+3), + tvb_get_guint8(tvb, nvOffset+4), + tvb_get_guint8(tvb, nvOffset+5), + tvb_get_letohs(tvb, nvOffset+6)); +} + +static void NvPublisherFormater(tvbuff_t *tvb, gint offset, char *szText, int nMax) +{ + guint32 nvOffset = offset; + + snprintf ( szText, nMax, "Publisher %d.%d.%d.%d.%d.%d", + tvb_get_guint8(tvb, nvOffset), + tvb_get_guint8(tvb, nvOffset+1), + tvb_get_guint8(tvb, nvOffset+2), + tvb_get_guint8(tvb, nvOffset+3), + tvb_get_guint8(tvb, nvOffset+4), + tvb_get_guint8(tvb, nvOffset+5)); +} + +static void NvVarHeaderFormater(tvbuff_t *tvb, gint offset, char *szText, int nMax) +{ + snprintf ( szText, nMax, "Variable - Id = %d, Length = %d", + tvb_get_letohs(tvb, offset), + tvb_get_letohs(tvb, offset+4)); +} + +static int dissect_nv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_item *ti; + proto_tree *nv_tree, *nv_header_tree, *nv_var_tree,*nv_varheader_tree; + gint offset = 0; + char szText[200]; + int nMax = (int)sizeof(szText)-1; + + gint i; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "TC-NV"); + + col_clear(pinfo->cinfo, COL_INFO); + + NvSummaryFormater(tvb, offset, szText, nMax); + col_append_str(pinfo->cinfo, COL_INFO, szText); + + if (tree) + { + guint16 nv_count; + + ti = proto_tree_add_item(tree, proto_nv, tvb, 0, -1, ENC_NA); + nv_tree = proto_item_add_subtree(ti, ett_nv); + proto_item_append_text(ti,": %s",szText); + + ti = proto_tree_add_item(nv_tree, hf_nv_header, tvb, offset, NvParserHDR_Len, ENC_NA); + + nv_header_tree = proto_item_add_subtree(ti, ett_nv_header); + + ti= proto_tree_add_item(nv_header_tree, hf_nv_publisher, tvb, offset, (int)sizeof(guint8)*6, ENC_NA); + NvPublisherFormater(tvb, offset, szText, nMax); + proto_item_set_text(ti, "%s", szText); + offset+=((int)sizeof(guint8)*6); + + proto_tree_add_item(nv_header_tree, hf_nv_count, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + nv_count = tvb_get_letohs(tvb, offset); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(nv_header_tree, hf_nv_cycleindex, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset = NvParserHDR_Len; + + for ( i=0; i < nv_count; i++ ) + { + guint16 var_length = tvb_get_letohs(tvb, offset+4); + + ti = proto_tree_add_item(nv_tree, hf_nv_variable, tvb, offset, ETYPE_88A4_NV_DATA_HEADER_Len+var_length, ENC_NA); + NvVarHeaderFormater(tvb, offset, szText, nMax); + proto_item_set_text(ti, "%s", szText); + + nv_var_tree = proto_item_add_subtree(ti, ett_nv_var); + ti = proto_tree_add_item(nv_var_tree, hf_nv_varheader, tvb, offset, ETYPE_88A4_NV_DATA_HEADER_Len, ENC_NA); + + nv_varheader_tree = proto_item_add_subtree(ti, ett_nv_varheader); + proto_tree_add_item(nv_varheader_tree, hf_nv_id, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(nv_varheader_tree, hf_nv_hash, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(nv_varheader_tree, hf_nv_length, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(nv_varheader_tree, hf_nv_quality, tvb, offset, (int)sizeof(guint16), ENC_LITTLE_ENDIAN); + offset+=(int)sizeof(guint16); + + proto_tree_add_item(nv_var_tree, hf_nv_data, tvb, offset, var_length, ENC_NA); + offset+=var_length; + } + } + return tvb_captured_length(tvb); +} + +void proto_register_nv(void) +{ + static hf_register_info hf[] = + { +#if 0 + { &hf_nv_summary, { "Summary of the Nv Packet", "tc_nv.summary", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_nv_header, { "Header", "tc_nv.header", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_publisher, { "Publisher", "tc_nv.publisher", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_count, { "Count", "tc_nv.count", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_cycleindex, { "CycleIndex", "tc_nv.cycleindex", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_variable, { "Variable", "tc_nv.variable", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_varheader, { "VarHeader", "tc_nv.varheader", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_id, { "Id", "tc_nv.id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_hash, { "Hash", "tc_nv.hash", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_length, { "Length", "tc_nv.length", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_quality, { "Quality", "tc_nv.quality", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_nv_data, { "Data", "tc_nv.data", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + }; + + static gint *ett[] = + { + &ett_nv, + &ett_nv_header, + &ett_nv_var, + &ett_nv_varheader + }; + + proto_nv = proto_register_protocol("TwinCAT NV", "TC-NV","tc_nv"); + proto_register_field_array(proto_nv,hf,array_length(hf)); + proto_register_subtree_array(ett,array_length(ett)); + nv_handle = register_dissector("tc_nv", dissect_nv, proto_nv); +} + +void proto_reg_handoff_nv(void) +{ + dissector_add_uint("ecatf.type", 4, nv_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 3 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=3 tabstop=8 expandtab: + * :indentSize=3:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/ethercat/packet-nv.h b/plugins/epan/ethercat/packet-nv.h new file mode 100644 index 00000000..14eaee03 --- /dev/null +++ b/plugins/epan/ethercat/packet-nv.h @@ -0,0 +1,34 @@ +/* packet-nv.h + * + * Copyright (c) 2007 by Beckhoff Automation GmbH + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef _PACKET_NV_H_ +#define _PACKET_NV_H_ + +/* Ensure the same data layout for all platforms*/ +typedef struct _ETYPE_88A4_NV_DATA_HEADER +{ + guint16 Id; + guint16 Hash; + guint16 Length; + guint16 Quality; +} ETYPE_88A4_NV_DATA_HEADER; +#define ETYPE_88A4_NV_DATA_HEADER_Len (int)sizeof(ETYPE_88A4_NV_DATA_HEADER) + +typedef struct _NvParserHDR +{ + guint8 Publisher[6]; + guint16 CountNV; + guint16 CycleIndex; + guint16 Reserved; +} NvParserHDR; +#define NvParserHDR_Len (int)sizeof(NvParserHDR) + +#endif /* _PACKET_NV_H_*/ diff --git a/plugins/epan/falco_bridge/AUTHORS b/plugins/epan/falco_bridge/AUTHORS new file mode 100644 index 00000000..2265263f --- /dev/null +++ b/plugins/epan/falco_bridge/AUTHORS @@ -0,0 +1,2 @@ +Author : +Loris Degioanni \ No newline at end of file diff --git a/plugins/epan/falco_bridge/CMakeLists.txt b/plugins/epan/falco_bridge/CMakeLists.txt new file mode 100644 index 00000000..384d81d2 --- /dev/null +++ b/plugins/epan/falco_bridge/CMakeLists.txt @@ -0,0 +1,82 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(falco-bridge 0 0 4 0) + +set(DISSECTOR_SRC + packet-falco-bridge.c + sinsp-span.cpp +) + +set(DISSECTOR_HEADERS + conversation-macros.h + sinsp-span.h +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_logray_plugin_library(falco-bridge epan) + +# XXX Hacks; need to fix in falcosecurity-libs. +target_compile_definitions(falco-bridge PRIVATE + HAVE_STRLCPY=1 + ) +# target_compile_options(falco-bridge PRIVATE -Wno-address-of-packed-member) + +target_include_directories(falco-bridge SYSTEM PRIVATE + ${SINSP_INCLUDE_DIRS} +) + +target_link_libraries(falco-bridge + epan + ${SINSP_LINK_LIBRARIES} +) + +install_plugin(falco-bridge epan) + +CHECKAPI( + NAME + falco-bridge + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/falco_bridge/README.md b/plugins/epan/falco_bridge/README.md new file mode 100644 index 00000000..d88276c7 --- /dev/null +++ b/plugins/epan/falco_bridge/README.md @@ -0,0 +1,56 @@ +# Falco Bridge + +This plugin is a bridge between [Falco plugins](https://github.com/falcosecurity/plugins/) and Wireshark, so that Falco plugins can be used as dissectors. +It requires [libsinsp and libscap](https://github.com/falcosecurity/libs/). + +## Building the Falco Bridge plugin + +1. Download and compile [libsinsp and libscap](https://github.com/falcosecurity/libs/). + You will probably want to pass `-DMINIMAL_BUILD=ON -DCREATE_TEST_TARGETS=OFF` to cmake. + +1. Configure Wireshark with + +``` +cmake \ + -DSINSP_INCLUDEDIR=/path/to/falcosecurity-libs \ + -DSINSP_LIBDIR=/path/to/falcosecurity-libs/ \ + -DFALCO_PLUGINS="/path/to/plugin1;/path/to/plugin2;/path/to/plugin3" \ + [other cmake args] +``` + +## Quick Start + +1. Create a directory named "falco" at the same level as the "epan" plugin folder. +You can find the global and per-user plugin folder locations on your system in About → Folders or in the [User's Guide](https://www.wireshark.org/docs/wsug_html_chunked/ChPluginFolders.html). + +1. Build your desired [Falco plugin](https://github.com/falcosecurity/plugins/) and place it in the "falco" plugin directory. + +## Conversations + +Falco plugins can mark individual fields with a conversation flag (EPF_CONVERSATION). +The Falco Bridge dissector treats each of these as separate conversations, and for features such as navigation and packet list marking, the _first_ conversation field is used for matching packets. + +## Licensing + +libsinsp and libscap are released under the Apache 2.0 license. +They depend on the following libraries: + +- b64: MIT +- c-ares: MIT +- curl: MIT +- GRPC: Apache 2.0 +- jq: MIT +- JsonCpp: MIT +- LuaJIT: MIT +- OpenSSL < 3.0: SSLeay +- OpenSSL >= 3.0 : Apache 2.0 +- Protobuf: BSD-3-Clause +- oneTBB: Apache 2.0 +- zlib: zlib + +Wireshark is released under the GPL version 2 (GPL-2.0-or-later). It and the Apache-2.0 license are compatible via the "any later version" provision in the GPL version 2. +As discussed at https://www.wireshark.org/lists/wireshark-dev/202203/msg00020.html, combining Wireshark and libsinsp+libscap should be OK, but that in effect invokes the GPLv2's "any later version" provision, making the Wireshark portion of the combined work GPLv3+. + +Debian would appear to concur: https://lists.debian.org/debian-legal/2014/08/msg00102.html. + +No version of the GPL is compatible with the SSLeay license; you must ensure that libsinsp+libscap is linked with OpenSSL 3.0 or later. diff --git a/plugins/epan/falco_bridge/packet-falco-bridge.c b/plugins/epan/falco_bridge/packet-falco-bridge.c new file mode 100644 index 00000000..81dbc6c1 --- /dev/null +++ b/plugins/epan/falco_bridge/packet-falco-bridge.c @@ -0,0 +1,676 @@ +/* packet-falco-bridge.c + * + * By Loris Degioanni + * Copyright (C) 2021 Sysdig, Inc. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +// To do: +// - Convert this to C++? It would let us get rid of the glue that is +// sinsp-span and make string handling a lot easier. However, +// epan/address.h and driver/ppm_events_public.h both define PT_NONE. +// - Add a configuration preference for configure_plugin? +// - Add a configuration preference for individual conversation filters vs ANDing them? +// We would need to add deregister_(|log_)conversation_filter before we implement this. + +#include "config.h" + +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sinsp-span.h" + +typedef enum bridge_field_flags_e { + BFF_NONE = 0, + BFF_HIDDEN = 1 << 1, // Unused + BFF_INFO = 1 << 2, + BFF_CONVERSATION = 1 << 3 +} bridge_field_flags_e; + +typedef struct conv_filter_info { + hf_register_info *field_info; + bool is_present; + wmem_strbuf_t *strbuf; +} conv_filter_info; + +typedef struct bridge_info { + sinsp_source_info_t *ssi; + uint32_t source_id; + int proto; + hf_register_info* hf; + int* hf_ids; + hf_register_info* hf_v4; + int *hf_v4_ids; + hf_register_info* hf_v6; + int *hf_v6_ids; + int* hf_id_to_addr_id; // Maps an hf offset to an hf_v[46] offset + uint32_t visible_fields; + uint32_t* field_flags; + int* field_ids; + uint32_t num_conversation_filters; + conv_filter_info *conversation_filters; +} bridge_info; + +static int proto_falco_bridge = -1; +static gint ett_falco_bridge = -1; +static gint ett_sinsp_span = -1; +static gint ett_address = -1; +static dissector_table_t ptype_dissector_table; + +static int dissect_falco_bridge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data); +static int dissect_sinsp_span(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_); + +/* + * Array of plugin bridges + */ +bridge_info* bridges = NULL; +guint nbridges = 0; +guint n_conv_fields = 0; + +/* + * sinsp extractor span + */ +sinsp_span_t *sinsp_span = NULL; + +/* + * Fields + */ +static int hf_sdp_source_id_size = -1; +static int hf_sdp_lengths = -1; +static int hf_sdp_source_id = -1; + +static hf_register_info hf[] = { + { &hf_sdp_source_id_size, + { "Plugin ID size", "falcobridge.id.size", + FT_UINT32, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_sdp_lengths, + { "Field Lengths", "falcobridge.lens", + FT_UINT32, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, + { &hf_sdp_source_id, + { "Plugin ID", "falcobridge.id", + FT_UINT32, BASE_DEC, + NULL, 0x0, + NULL, HFILL } + }, +}; + +// Returns true if the field might contain an IPv4 or IPv6 address. +// XXX This should probably be a preference. +static bool is_addr_field(const char *abbrev) { + if (strstr(abbrev, ".srcip")) { // ct.srcip + return true; + } else if (strstr(abbrev, ".client.ip")) { // okta.client.ip + return true; + } + return false; +} + +static gboolean +is_filter_valid(packet_info *pinfo, void *cfi_ptr) +{ + conv_filter_info *cfi = (conv_filter_info *)cfi_ptr; + + if (!cfi->is_present) { + return FALSE; + } + + int proto_id = proto_registrar_get_parent(cfi->field_info->hfinfo.id); + + if (proto_id < 0) { + return false; + } + + return proto_is_frame_protocol(pinfo->layers, proto_registrar_get_nth(proto_id)->abbrev); +} + +static gchar* +build_filter(packet_info *pinfo _U_, void *cfi_ptr) +{ + conv_filter_info *cfi = (conv_filter_info *)cfi_ptr; + + if (!cfi->is_present) { + return FALSE; + } + + return ws_strdup_printf("%s eq %s", cfi->field_info->hfinfo.abbrev, cfi->strbuf->str); +} + +void +configure_plugin(bridge_info* bi, char* config _U_) +{ + /* + * Initialize the plugin + */ + bi->source_id = get_sinsp_source_id(bi->ssi); + + size_t tot_fields = get_sinsp_source_nfields(bi->ssi); + bi->visible_fields = 0; + uint32_t addr_fields = 0; + sinsp_field_info_t sfi; + bi->num_conversation_filters = 0; + + for (size_t j = 0; j < tot_fields; j++) { + get_sinsp_source_field_info(bi->ssi, j, &sfi); + if (sfi.is_hidden) { + /* + * Skip the fields that are marked as hidden. + * XXX Should we keep them and call proto_item_set_hidden? + */ + continue; + } + if (sfi.type == SFT_STRINGZ && is_addr_field(sfi.abbrev)) { + addr_fields++; + } + bi->visible_fields++; + + if (sfi.is_conversation) { + bi->num_conversation_filters++; + } + } + + if (bi->visible_fields) { + bi->hf = (hf_register_info*)wmem_alloc(wmem_epan_scope(), bi->visible_fields * sizeof(hf_register_info)); + bi->hf_ids = (int*)wmem_alloc(wmem_epan_scope(), bi->visible_fields * sizeof(int)); + bi->field_ids = (int*)wmem_alloc(wmem_epan_scope(), bi->visible_fields * sizeof(int)); + bi->field_flags = (guint32*)wmem_alloc(wmem_epan_scope(), bi->visible_fields * sizeof(guint32)); + + if (addr_fields) { + bi->hf_id_to_addr_id = (int *)wmem_alloc(wmem_epan_scope(), bi->visible_fields * sizeof(int)); + bi->hf_v4 = (hf_register_info*)wmem_alloc(wmem_epan_scope(), addr_fields * sizeof(hf_register_info)); + bi->hf_v4_ids = (int*)wmem_alloc(wmem_epan_scope(), addr_fields * sizeof(int)); + bi->hf_v6 = (hf_register_info*)wmem_alloc(wmem_epan_scope(), addr_fields * sizeof(hf_register_info)); + bi->hf_v6_ids = (int*)wmem_alloc(wmem_epan_scope(), addr_fields * sizeof(int)); + } + + if (bi->num_conversation_filters) { + bi->conversation_filters = (conv_filter_info *)wmem_alloc(wmem_epan_scope(), bi->num_conversation_filters * sizeof (conv_filter_info)); + } + + uint32_t fld_cnt = 0; + size_t conv_fld_cnt = 0; + uint32_t addr_fld_cnt = 0; + + for (size_t j = 0; j < tot_fields; j++) + { + bi->hf_ids[fld_cnt] = -1; + bi->field_ids[fld_cnt] = (int) j; + bi->field_flags[fld_cnt] = BFF_NONE; + hf_register_info* ri = bi->hf + fld_cnt; + + get_sinsp_source_field_info(bi->ssi, j, &sfi); + + if (sfi.is_hidden) { + /* + * Skip the fields that are marked as hidden + */ + continue; + } + + enum ftenum ftype; + int fdisplay = BASE_NONE; + switch (sfi.type) { + case SFT_STRINGZ: + ftype = FT_STRINGZ; + break; + case SFT_UINT64: + ftype = FT_UINT64; + switch (sfi.display_format) { + case SFDF_DECIMAL: + fdisplay = BASE_DEC; + break; + case SFDF_HEXADECIMAL: + fdisplay = BASE_HEX; + break; + case SFDF_OCTAL: + fdisplay = BASE_OCT; + break; + default: + THROW_FORMATTED(DissectorError, "error in plugin %s: display format %s is not supported", + get_sinsp_source_name(bi->ssi), + sfi.abbrev); + } + break; + default: + THROW_FORMATTED(DissectorError, "error in plugin %s: type of field %s is not supported", + get_sinsp_source_name(bi->ssi), + sfi.abbrev); + } + + hf_register_info finfo = { + bi->hf_ids + fld_cnt, + { + wmem_strdup(wmem_epan_scope(), sfi.display), wmem_strdup(wmem_epan_scope(), sfi.abbrev), + ftype, fdisplay, + NULL, 0x0, + wmem_strdup(wmem_epan_scope(), sfi.description), HFILL + } + }; + *ri = finfo; + + if (sfi.is_conversation) { + bi->field_flags[fld_cnt] |= BFF_CONVERSATION; + bi->conversation_filters[conv_fld_cnt].field_info = ri; + bi->conversation_filters[conv_fld_cnt].strbuf = wmem_strbuf_new(wmem_epan_scope(), ""); + + const char *source_name = get_sinsp_source_name(bi->ssi); + const char *conv_filter_name = wmem_strdup_printf(wmem_epan_scope(), "%s %s", source_name, ri->hfinfo.name); + register_log_conversation_filter(source_name, conv_filter_name, is_filter_valid, build_filter, &bi->conversation_filters[conv_fld_cnt]); + if (conv_fld_cnt == 0) { + add_conversation_filter_protocol(source_name); + } + conv_fld_cnt++; + } + + if (sfi.is_info) { + bi->field_flags[fld_cnt] |= BFF_INFO; + } + + if (sfi.type == SFT_STRINGZ && is_addr_field(sfi.abbrev)) { + bi->hf_id_to_addr_id[fld_cnt] = addr_fld_cnt; + + bi->hf_v4_ids[addr_fld_cnt] = -1; + hf_register_info* ri_v4 = bi->hf_v4 + addr_fld_cnt; + hf_register_info finfo_v4 = { + bi->hf_v4_ids + addr_fld_cnt, + { + wmem_strdup_printf(wmem_epan_scope(), "%s (IPv4)", sfi.display), + wmem_strdup_printf(wmem_epan_scope(), "%s.v4", sfi.abbrev), + FT_IPv4, BASE_NONE, + NULL, 0x0, + wmem_strdup_printf(wmem_epan_scope(), "%s (IPv4)", sfi.description), HFILL + } + }; + *ri_v4 = finfo_v4; + + bi->hf_v6_ids[addr_fld_cnt] = -1; + hf_register_info* ri_v6 = bi->hf_v6 + addr_fld_cnt; + hf_register_info finfo_v6 = { + bi->hf_v6_ids + addr_fld_cnt, + { + wmem_strdup_printf(wmem_epan_scope(), "%s (IPv6)", sfi.display), + wmem_strdup_printf(wmem_epan_scope(), "%s.v6", sfi.abbrev), + FT_IPv4, BASE_NONE, + NULL, 0x0, + wmem_strdup_printf(wmem_epan_scope(), "%s (IPv6)", sfi.description), HFILL + } + }; + *ri_v6 = finfo_v6; + addr_fld_cnt++; + } else if (bi->hf_id_to_addr_id) { + bi->hf_id_to_addr_id[fld_cnt] = -1; + } + fld_cnt++; + } + proto_register_field_array(proto_falco_bridge, bi->hf, fld_cnt); + if (addr_fld_cnt) { + proto_register_field_array(proto_falco_bridge, bi->hf_v4, addr_fld_cnt); + proto_register_field_array(proto_falco_bridge, bi->hf_v6, addr_fld_cnt); + } + } +} + +void +import_plugin(char* fname) +{ + nbridges++; + bridge_info* bi = &bridges[nbridges - 1]; + + char *err_str = create_sinsp_source(sinsp_span, fname, &(bi->ssi)); + if (err_str) { + nbridges--; + report_failure("Unable to load sinsp plugin %s: %s.", fname, err_str); + g_free(err_str); + return; + } + + configure_plugin(bi, ""); + + const char *source_name = get_sinsp_source_name(bi->ssi); + const char *plugin_name = g_strdup_printf("%s Plugin", source_name); + bi->proto = proto_register_protocol ( + plugin_name, /* full name */ + source_name, /* short name */ + source_name /* filter_name */ + ); + + static dissector_handle_t ct_handle; + ct_handle = create_dissector_handle(dissect_sinsp_span, bi->proto); + dissector_add_uint("falcobridge.id", bi->source_id, ct_handle); +} + +static void +on_wireshark_exit(void) +{ + // XXX This currently crashes in a sinsp thread. + // destroy_sinsp_span(sinsp_span); + sinsp_span = NULL; +} + +void +proto_register_falcoplugin(void) +{ + proto_falco_bridge = proto_register_protocol ( + "Falco Bridge", /* name */ + "Falco Bridge", /* short name */ + "falcobridge" /* abbrev */ + ); + register_dissector("falcobridge", dissect_falco_bridge, proto_falco_bridge); + + /* + * Create the dissector table that we will use to route the dissection to + * the appropriate Falco plugin. + */ + ptype_dissector_table = register_dissector_table("falcobridge.id", + "Falco Bridge Plugin ID", proto_falco_bridge, FT_UINT32, BASE_DEC); + + /* + * Load the plugins + */ + WS_DIR *dir; + WS_DIRENT *file; + char *filename; + char *spdname = g_build_filename(get_plugins_dir_with_version(), "falco", NULL); + char *ppdname = g_build_filename(get_plugins_pers_dir_with_version(), "falco", NULL); + + /* + * We scan the plugins directory twice. The first time we count how many + * plugins we have, which we need to know in order to allocate the right + * amount of memory. The second time we actually load and configure + * each plugin. + */ + if ((dir = ws_dir_open(spdname, 0, NULL)) != NULL) { + while ((ws_dir_read_name(dir)) != NULL) { + nbridges++; + } + ws_dir_close(dir); + } + + if ((dir = ws_dir_open(ppdname, 0, NULL)) != NULL) { + while ((ws_dir_read_name(dir)) != NULL) { + nbridges++; + } + ws_dir_close(dir); + } + + sinsp_span = create_sinsp_span(); + + bridges = g_new0(bridge_info, nbridges); + nbridges = 0; + + if ((dir = ws_dir_open(spdname, 0, NULL)) != NULL) { + while ((file = ws_dir_read_name(dir)) != NULL) { + filename = g_build_filename(spdname, ws_dir_get_name(file), NULL); + import_plugin(filename); + g_free(filename); + } + ws_dir_close(dir); + } + + if ((dir = ws_dir_open(ppdname, 0, NULL)) != NULL) { + while ((file = ws_dir_read_name(dir)) != NULL) { + filename = g_build_filename(ppdname, ws_dir_get_name(file), NULL); + import_plugin(filename); + g_free(filename); + } + ws_dir_close(dir); + } + + g_free(spdname); + g_free(ppdname); + + /* + * Setup protocol subtree array + */ + static gint *ett[] = { + &ett_falco_bridge, + &ett_sinsp_span, + &ett_address, + }; + + proto_register_field_array(proto_falco_bridge, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_shutdown_routine(on_wireshark_exit); +} + +static bridge_info* +get_bridge_info(guint32 source_id) +{ + for(guint j = 0; j < nbridges; j++) + { + if(bridges[j].source_id == source_id) + { + return &bridges[j]; + } + } + + return NULL; +} + +static int +dissect_falco_bridge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "Falco Bridge"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo,COL_INFO); + + // https://github.com/falcosecurity/libs/blob/9c942f27/userspace/libscap/scap.c#L1900 + proto_item *ti = proto_tree_add_item(tree, proto_falco_bridge, tvb, 0, 12, ENC_NA); + proto_tree *fb_tree = proto_item_add_subtree(ti, ett_falco_bridge); + proto_tree_add_item(fb_tree, hf_sdp_source_id_size, tvb, 0, 4, ENC_LITTLE_ENDIAN); + proto_tree_add_item(fb_tree, hf_sdp_lengths, tvb, 4, 4, ENC_LITTLE_ENDIAN); + proto_item *idti = proto_tree_add_item(fb_tree, hf_sdp_source_id, tvb, 8, 4, ENC_LITTLE_ENDIAN); + + guint32 source_id = tvb_get_guint32(tvb, 8, ENC_LITTLE_ENDIAN); + bridge_info* bi = get_bridge_info(source_id); + col_add_fstr(pinfo->cinfo, COL_INFO, "Plugin ID: %u", source_id); + + if (bi == NULL) { + proto_item_append_text(idti, " (NOT SUPPORTED)"); + col_append_str(pinfo->cinfo, COL_INFO, " (NOT SUPPORTED)"); + return tvb_captured_length(tvb); + } + + const char *source_name = get_sinsp_source_name(bi->ssi); + proto_item_append_text(idti, " (%s)", source_name); + col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", source_name); + + dissector_handle_t dissector = dissector_get_uint_handle(ptype_dissector_table, source_id); + if (dissector) { + tvbuff_t* next_tvb = tvb_new_subset_length(tvb, 12, tvb_captured_length(tvb) - 12); + call_dissector_with_data(dissector, next_tvb, pinfo, tree, bi); + } + + return tvb_captured_length(tvb); +} + +static int +dissect_sinsp_span(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* bi_ptr) +{ + bridge_info* bi = (bridge_info *) bi_ptr; + guint plen = tvb_captured_length(tvb); + const char *source_name = get_sinsp_source_name(bi->ssi); + + col_set_str(pinfo->cinfo, COL_PROTOCOL, source_name); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo, COL_INFO); + + proto_item* ti = proto_tree_add_item(tree, bi->proto, tvb, 0, plen, ENC_NA); + proto_tree* fb_tree = proto_item_add_subtree(ti, ett_sinsp_span); + + guint8* payload = (guint8*)tvb_get_ptr(tvb, 0, plen); + + sinsp_field_extract_t *sinsp_fields = (sinsp_field_extract_t*) wmem_alloc(pinfo->pool, sizeof(sinsp_field_extract_t) * bi->visible_fields); + for (uint32_t fld_idx = 0; fld_idx < bi->visible_fields; fld_idx++) { + header_field_info* hfinfo = &(bi->hf[fld_idx].hfinfo); + sinsp_field_extract_t *sfe = &sinsp_fields[fld_idx]; + + sfe->field_id = bi->field_ids[fld_idx]; + sfe->field_name = hfinfo->abbrev; + sfe->type = hfinfo->type == FT_STRINGZ ? SFT_STRINGZ : SFT_UINT64; + } + + // If we have a failure, try to dissect what we can first, then bail out with an error. + bool rc = extract_sisnp_source_fields(bi->ssi, payload, plen, pinfo->pool, sinsp_fields, bi->visible_fields); + + if (!rc) { + REPORT_DISSECTOR_BUG("Falco plugin %s extract error: %s", get_sinsp_source_name(bi->ssi), get_sinsp_source_last_error(bi->ssi)); + } + + for (uint32_t idx = 0; idx < bi->num_conversation_filters; idx++) { + bi->conversation_filters[idx].is_present = false; + wmem_strbuf_truncate(bi->conversation_filters[idx].strbuf, 0); + } + + conversation_element_t *first_conv_els = NULL; // hfid + field val + CONVERSATION_LOG + + for (uint32_t fld_idx = 0; fld_idx < bi->visible_fields; fld_idx++) { + sinsp_field_extract_t *sfe = &sinsp_fields[fld_idx]; + header_field_info* hfinfo = &(bi->hf[fld_idx].hfinfo); + + if (!sfe->is_present) { + continue; + } + + conv_filter_info *cur_conv_filter = NULL; + conversation_element_t *cur_conv_els = NULL; + if ((bi->field_flags[fld_idx] & BFF_CONVERSATION) != 0) { + for (uint32_t cf_idx = 0; cf_idx < bi->num_conversation_filters; cf_idx++) { + if (&(bi->conversation_filters[cf_idx].field_info)->hfinfo == hfinfo) { + cur_conv_filter = &bi->conversation_filters[cf_idx]; + if (!first_conv_els) { + first_conv_els = wmem_alloc0(pinfo->pool, sizeof(conversation_element_t) * 3); + first_conv_els[0].type = CE_INT; + first_conv_els[0].int_val = hfinfo->id; + cur_conv_els = first_conv_els; + } + break; + } + } + } + + + if (sfe->type == SFT_STRINGZ && hfinfo->type == FT_STRINGZ) { + proto_item *pi = proto_tree_add_string(fb_tree, bi->hf_ids[fld_idx], tvb, 0, plen, sfe->res_str); + if (bi->field_flags[fld_idx] & BFF_INFO) { + col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s", sfe->res_str); + // Mark it hidden, otherwise we end up with a bunch of empty "Info" tree items. + proto_item_set_hidden(pi); + } + + int addr_fld_idx = bi->hf_id_to_addr_id[fld_idx]; + if (addr_fld_idx >= 0) { + ws_in4_addr v4_addr; + ws_in6_addr v6_addr; + proto_tree *addr_tree; + proto_item *addr_item = NULL; + if (ws_inet_pton4(sfe->res_str, &v4_addr)) { + addr_tree = proto_item_add_subtree(pi, ett_address); + addr_item = proto_tree_add_ipv4(addr_tree, bi->hf_v4_ids[addr_fld_idx], tvb, 0, 0, v4_addr); + set_address(&pinfo->net_src, AT_IPv4, sizeof(ws_in4_addr), &v4_addr); + } else if (ws_inet_pton6(sfe->res_str, &v6_addr)) { + addr_tree = proto_item_add_subtree(pi, ett_address); + addr_item = proto_tree_add_ipv6(addr_tree, bi->hf_v6_ids[addr_fld_idx], tvb, 0, 0, &v6_addr); + set_address(&pinfo->net_src, AT_IPv6, sizeof(ws_in6_addr), &v6_addr); + } + if (addr_item) { + proto_item_set_generated(addr_item); + } + if (cur_conv_filter) { + wmem_strbuf_append(cur_conv_filter->strbuf, sfe->res_str); + cur_conv_filter->is_present = true; + } + if (cur_conv_els) { + cur_conv_els[1].type = CE_ADDRESS; + copy_address(&cur_conv_els[1].addr_val, &pinfo->net_src); + } + } else { + if (cur_conv_filter) { + wmem_strbuf_append_printf(cur_conv_filter->strbuf, "\"%s\"", sfe->res_str); + cur_conv_filter->is_present = true; + } + if (cur_conv_els) { + cur_conv_els[1].type = CE_STRING; + cur_conv_els[1].str_val = wmem_strdup(pinfo->pool, sfe->res_str); + } + } + } + else if (sfe->type == SFT_UINT64 && hfinfo->type == FT_UINT64) { + proto_tree_add_uint64(fb_tree, bi->hf_ids[fld_idx], tvb, 0, plen, sfe->res_u64); + if (cur_conv_filter) { + switch (hfinfo->display) { + case BASE_HEX: + wmem_strbuf_append_printf(cur_conv_filter->strbuf, "%" PRIx64, sfe->res_u64); + break; + case BASE_OCT: + wmem_strbuf_append_printf(cur_conv_filter->strbuf, "%" PRIo64, sfe->res_u64); + break; + default: + wmem_strbuf_append_printf(cur_conv_filter->strbuf, "%" PRId64, sfe->res_u64); + } + cur_conv_filter->is_present = true; + } + + if (cur_conv_els) { + cur_conv_els[1].type = CE_UINT64; + cur_conv_els[1].uint64_val = sfe->res_u64; + } + } + else { + REPORT_DISSECTOR_BUG("Field %s has an unrecognized or mismatched type %u != %u", + hfinfo->abbrev, sfe->type, hfinfo->type); + } + } + + if (!rc) { + REPORT_DISSECTOR_BUG("Falco plugin %s extract error", get_sinsp_source_name(bi->ssi)); + } + + if (first_conv_els) { + first_conv_els[2].type = CE_CONVERSATION_TYPE; + first_conv_els[2].conversation_type_val = CONVERSATION_LOG; + pinfo->conv_elements = first_conv_els; +// conversation_t *conv = find_or_create_conversation(pinfo); +// if (!conv) { +// conversation_new_full(pinfo->fd->num, pinfo->conv_elements); +// } + } + + return plen; +} + +void +proto_reg_handoff_sdplugin(void) +{ +} diff --git a/plugins/epan/falco_bridge/sinsp-span.cpp b/plugins/epan/falco_bridge/sinsp-span.cpp new file mode 100644 index 00000000..eb2fc7e7 --- /dev/null +++ b/plugins/epan/falco_bridge/sinsp-span.cpp @@ -0,0 +1,239 @@ +/* sinsp-span.cpp + * + * By Gerald Combs + * Copyright (C) 2022 Sysdig, Inc. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include + +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4100) +#pragma warning(disable:4267) +#endif + +// epan/address.h and driver/ppm_events_public.h both define PT_NONE, so +// handle libsinsp calls here. + +typedef struct hf_register_info hf_register_info; + +typedef struct ss_plugin_info ss_plugin_info; + +#include "sinsp-span.h" + +#include + +typedef struct sinsp_source_info_t { + sinsp_plugin *source; + sinsp_evt *evt; + uint8_t *evt_storage; + size_t evt_storage_size; + const char *name; + const char *description; + char *last_error; + const char *fields; +} sinsp_source_info_t; + +typedef struct sinsp_span_t { + sinsp inspector; +} sinsp_span_t; + +sinsp_span_t *create_sinsp_span() +{ + return new(sinsp_span_t); +} + +void destroy_sinsp_span(sinsp_span_t *sinsp_span) { + delete(sinsp_span); +} + +/* + * Populate a source_plugin_info struct with the symbols coming from a library loaded via libsinsp + */ +char * +create_sinsp_source(sinsp_span_t *sinsp_span, const char* libname, sinsp_source_info_t **ssi_ptr) +{ + char *err_str = NULL; + sinsp_source_info_t *ssi = new sinsp_source_info_t(); + + try { + auto sp = sinsp_span->inspector.register_plugin(libname); + if (sp->caps() & CAP_EXTRACTION) { + ssi->source = dynamic_cast(sp.get()); + } else { + err_str = g_strdup_printf("%s has unsupported plugin capabilities 0x%02x", libname, sp->caps()); + } + } catch (const sinsp_exception& e) { + err_str = g_strdup_printf("Caught sinsp exception %s", e.what()); + } + + std::string init_err; + if (!err_str) { + if (!ssi->source->init("{}", init_err)) { + err_str = g_strdup_printf("Unable to initialize %s: %s", libname, init_err.c_str()); + } + } + + if (err_str) { + delete ssi; + return err_str; + } + + ssi->evt = new sinsp_evt(&sinsp_span->inspector); + ssi->evt_storage_size = 4096; + ssi->evt_storage = (uint8_t *) g_malloc(ssi->evt_storage_size); + ssi->name = strdup(ssi->source->name().c_str()); + ssi->description = strdup(ssi->source->description().c_str()); + *ssi_ptr = ssi; + return NULL; +} + +uint32_t get_sinsp_source_id(sinsp_source_info_t *ssi) +{ + return ssi->source->id(); +} + +const char *get_sinsp_source_last_error(sinsp_source_info_t *ssi) +{ + if (ssi->last_error) { + free(ssi->last_error); + } + ssi->last_error = strdup(ssi->source->get_last_error().c_str()); + return ssi->last_error; +} + +const char *get_sinsp_source_name(sinsp_source_info_t *ssi) +{ + return ssi->name; +} + +const char *get_sinsp_source_description(sinsp_source_info_t *ssi) +{ + return ssi->description; +} + +size_t get_sinsp_source_nfields(sinsp_source_info_t *ssi) +{ + return ssi->source->fields().size(); +} + +bool get_sinsp_source_field_info(sinsp_source_info_t *ssi, size_t field_num, sinsp_field_info_t *field) +{ + if (field_num >= ssi->source->fields().size()) { + return false; + } + + const filtercheck_field_info *ffi = &ssi->source->fields()[field_num]; + + switch (ffi->m_type) { + case PT_CHARBUF: + field->type = SFT_STRINGZ; + break; + case PT_UINT64: + field->type = SFT_UINT64; + break; + default: + field->type = SFT_UNKNOWN; + } + + switch (ffi->m_print_format) { + case PF_DEC: + field->display_format = SFDF_DECIMAL; + break; + case PF_HEX: + field->display_format = SFDF_HEXADECIMAL; + break; + case PF_OCT: + field->display_format = SFDF_OCTAL; + break; + default: + field->display_format = SFDF_UNKNOWN; + } + + g_strlcpy(field->abbrev, ffi->m_name, sizeof(ffi->m_name)); + g_strlcpy(field->display, ffi->m_display, sizeof(ffi->m_display)); + g_strlcpy(field->description, ffi->m_description, sizeof(ffi->m_description)); + + field->is_hidden = ffi->m_flags & EPF_TABLE_ONLY; + field->is_info = ffi->m_flags & EPF_INFO; + field->is_conversation = ffi->m_flags & EPF_CONVERSATION; + + return true; +} + +// The code below, falcosecurity/libs, and falcosecurity/plugins need to be in alignment. +// The Makefile in /plugins defines FALCOSECURITY_LIBS_REVISION and uses that version of +// plugin_info.h. We need to build against a compatible revision of /libs. +bool extract_sisnp_source_fields(sinsp_source_info_t *ssi, uint8_t *evt_data, uint32_t evt_datalen, wmem_allocator_t *pool, sinsp_field_extract_t *sinsp_fields, uint32_t sinsp_field_len) +{ + std::vector fields; + + // PPME_PLUGINEVENT_E events have the following format: + // | scap_evt header | uint32_t sizeof(id) = 4 | uint32_t evt_datalen | uint32_t id | uint8_t[] evt_data | + + uint32_t payload_hdr[3] = {4, evt_datalen, ssi->source->id()}; + uint32_t tot_evt_len = (uint32_t)sizeof(scap_evt) + sizeof(payload_hdr) + evt_datalen; + if (ssi->evt_storage_size < tot_evt_len) { + while (ssi->evt_storage_size < tot_evt_len) { + ssi->evt_storage_size *= 2; + } + ssi->evt_storage = (uint8_t *) g_realloc(ssi->evt_storage, ssi->evt_storage_size); + } + scap_evt *sevt = (scap_evt *) ssi->evt_storage; + + sevt->ts = -1; + sevt->tid = -1; + sevt->len = tot_evt_len; + sevt->type = PPME_PLUGINEVENT_E; + sevt->nparams = 2; // Plugin ID + evt_data + + memcpy(ssi->evt_storage + sizeof(scap_evt), payload_hdr, sizeof(payload_hdr)); + memcpy(ssi->evt_storage + sizeof(scap_evt) + sizeof(payload_hdr), evt_data, evt_datalen); + ssi->evt->init(ssi->evt_storage, 0); + + fields.resize(sinsp_field_len); + // We must supply field_id, field, arg, and type. + for (size_t i = 0; i < sinsp_field_len; i++) { + fields.at(i).field_id = sinsp_fields[i].field_id; + fields.at(i).field = sinsp_fields[i].field_name; + if (sinsp_fields[i].type == SFT_STRINGZ) { + fields.at(i).ftype = FTYPE_STRING; + } else { + fields.at(i).ftype = FTYPE_UINT64; + } + } + + bool status = true; + if (!ssi->source->extract_fields(ssi->evt, sinsp_field_len, fields.data())) { + status = false; + } + + for (size_t i = 0; i < sinsp_field_len; i++) { + sinsp_fields[i].is_present = fields.at(i).res_len > 0; + if (sinsp_fields[i].is_present) { + if (fields.at(i).ftype == PT_CHARBUF) { + sinsp_fields[i].res_str = wmem_strdup(pool, *fields.at(i).res.str); + } else if (fields.at(i).ftype == PT_UINT64) { + sinsp_fields[i].res_u64 = *fields.at(i).res.u64; + } else { + status = false; + } + } + } + return status; +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/plugins/epan/falco_bridge/sinsp-span.h b/plugins/epan/falco_bridge/sinsp-span.h new file mode 100644 index 00000000..2a474714 --- /dev/null +++ b/plugins/epan/falco_bridge/sinsp-span.h @@ -0,0 +1,80 @@ +/* sinsp-span.h + * + * By Gerald Combs + * Copyright (C) 2022 Sysdig, Inc. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __SINSP_SPAN_H__ +#define __SINSP_SPAN_H__ + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef struct sinsp_source_info_t sinsp_source_info_t; +typedef struct sinsp_span_t sinsp_span_t; + +typedef enum sinsp_field_type_e { + SFT_UNKNOWN, + SFT_STRINGZ, + SFT_UINT64, +} sinsp_field_type_e; + +typedef enum sinsp_field_display_format_e { + SFDF_UNKNOWN, + SFDF_DECIMAL, + SFDF_HEXADECIMAL, + SFDF_OCTAL +} sinsp_field_display_format_e; + +typedef struct sinsp_field_info_t { + sinsp_field_type_e type; + sinsp_field_display_format_e display_format; + char abbrev[64]; // filter name + char display[64]; // display name + char description[1024]; + bool is_hidden; + bool is_conversation; + bool is_info; +} sinsp_field_info_t; + +typedef struct sinsp_field_extract_t { + uint32_t field_id; // in + const char *field_name; // in + sinsp_field_type_e type; // in, out + bool is_present; // out + const char *res_str; // out + uint64_t res_u64; // out +} sinsp_field_extract_t; + +sinsp_span_t *create_sinsp_span(void); +void destroy_sinsp_span(sinsp_span_t *sinsp_span); + +char *create_sinsp_source(sinsp_span_t *sinsp_span, const char* libname, sinsp_source_info_t **ssi_ptr); + +// Extractor plugin routines. +// These roughly match common_plugin_info +uint32_t get_sinsp_source_id(sinsp_source_info_t *ssi); +const char *get_sinsp_source_last_error(sinsp_source_info_t *ssi); +const char *get_sinsp_source_name(sinsp_source_info_t *ssi); +const char* get_sinsp_source_description(sinsp_source_info_t *ssi); +size_t get_sinsp_source_nfields(sinsp_source_info_t *ssi); +bool get_sinsp_source_field_info(sinsp_source_info_t *ssi, size_t field_num, sinsp_field_info_t *field); +bool extract_sisnp_source_fields(sinsp_source_info_t *ssi, uint8_t *evt_data, uint32_t evt_datalen, wmem_allocator_t *pool, sinsp_field_extract_t *sinsp_fields, uint32_t sinsp_field_len); + + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // __SINSP_SPAN_H__ diff --git a/plugins/epan/gryphon/AUTHORS b/plugins/epan/gryphon/AUTHORS new file mode 100644 index 00000000..8f834e13 --- /dev/null +++ b/plugins/epan/gryphon/AUTHORS @@ -0,0 +1,8 @@ +Author : +Steve Limkemann + +Plugin conversion : +Olivier Abad + +Plugin conversion fixes and Gryphon Protocol additions: +Mark Ciechanowski diff --git a/plugins/epan/gryphon/CMakeLists.txt b/plugins/epan/gryphon/CMakeLists.txt new file mode 100644 index 00000000..e047c069 --- /dev/null +++ b/plugins/epan/gryphon/CMakeLists.txt @@ -0,0 +1,64 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(gryphon 0 0 4 0) + +set(DISSECTOR_SRC + packet-gryphon.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_wireshark_plugin_library(gryphon epan) + +target_link_libraries(gryphon epan) + +install_plugin(gryphon epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + gryphon + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/gryphon/README b/plugins/epan/gryphon/README new file mode 100644 index 00000000..1f954952 --- /dev/null +++ b/plugins/epan/gryphon/README @@ -0,0 +1,11 @@ +Dearborn Group Technology has released under GPL this plugin +for Wireshark. It decodes the protocol used by their Gryphon +and BEACON automotive network tool. + +The plugin decodes the communication protocol, but not any +vehicle network messages. + +Dearborn Group Technology can be found at https://www.dgtech.com +The author is Steve Limkemann , +with fixes and updates by Mark Ciechanowski + diff --git a/plugins/epan/gryphon/packet-gryphon.c b/plugins/epan/gryphon/packet-gryphon.c new file mode 100644 index 00000000..6df68a31 --- /dev/null +++ b/plugins/epan/gryphon/packet-gryphon.c @@ -0,0 +1,5332 @@ +/* packet-gryphon.c + * + * Updated routines for Gryphon protocol packet dissection + * By Mark C. + * Copyright (C) 2018 DG Technologies, Inc. (Dearborn Group, Inc.) USA + * + * Routines for Gryphon protocol packet disassembly + * By Steve Limkemann + * Copyright 1998 Steve Limkemann + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Specification: http://www.dgtech.com/product/gryphon/manual/html/GCprotocol/ + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include "packet-gryphon.h" + +/* + * See + * + * https://www.dgtech.com/product/gryphon/manual/html/GCprotocol/ + */ + +void proto_register_gryphon(void); +void proto_reg_handoff_gryphon(void); + +static dissector_handle_t gryphon_handle; + +#define GRYPHON_TCP_PORT 7000 /* Not IANA registed */ + +static int proto_gryphon = -1; + +static int hf_gryphon_src = -1; +static int hf_gryphon_srcchan = -1; +static int hf_gryphon_srcchanclient = -1; +static int hf_gryphon_dest = -1; +static int hf_gryphon_destchan = -1; +static int hf_gryphon_destchanclient = -1; +static int hf_gryphon_type = -1; +static int hf_gryphon_cmd = -1; +static int hf_gryphon_cmd_context = -1; +static int hf_gryphon_cmd_ioctl_context = -1; +static int hf_gryphon_data = -1; +static int hf_gryphon_data_length = -1; +static int hf_gryphon_reserved = -1; +static int hf_gryphon_padding = -1; +static int hf_gryphon_ignored = -1; +static int hf_gryphon_wait_flags = -1; +static int hf_gryphon_wait_resp = -1; +static int hf_gryphon_wait_prev_resp = -1; +static int hf_gryphon_status = -1; +static int hf_gryphon_response_in = -1; +static int hf_gryphon_response_to = -1; +static int hf_gryphon_response_time = -1; +static int hf_gryphon_data_header_length = -1; +static int hf_gryphon_data_header_length_bits = -1; +static int hf_gryphon_data_data_length = -1; +static int hf_gryphon_data_extra_data_length = -1; +static int hf_gryphon_data_mode = -1; +static int hf_gryphon_data_mode_transmitted = -1; +static int hf_gryphon_data_mode_receive = -1; +static int hf_gryphon_data_mode_local = -1; +static int hf_gryphon_data_mode_remote = -1; +static int hf_gryphon_data_mode_oneshot = -1; +static int hf_gryphon_data_mode_combined = -1; +static int hf_gryphon_data_mode_nomux = -1; +static int hf_gryphon_data_mode_internal = -1; +static int hf_gryphon_data_priority = -1; +static int hf_gryphon_data_error_status = -1; +static int hf_gryphon_data_time = -1; +static int hf_gryphon_data_context = -1; +static int hf_gryphon_data_header_data = -1; +static int hf_gryphon_data_data = -1; +static int hf_gryphon_data_extra_data = -1; +static int hf_gryphon_data_padding = -1; +static int hf_gryphon_event_id = -1; +static int hf_gryphon_event_context = -1; +static int hf_gryphon_event_time = -1; +static int hf_gryphon_event_data = -1; +static int hf_gryphon_event_padding = -1; +static int hf_gryphon_misc_text = -1; +static int hf_gryphon_misc_padding = -1; +static int hf_gryphon_eventnum = -1; +static int hf_gryphon_resp_time = -1; +static int hf_gryphon_setfilt = -1; +static int hf_gryphon_setfilt_length = -1; +static int hf_gryphon_setfilt_discard_data = -1; +static int hf_gryphon_setfilt_padding = -1; +static int hf_gryphon_ioctl = -1; +static int hf_gryphon_ioctl_nbytes = -1; +static int hf_gryphon_ioctl_data = -1; +static int hf_gryphon_addfilt_pass = -1; +static int hf_gryphon_addfilt_active = -1; +static int hf_gryphon_addfilt_blocks = -1; +static int hf_gryphon_addfilt_handle = -1; +static int hf_gryphon_modfilt = -1; +static int hf_gryphon_modfilt_action = -1; +static int hf_gryphon_filthan = -1; +static int hf_gryphon_filthan_id = -1; +static int hf_gryphon_filthan_padding = -1; +static int hf_gryphon_dfiltmode = -1; +static int hf_gryphon_filtmode = -1; +static int hf_gryphon_event_name = -1; +static int hf_gryphon_register_username = -1; +static int hf_gryphon_register_password = -1; +static int hf_gryphon_register_client_id = -1; +static int hf_gryphon_register_privileges = -1; +static int hf_gryphon_getspeeds_set_ioctl = -1; +static int hf_gryphon_getspeeds_get_ioctl = -1; +static int hf_gryphon_getspeeds_size = -1; +static int hf_gryphon_getspeeds_preset = -1; +static int hf_gryphon_getspeeds_data = -1; +static int hf_gryphon_cmd_sort = -1; +static int hf_gryphon_cmd_optimize = -1; +static int hf_gryphon_config_device_name = -1; +static int hf_gryphon_config_device_version = -1; +static int hf_gryphon_config_device_serial_number = -1; +static int hf_gryphon_config_num_channels = -1; +static int hf_gryphon_config_name_version_ext = -1; +static int hf_gryphon_config_driver_name = -1; +static int hf_gryphon_config_driver_version = -1; +static int hf_gryphon_config_device_security = -1; +static int hf_gryphon_config_max_data_length = -1; +static int hf_gryphon_config_min_data_length = -1; +static int hf_gryphon_config_hardware_serial_number = -1; +static int hf_gryphon_config_protocol_type = -1; +static int hf_gryphon_config_channel_id = -1; +static int hf_gryphon_config_card_slot_number = -1; +static int hf_gryphon_config_max_extra_data = -1; +static int hf_gryphon_config_min_extra_data = -1; +static int hf_gryphon_sched_num_iterations = -1; +static int hf_gryphon_sched_flags = -1; +static int hf_gryphon_sched_flags_scheduler = -1; +static int hf_gryphon_sched_sleep = -1; +static int hf_gryphon_sched_transmit_count = -1; +static int hf_gryphon_sched_transmit_period = -1; +static int hf_gryphon_sched_transmit_flags = -1; +static int hf_gryphon_sched_skip_transmit_period = -1; +static int hf_gryphon_sched_skip_sleep = -1; +static int hf_gryphon_sched_channel = -1; +static int hf_gryphon_sched_channel0 = -1; +static int hf_gryphon_sched_rep_id = -1; +static int hf_gryphon_sched_rep_message_index = -1; +static int hf_gryphon_blm_data_time = -1; +static int hf_gryphon_blm_data_bus_load = -1; +static int hf_gryphon_blm_data_current_bus_load = -1; +static int hf_gryphon_blm_data_peak_bus_load = -1; +static int hf_gryphon_blm_data_historic_peak_bus_load = -1; +static int hf_gryphon_blm_stat_receive_frame_count = -1; +static int hf_gryphon_blm_stat_transmit_frame_count = -1; +static int hf_gryphon_blm_stat_receive_dropped_frame_count = -1; +static int hf_gryphon_blm_stat_transmit_dropped_frame_count = -1; +static int hf_gryphon_blm_stat_receive_error_count = -1; +static int hf_gryphon_blm_stat_transmit_error_count = -1; +static int hf_gryphon_addresp_flags = -1; +static int hf_gryphon_addresp_flags_active = -1; +static int hf_gryphon_addresp_blocks = -1; +static int hf_gryphon_addresp_responses = -1; +static int hf_gryphon_addresp_old_handle = -1; +static int hf_gryphon_addresp_action = -1; +static int hf_gryphon_addresp_action_period = -1; +static int hf_gryphon_addresp_action_deact_on_event = -1; +static int hf_gryphon_addresp_action_deact_after_period = -1; +static int hf_gryphon_addresp_action_period_type = -1; +static int hf_gryphon_addresp_handle = -1; +static int hf_gryphon_ldf_list = -1; +static int hf_gryphon_ldf_number = -1; +static int hf_gryphon_ldf_nodenumber = -1; +static int hf_gryphon_ldf_remaining = -1; +static int hf_gryphon_ldf_name = -1; +static int hf_gryphon_ldf_info_pv = -1; +static int hf_gryphon_ldf_info_lv = -1; +static int hf_gryphon_ldf_ui = -1; +static int hf_gryphon_lin_nodename = -1; +static int hf_gryphon_lin_data_length = -1; +static int hf_gryphon_lin_slave_table_enable = -1; +static int hf_gryphon_lin_slave_table_cs = -1; +static int hf_gryphon_lin_slave_table_data = -1; +static int hf_gryphon_lin_slave_table_datacs = -1; +static int hf_gryphon_lin_masterevent = -1; +static int hf_gryphon_lin_numdata = -1; +static int hf_gryphon_lin_numextra = -1; +static int hf_gryphon_ldf_description = -1; +static int hf_gryphon_ldf_size = -1; +static int hf_gryphon_ldf_exists = -1; +static int hf_gryphon_ldf_blockn = -1; +static int hf_gryphon_ldf_file = -1; +static int hf_gryphon_ldf_desc_pad = -1; +static int hf_gryphon_ldf_restore_session = -1; +static int hf_gryphon_ldf_schedule_name = -1; +static int hf_gryphon_ldf_schedule_msg_dbytes = -1; +static int hf_gryphon_ldf_schedule_flags = -1; +static int hf_gryphon_ldf_schedule_event = -1; +static int hf_gryphon_ldf_schedule_sporadic = -1; +static int hf_gryphon_ldf_ioctl_setflags = -1; +static int hf_gryphon_ldf_numb_ids = -1; +static int hf_gryphon_ldf_bitrate = -1; +static int hf_gryphon_ldf_ioctl_setflags_flags = -1; +static int hf_gryphon_ldf_sched_size_place = -1; +static int hf_gryphon_ldf_sched_numb_place = -1; +static int hf_gryphon_ldf_sched_size = -1; +static int hf_gryphon_ldf_num_node_names = -1; +static int hf_gryphon_ldf_num_frames = -1; +static int hf_gryphon_ldf_num_signal_names = -1; +static int hf_gryphon_ldf_num_schedules = -1; +static int hf_gryphon_ldf_num_encodings = -1; +static int hf_gryphon_ldf_encoding_value = -1; +static int hf_gryphon_ldf_encoding_min = -1; +static int hf_gryphon_ldf_encoding_max = -1; +static int hf_gryphon_ldf_master_node_name = -1; +static int hf_gryphon_ldf_slave_node_name = -1; +static int hf_gryphon_ldf_node_name = -1; +static int hf_gryphon_ldf_signal_name = -1; +static int hf_gryphon_ldf_signal_encoding_name = -1; +static int hf_gryphon_ldf_signal_encoding_type = -1; +static int hf_gryphon_ldf_signal_encoding_logical = -1; +static int hf_gryphon_ldf_signal_offset = -1; +static int hf_gryphon_ldf_signal_length = -1; +static int hf_gryphon_ldf_get_frame = -1; +static int hf_gryphon_ldf_get_frame_num = -1; +static int hf_gryphon_ldf_get_frame_pub = -1; +static int hf_gryphon_ldf_get_frame_num_signals = -1; +static int hf_gryphon_cnvt_valuef = -1; +static int hf_gryphon_cnvt_valuei = -1; +static int hf_gryphon_cnvt_values = -1; +static int hf_gryphon_cnvt_units = -1; +static int hf_gryphon_cnvt_flags_getvalues = -1; +static int hf_gryphon_dd_stream = -1; +static int hf_gryphon_dd_value = -1; +static int hf_gryphon_dd_time = -1; +static int hf_gryphon_modresp_handle = -1; +static int hf_gryphon_modresp_action = -1; +static int hf_gryphon_num_resphan = -1; +static int hf_gryphon_handle = -1; +static int hf_gryphon_transmit_sched_id = -1; +static int hf_gryphon_desc_program_size = -1; +static int hf_gryphon_desc_program_name = -1; +static int hf_gryphon_desc_program_description = -1; +static int hf_gryphon_desc_flags = -1; +static int hf_gryphon_desc_flags_program = -1; +static int hf_gryphon_desc_handle = -1; +static int hf_gryphon_upload_block_number = -1; +static int hf_gryphon_upload_handle = -1; +static int hf_gryphon_upload_data = -1; +static int hf_gryphon_delete = -1; +static int hf_gryphon_list_block_number = -1; +static int hf_gryphon_list_num_programs = -1; +static int hf_gryphon_list_num_remain_programs = -1; +static int hf_gryphon_list_name = -1; +static int hf_gryphon_list_description = -1; +static int hf_gryphon_start_arguments = -1; +static int hf_gryphon_start_channel = -1; +static int hf_gryphon_status_num_running_copies = -1; +static int hf_gryphon_options_handle = -1; +static int hf_gryphon_files = -1; +static int hf_gryphon_usdt_flags_register = -1; +static int hf_gryphon_usdt_action_flags = -1; +static int hf_gryphon_usdt_action_flags_non_legacy = -1; +static int hf_gryphon_usdt_action_flags_register = -1; +static int hf_gryphon_usdt_action_flags_action = -1; +static int hf_gryphon_usdt_transmit_options_flags = -1; +static int hf_gryphon_usdt_transmit_options_flags_echo = -1; +static int hf_gryphon_usdt_transmit_options_done_event = -1; +static int hf_gryphon_usdt_transmit_options_echo_short = -1; +static int hf_gryphon_usdt_transmit_options_rx_nth_fc = -1; +static int hf_gryphon_usdt_transmit_options_action = -1; +static int hf_gryphon_usdt_transmit_options_send_done = -1; +static int hf_gryphon_usdt_receive_options_flags = -1; +static int hf_gryphon_usdt_receive_options_action = -1; +static int hf_gryphon_usdt_receive_options_firstframe_event = -1; +static int hf_gryphon_usdt_receive_options_lastframe_event = -1; +static int hf_gryphon_usdt_receive_options_tx_nth_fc = -1; +static int hf_gryphon_usdt_length_options_flags = -1; +static int hf_gryphon_usdt_length_control_j1939 = -1; +static int hf_gryphon_usdt_stmin_fc = -1; +static int hf_gryphon_usdt_bsmax_fc = -1; +static int hf_gryphon_usdt_stmin_override = -1; +static int hf_gryphon_usdt_stmin_override_active = -1; +static int hf_gryphon_usdt_stmin_override_activate = -1; +static int hf_gryphon_usdt_set_stmin_mul = -1; +static int hf_gryphon_usdt_receive_options_firstframe = -1; +static int hf_gryphon_usdt_receive_options_lastframe = -1; +static int hf_gryphon_usdt_ext_address = -1; +static int hf_gryphon_usdt_ext_address_id = -1; +static int hf_gryphon_usdt_block_size = -1; +static int hf_gryphon_bits_in_input1 = -1; +static int hf_gryphon_bits_in_input2 = -1; +static int hf_gryphon_bits_in_input3 = -1; +static int hf_gryphon_bits_in_pushbutton = -1; +static int hf_gryphon_bits_out_output1 = -1; +static int hf_gryphon_bits_out_output2 = -1; +static int hf_gryphon_init_strat_reset_limit = -1; +static int hf_gryphon_init_strat_delay = -1; +static int hf_gryphon_speed_baud_rate_index = -1; +static int hf_gryphon_filter_block_filter_start = -1; +static int hf_gryphon_filter_block_filter_length = -1; +static int hf_gryphon_filter_block_filter_type = -1; +static int hf_gryphon_filter_block_filter_operator = -1; +static int hf_gryphon_filter_block_filter_value1 = -1; +static int hf_gryphon_filter_block_filter_value2 = -1; +static int hf_gryphon_filter_block_filter_value4 = -1; +static int hf_gryphon_filter_block_filter_value_bytes = -1; +static int hf_gryphon_blm_mode = -1; +static int hf_gryphon_blm_mode_avg_period = -1; +static int hf_gryphon_blm_mode_avg_frames = -1; +static int hf_gryphon_command = -1; +static int hf_gryphon_cmd_mode = -1; +static int hf_gryphon_option = -1; +static int hf_gryphon_option_data = -1; +static int hf_gryphon_cmd_file = -1; +static int hf_gryphon_bit_in_digital_data = -1; +static int hf_gryphon_bit_out_digital_data = -1; +static int hf_gryphon_filter_block_pattern = -1; +static int hf_gryphon_filter_block_mask = -1; +static int hf_gryphon_usdt_request = -1; +static int hf_gryphon_usdt_request_ext = -1; +static int hf_gryphon_usdt_nids = -1; +static int hf_gryphon_usdt_response = -1; +static int hf_gryphon_usdt_response_ext = -1; +static int hf_gryphon_uudt_response = -1; +static int hf_gryphon_uudt_response_ext = -1; +static int hf_gryphon_more_filenames = -1; +static int hf_gryphon_filenames = -1; +static int hf_gryphon_program_channel_number = -1; +static int hf_gryphon_valid_header_length = -1; + +static gint ett_gryphon = -1; +static gint ett_gryphon_header = -1; +static gint ett_gryphon_body = -1; +static gint ett_gryphon_command_data = -1; +static gint ett_gryphon_response_data = -1; +static gint ett_gryphon_data_header = -1; +static gint ett_gryphon_flags = -1; +static gint ett_gryphon_data_body = -1; +static gint ett_gryphon_cmd_filter_block = -1; +static gint ett_gryphon_cmd_events_data = -1; +static gint ett_gryphon_cmd_config_device = -1; +static gint ett_gryphon_cmd_sched_data = -1; +static gint ett_gryphon_cmd_sched_cmd = -1; +static gint ett_gryphon_cmd_response_block = -1; +static gint ett_gryphon_pgm_list = -1; +static gint ett_gryphon_pgm_status = -1; +static gint ett_gryphon_pgm_options = -1; +static gint ett_gryphon_valid_headers = -1; +static gint ett_gryphon_usdt_data = -1; +static gint ett_gryphon_usdt_action_flags = -1; +static gint ett_gryphon_usdt_tx_options_flags = -1; +static gint ett_gryphon_usdt_rx_options_flags = -1; +static gint ett_gryphon_usdt_len_options_flags = -1; +static gint ett_gryphon_usdt_data_block = -1; +static gint ett_gryphon_lin_emulate_node = -1; +static gint ett_gryphon_ldf_block = -1; +static gint ett_gryphon_ldf_schedule_name = -1; +static gint ett_gryphon_lin_schedule_msg = -1; +static gint ett_gryphon_cnvt_getflags = -1; +static gint ett_gryphon_digital_data = -1; +static gint ett_gryphon_blm_mode = -1; + +static expert_field ei_gryphon_type = EI_INIT; + +/* desegmentation of Gryphon */ +static gboolean gryphon_desegment = TRUE; + +/* +* Length of the frame header. +*/ +#define GRYPHON_FRAME_HEADER_LEN 8 + +static int dissect_gryphon_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_msgresp_add); +static int cmd_ioctl(tvbuff_t*, packet_info*, int, proto_tree*, guint32 ui_command); +static int cmd_ioctl_resp(tvbuff_t*, packet_info*, int, proto_tree*, guint32 ui_command); + +static const value_string action_vals[] = { + { FR_RESP_AFTER_EVENT, + "Send response(s) for each conforming message" }, + { FR_RESP_AFTER_PERIOD, + "Send response(s) after the specified period expires following a conforming message" }, + { FR_IGNORE_DURING_PER, + "Send response(s) for a conforming message and ignore further messages until the specified period expires" }, + { 0, + NULL } +}; + +static const value_string deact_on_event_vals[] = { + { FR_DEACT_ON_EVENT, + "Deactivate this response for a conforming message" }, + { FR_DELETE|FR_DEACT_ON_EVENT, + "Delete this response for a conforming message" }, + { 0, + NULL } +}; + +static const value_string deact_after_per_vals[] = { + { FR_DEACT_AFTER_PER, + "Deactivate this response after the specified period following a conforming message" }, + { FR_DELETE|FR_DEACT_AFTER_PER, + "Delete this response after the specified period following a conforming message" }, + { 0, + NULL } +}; + +static const value_string cmd_optimize_type[] = { + {0, "Optimize for throughput (Nagle algorithm enabled)"}, + {1, "Optimize for latency (Nagle algorithm disabled)"}, + {0, NULL} +}; + +static const value_string usdt_action_vals[] = { + { 0, "Use 11 bit headers only" }, + { 1, "Use 29 bit headers only" }, + { 2, "Use both 11 & 29 bit headers" }, + { 3, "undefined" }, + { 0, NULL } +}; + +static const value_string xmit_opt_nth_fc_event[] = { + { 0, "Do not send a USDT_RX_NTH_FLOWCONTROL event when the 1st, 2nd, 3rd, etc. flow control message is received" }, + { 1, "Send a USDT_RX_NTH_FLOWCONTROL event when the 1st, 2nd, 3rd, etc. flow control message is received" }, + { 0, NULL } +}; + +static const value_string xmit_opt_echo_short[] = { + { 0, "Do not Echo short transmitted messages back to the client (message less than 8 bytes)" }, + { 1, "Echo short transmitted messages back to the client (message less than 8 bytes)" }, + { 0, NULL } +}; + +static const value_string xmit_opt_done[] = { + { 0, "Do not send a USDT_DONE event when the last frame of a multi-frame message is transmitted" }, + { 1, "Send a USDT_DONE event when the last frame of a multi-frame message is transmitted" }, + { 0, NULL } +}; + +static const value_string xmit_opt_vals[] = { + { 0, "Pad messages with less than 8 data bytes with 0x00's" }, + { 1, "Pad messages with less than 8 data bytes with 0xFF's" }, + { 2, "Do not pad messages with less than 8 data bytes" }, + { 3, "undefined" }, + { 0, NULL } +}; + +static const value_string xmit_opt_echo_long[] = { + { 0, "Do not Echo long transmitted messages back to the client (message longer than 6 or 7 bytes)" }, + { 1, "Echo long transmitted messages back to the client (message longer than 6 or 7 bytes)" }, + { 0, NULL } +}; + + +static const value_string recv_opt_nth_fc_event[] = { + { 0, "Do not send a USDT_TX_NTH_FLOWCONTROL event when the 1st, 2nd, 3rd, etc. flow control message is sent" }, + { 1, "Send a USDT_TX_NTH_FLOWCONTROL event when the 1st, 2nd, 3rd, etc. flow control message is sent" }, + { 0, NULL } +}; +static const value_string recv_opt_lastframe_event[] = { + { 0, "Do not send a USDT_LASTFRAME event when the last frame of a multi-frame message is received" }, + { 1, "Send a USDT_LASTFRAME event when the last frame of a multi-frame message is received" }, + { 0, NULL } +}; +static const value_string recv_opt_firstframe_event[] = { + { 0, "Do not send a USDT_FIRSTFRAME event when the first frame of a multi-frame message is received" }, + { 1, "Send a USDT_FIRSTFRAME event when the first frame of a multi-frame message is received" }, + { 0, NULL } +}; + +static const value_string recv_opt_j1939[] = { + { 0, "Treat the length as a regular 4-byte size in calculating the multi-ID block range (not J1939-style)" }, + { 1, "Use J1939-style length (the source and destination bytes are swapped in response (for 29-bit ID/headers only))" }, + { 2, "undefined" }, + { 0, NULL } +}; + +static const value_string recv_opt_vals[] = { + { 0, "Do not verify the integrity of long received messages and do not send them to the client" }, + { 1, "Verify the integrity of long received messages and send them to the client" }, + { 2, "Verify the integrity of long received messages but do not send them to the client" }, + { 3, "undefined" }, + { 0, NULL } +}; + +static const value_string register_unregister [] = { + { 0, "Unregister" }, + { 1, "Register" }, + { 0, NULL } +}; + +static const value_string ldf_exists[] = { + { 0, "Name is OK, does not already exist" }, + { 1, "*** Warning ***: LDF file with same name already exists" }, + { 0, NULL } +}; + +static const value_string lin_slave_table_enable[] = { + { 0, "Disabled" }, + { 1, "Enabled" }, + { 2, "One-shot enabled" }, + { 0, NULL } +}; + +static const value_string lin_slave_table_cs[] = { + { 0, "Good" }, + { 1, "Bad" }, + { 0, NULL } +}; + +static const value_string lin_ldf_ioctl_setflags[] = { + {0, "Clear all flags first"}, + {1, "Leave existing flags intact"}, + {0, NULL} +}; +static const value_string lin_cnvt_getflags[] = { + {1, "Float value"}, + {2, "Int value"}, + {3, "Float and Int value"}, + {4, "String value"}, + {5, "Float and String value"}, + {6, "Int and String value"}, + {7, "Float, Int, and String value"}, + {0, NULL} +}; + +static const value_string lin_ioctl_masterevent[] = { + {0, "LIN driver will not send an event on master schedule start-of-cycle"}, + {1, "LIN driver will send an event on master schedule start-of-cycle"}, + {0, NULL} +}; + +static const value_string blm_mode_vals[] = { + { 0, "Off" }, + { 1, "Average over time" }, + { 2, "Average over frame count" }, + { 0, NULL } +}; + +static const value_string dmodes[] = { + {DEFAULT_FILTER_BLOCK, "Block"}, + {DEFAULT_FILTER_PASS, "Pass"}, + {0, NULL}, +}; + +static const value_string frame_type[] = { + {0, ""}, + {1, "Command request"}, + {2, "Command response"}, + {3, "Network (vehicle) data"}, + {4, "Event"}, + {5, "Miscellaneous"}, + {6, "Text string"}, + {7, "Signal (vehicle) network"}, + {0, NULL} +}; + +static const value_string src_dest[] = { + {SD_CARD, "Card"}, + {SD_SERVER, "Server"}, + {SD_CLIENT, "Client"}, + {SD_SCHED, "Scheduler"}, + {SD_SCRIPT, "Script Processor"}, + {SD_PGM, "Program Loader"}, + {SD_USDT, "USDT Server"}, + {SD_BLM, "Bus Load Monitoring"}, + {SD_LIN, "LIN LDF Server"}, /* 20171031 mc */ + {SD_FLIGHT, "Flight Recorder / Data Logger"}, + {SD_RESP, "Message Responder"}, + {SD_IOPWR, "I/O and power"}, + {SD_UTIL, "Utility/Miscellaneous"}, + {SD_CNVT, "Signal Conversion Utility"}, /* 20171031 mc */ + {0, NULL} +}; + +/* 20180305 use with BASE_SPECIAL_VALS */ +static const value_string channel_or_broadcast[] = { + {CH_BROADCAST, "Broadcast"}, + {0, NULL} +}; + +static const value_string cmd_vals[] = { + { CMD_INIT, "Initialize" }, + { CMD_GET_STAT, "Get status" }, + { CMD_GET_CONFIG, "Get configuration" }, + { CMD_EVENT_ENABLE, "Enable event" }, + { CMD_EVENT_DISABLE, "Disable event" }, + { CMD_GET_TIME, "Get time" }, + { CMD_GET_RXDROP, "Get number of dropped RX messages" }, + { CMD_RESET_RXDROP, "Clear number of dropped RX messages" }, + { CMD_BCAST_ON, "Set broadcasts on" }, + { CMD_BCAST_OFF, "Set broadcasts off" }, + { CMD_SET_TIME, "Set time" }, + { CMD_CARD_SET_SPEED, "Set channel baud rate" }, + { CMD_CARD_GET_SPEED, "Get channel baud rate" }, + { CMD_CARD_SET_FILTER, "Set filter (deprecated)" }, + { CMD_CARD_GET_FILTER, "Get filter" }, + { CMD_CARD_TX, "Transmit message" }, + { CMD_CARD_TX_LOOP_ON, "Set transmit loopback on" }, + { CMD_CARD_TX_LOOP_OFF, "Set transmit loopback off" }, + { CMD_CARD_IOCTL, "IOCTL pass-through" }, + { CMD_CARD_ADD_FILTER, "Add a filter" }, + { CMD_CARD_MODIFY_FILTER, "Modify a filter" }, + { CMD_CARD_GET_FILTER_HANDLES, "Get filter handles" }, + { CMD_CARD_SET_DEFAULT_FILTER, "Set default filter" }, + { CMD_CARD_GET_DEFAULT_FILTER, "Get default filter mode" }, + { CMD_CARD_SET_FILTER_MODE, "Set filter mode" }, + { CMD_CARD_GET_FILTER_MODE, "Get filter mode" }, + { CMD_CARD_GET_EVNAMES, "Get event names" }, + { CMD_CARD_GET_SPEEDS, "Get defined speeds" }, + { CMD_SERVER_REG, "Register with server" }, + { CMD_SERVER_SET_SORT, "Set the sorting behavior" }, + { CMD_SERVER_SET_OPT, "Set the type of optimization" }, + { CMD_PGM_START2, "Start an uploaded program" }, + { CMD_SCHED_TX, "Schedule transmission of messages" }, + { CMD_SCHED_KILL_TX, "Stop and destroy a message schedule transmission" }, + { CMD_SCHED_MSG_REPLACE, "Replace a scheduled message" }, + { CMD_PGM_DESC, "Describe program to be uploaded" }, + { CMD_PGM_UPLOAD, "Upload a program to the Gryphon" }, + { CMD_PGM_DELETE, "Delete an uploaded program" }, + { CMD_PGM_LIST, "Get a list of uploaded programs" }, + { CMD_PGM_START, "Start an uploaded program" }, + { CMD_PGM_STOP, "Stop an uploaded program" }, + { CMD_PGM_STATUS, "Get status of an uploaded program" }, + { CMD_PGM_OPTIONS, "Set program upload options" }, + { CMD_PGM_FILES, "Get a list of files & directories" }, + { CMD_USDT_REGISTER, "Register/Unregister with USDT server (deprecated)" }, + { CMD_USDT_SET_FUNCTIONAL, "Set IDs to use extended addressing (deprecated)" }, + { CMD_USDT_SET_STMIN_MULT, "Set USDT STMIN multiplier" }, + { CMD_USDT_SET_STMIN_FC, "Set USDT STMIN flow control (new command July 2017)" }, + { CMD_USDT_GET_STMIN_FC, "Get USDT STMIN flow control (new command July 2017)" }, + { CMD_USDT_SET_BSMAX_FC, "Set USDT BSMAX flow control (new command July 2017)" }, + { CMD_USDT_GET_BSMAX_FC, "Get USDT BSMAX flow control (new command July 2017)" }, + { CMD_USDT_REGISTER_NON_LEGACY, "Register/Unregister with USDT (ISO-15765) server, non-legacy (new command July 2017)" }, + { CMD_USDT_SET_STMIN_OVERRIDE, "Set USDT STMIN override (new command July 2017)" }, + { CMD_USDT_GET_STMIN_OVERRIDE, "Get USDT STMIN override (new command July 2017)" }, + { CMD_USDT_ACTIVATE_STMIN_OVERRIDE, "Activate/deactivate USDT STMIN override (new command July 2017)" }, + { CMD_BLM_SET_MODE, "Set Bus Load Monitoring mode" }, + { CMD_BLM_GET_MODE, "Get Bus Load Monitoring mode" }, + { CMD_BLM_GET_DATA, "Get Bus Load data" }, + { CMD_BLM_GET_STATS, "Get Bus Load statistics" }, + { CMD_GET_FRAMES, "Get frames defined in the LIN LDF file" }, + { CMD_LDF_DESC, "Set Name and description of LIN LDF file" }, + { CMD_LDF_UPLOAD, "Upload a LIN LDF file to the Gryphon" }, + { CMD_LDF_LIST, "Get list of loaded LIN LDFs" }, + { CMD_LDF_DELETE, "Delete LIN LDF" }, + { CMD_LDF_PARSE, "Parse an uploaded LIN LDF file" }, + { CMD_GET_LDF_INFO, "Get info of a parsed LDF file" }, + { CMD_GET_NODE_NAMES, "Get names of nodes defined in the LIN LDF file" }, + { CMD_EMULATE_NODES, "Emulate LIN nodes" }, + { CMD_GET_FRAME_INFO, "Get info from a frame defined in the LIN LDF file" }, + { CMD_GET_SIGNAL_INFO, "Get info from a signal defined in the LIN LDF file" }, + { CMD_GET_SIGNAL_DETAIL, "Get details from a signal defined in the LIN LDF file" }, + { CMD_GET_ENCODING_INFO, "Get details from an encoding name defined in the LIN LDF file" }, + { CMD_GET_SCHEDULES, "Get schedules of the LIN LDF file" }, + { CMD_START_SCHEDULE, "Start a LIN schedule from the LIN LDF file" }, + { CMD_SAVE_SESSION, "Save an internal representation of the LIN LDF file" }, + { CMD_RESTORE_SESSION, "Restore a previously saved LIN LDF session" }, + { CMD_GET_NODE_SIGNALS, "Get signal names of the node defined in the LIN LDF file" }, + { CMD_FLIGHT_GET_CONFIG, "Get flight recorder channel info" }, + { CMD_FLIGHT_START_MON, "Start flight recorder monitoring" }, + { CMD_FLIGHT_STOP_MON, "Stop flight recorder monitoring" }, + { CMD_MSGRESP_ADD, "Add response message" }, + { CMD_MSGRESP_GET, "Get response message" }, + { CMD_MSGRESP_MODIFY, "Modify response message state" }, + { CMD_MSGRESP_GET_HANDLES, "Get response message handles" }, + { CMD_IOPWR_GETINP, "Read current digital inputs" }, + { CMD_IOPWR_GETLATCH, "Read latched digital inputs" }, + { CMD_IOPWR_CLRLATCH, "Read & clear latched digital inputs" }, + { CMD_IOPWR_GETOUT, "Read digital outputs" }, + { CMD_IOPWR_SETOUT, "Write digital outputs" }, + { CMD_IOPWR_SETBIT, "Set indicated output bits" }, + { CMD_IOPWR_CLRBIT, "Clear indicated output bits" }, + { CMD_IOPWR_GETPOWER, "Read digital inputs at power on time" }, + { CMD_UTIL_SET_INIT_STRATEGY, "Set initialization strategy" }, + { CMD_UTIL_GET_INIT_STRATEGY, "Get initialization strategy" }, + { CMD_CNVT_GET_VALUES, "Read one or more signal values from LIN Signal Conversion" }, + { CMD_CNVT_GET_UNITS, "Read one or more signal units from LIN Signal Conversion" }, + { CMD_CNVT_SET_VALUES, "Write one or more signal values for LIN Signal Conversion" }, + { CMD_CNVT_DESTROY_SESSION, "Destroy internal LIN Signal Conversion info" }, + { CMD_CNVT_SAVE_SESSION, "Save an internal representation of the LIN Signal Conversion" }, + { CMD_CNVT_RESTORE_SESSION, "Restore a previously saved LIN Signal Conversion session" }, + { CMD_CNVT_GET_NODE_SIGNALS, "Get signal names of the node defined in the LIN Signal Conversion Session" }, + { 0, NULL}, +}; + +static value_string_ext cmd_vals_ext = VALUE_STRING_EXT_INIT(cmd_vals); + +static const value_string responses_vs[] = { + {RESP_OK, "OK - no error"}, + {RESP_UNKNOWN_ERR, "Unknown error"}, + {RESP_UNKNOWN_CMD, "Unrecognised command"}, + {RESP_UNSUPPORTED, "Unsupported command"}, + {RESP_INVAL_CHAN, "Invalid channel specified"}, + {RESP_INVAL_DST, "Invalid destination"}, + {RESP_INVAL_PARAM, "Invalid parameter(s)"}, + {RESP_INVAL_MSG, "Invalid message"}, + {RESP_INVAL_LEN, "Invalid length field"}, + {RESP_TX_FAIL, "Transmit failed"}, + {RESP_RX_FAIL, "Receive failed"}, + {RESP_AUTH_FAIL, "Authorization failed"}, + {RESP_MEM_ALLOC_ERR, "Memory allocation error"}, + {RESP_TIMEOUT, "Command timed out"}, + {RESP_UNAVAILABLE, "Unavailable"}, + {RESP_BUF_FULL, "Buffer full"}, + {RESP_NO_SUCH_JOB, "No such job"}, + {0, NULL}, +}; + +static const value_string filter_data_types[] = { + {FILTER_DATA_TYPE_HEADER_FRAME, "frame header"}, + {FILTER_DATA_TYPE_HEADER, "data message header"}, + {FILTER_DATA_TYPE_DATA, "data message data"}, + {FILTER_DATA_TYPE_EXTRA_DATA, "data message extra data"}, + {FILTER_EVENT_TYPE_HEADER, "event message header"}, + {FILTER_EVENT_TYPE_DATA, "event message"}, + {0, NULL}, +}; + +static const value_string operators[] = { + {BIT_FIELD_CHECK, "Bit field check"}, + {SVALUE_GT, "Greater than (signed)"}, + {SVALUE_GE, "Greater than or equal to (signed)"}, + {SVALUE_LT, "Less than (signed)"}, + {SVALUE_LE, "Less than or equal to (signed)"}, + {VALUE_EQ, "Equal to"}, + {VALUE_NE, "Not equal to"}, + {UVALUE_GT, "Greater than (unsigned)"}, + {UVALUE_GE, "Greater than or equal to (unsigned)"}, + {UVALUE_LT, "Less than (unsigned)"}, + {UVALUE_LE, "Less than or equal to (unsigned)"}, + {DIG_LOW_TO_HIGH, "Digital, low to high transition"}, + {DIG_HIGH_TO_LOW, "Digital, high to low transition"}, + {DIG_TRANSITION, "Digital, change of state"}, + {0, NULL}, +}; + +static const value_string modes[] = { + {FILTER_OFF_PASS_ALL, "Filter off, pass all messages"}, + {FILTER_OFF_BLOCK_ALL, "Filter off, block all messages"}, + {FILTER_ON, "Filter on"}, + {0, NULL}, +}; + +static const value_string filtacts[] = { + {DELETE_FILTER, "Delete"}, + {ACTIVATE_FILTER, "Activate"}, + {DEACTIVATE_FILTER, "Deactivate"}, + {0, NULL}, +}; + +static const value_string ioctls[] = { + {GINIT, "GINIT: Initialize"}, + {GLOOPON, "GLOOPON: Loop on"}, + {GLOOPOFF, "GLOOPOFF: Loop off"}, + {GGETHWTYPE, "GGETHWTYPE: Get hardware type"}, + {GGETREG, "GGETREG: Get register"}, + {GSETREG, "GSETREG: Set register"}, + {GGETRXCOUNT, "GGETRXCOUNT: Get the receive message counter"}, + {GSETRXCOUNT, "GSETRXCOUNT: Set the receive message counter"}, + {GGETTXCOUNT, "GGETTXCOUNT: Get the transmit message counter"}, + {GSETTXCOUNT, "GSETTXCOUNT: Set the transmit message counter"}, + {GGETRXDROP, "GGETRXDROP: Get the number of dropped receive messages"}, + {GSETRXDROP, "GSETRXDROP: Set the number of dropped receive messages"}, + {GGETTXDROP, "GGETTXDROP: Get the number of dropped transmit messages"}, + {GSETTXDROP, "GSETTXDROP: Set the number of dropped transmit messages"}, + {GGETRXBAD, "GGETRXBAD: Get the number of bad receive messages"}, + {GGETTXBAD, "GGETTXBAD: Get the number of bad transmit messages"}, + {GGETCOUNTS, "GGETCOUNTS: Get total message counter"}, + {GGETBLMON, "GGETBLMON: Get bus load monitoring status"}, + {GSETBLMON, "GSETBLMON: Set bus load monitoring status (turn on/off)"}, + {GGETERRLEV, "GGETERRLEV: Get error level"}, + {GSETERRLEV, "GSETERRLEV: Set error level"}, + {GGETBITRATE, "GGETBITRATE: Get bit rate"}, + {GGETRAM, "GGETRAM: Read value from RAM"}, + {GSETRAM, "GSETRAM: Write value to RAM"}, + {GCANGETBTRS, "GCANGETBTRS: Read CAN bit timing registers"}, + {GCANSETBTRS, "GCANSETBTRS: Write CAN bit timing registers"}, + {GCANGETBC, "GCANGETBC: Read CAN bus configuration register"}, + {GCANSETBC, "GCANSETBC: Write CAN bus configuration register"}, + {GCANGETMODE, "GCANGETMODE"}, + {GCANSETMODE, "GCANSETMODE"}, + {GCANGETTRANS, "GCANGETTRANS"}, + {GCANSETTRANS, "GCANSETTRANS"}, + {GCANSENDERR, "GCANSENDERR"}, + {GCANRGETOBJ, "GCANRGETOBJ"}, + {GCANRSETSTDID, "GCANRSETSTDID"}, + {GCANRSETEXTID, "GCANRSETEXTID"}, + {GCANRSETDATA, "GCANRSETDATA"}, + {GCANRENABLE, "GCANRENABLE"}, + {GCANRDISABLE, "GCANRDISABLE"}, + {GCANRGETMASKS, "GCANRGETMASKS"}, + {GCANRSETMASKS, "GCANRSETMASKS"}, + {GCANSWGETMODE, "GCANSWGETMODE"}, + {GCANSWSETMODE, "GCANSWSETMODE"}, + {GDLCGETFOURX, "GDLCGETFOURX"}, + {GDLCSETFOURX, "GDLCSETFOURX"}, + {GDLCGETLOAD, "GDLCGETLOAD"}, + {GDLCSETLOAD, "GDLCSETLOAD"}, + {GDLCSENDBREAK, "GDLCSENDBREAK"}, + {GDLCABORTTX, "GDLCABORTTX"}, + {GDLCGETHDRMODE, "DLCGETHDRMODE"}, + {GDLCSETHDRMODE, "GDLCSETHDRMODE"}, + {GHONSLEEP, "GHONSLEEP"}, + {GHONSILENCE, "GHONSILENCE"}, + {GKWPSETPTIMES, "GKWPSETPTIMES"}, + {GKWPSETWTIMES, "GKWPSETWTIMES"}, + {GKWPDOWAKEUP, "GKWPDOWAKEUP"}, + {GKWPGETBITTIME, "GKWPGETBITTIME"}, + {GKWPSETBITTIME, "GKWPSETBITTIME"}, + {GKWPSETNODEADDR, "GKWPSETNODEADDR"}, + {GKWPGETNODETYPE, "GKWPGETNODETYPE"}, + {GKWPSETNODETYPE, "GKWPSETNODETYPE"}, + {GKWPSETWAKETYPE, "GKWPSETWAKETYPE"}, + {GKWPSETTARGADDR, "GKWPSETTARGADDR"}, + {GKWPSETKEYBYTES, "GKWPSETKEYBYTES"}, + {GKWPSETSTARTREQ, "GKWPSETSTARTREQ"}, + {GKWPSETSTARTRESP, "GKWPSETSTARTRESP"}, + {GKWPSETPROTOCOL, "GKWPSETPROTOCOL"}, + {GKWPGETLASTKEYBYTES, "GKWPGETLASTKEYBYTES"}, + {GKWPSETLASTKEYBYTES, "GKWPSETLASTKEYBYTES"}, + {GSCPGETBBR, "GSCPGETBBR"}, + {GSCPSETBBR, "GSCPSETBBR"}, + {GSCPGETID, "GSCPGETID"}, + {GSCPSETID, "GSCPSETID"}, + {GSCPADDFUNCID, "GSCPADDFUNCID"}, + {GSCPCLRFUNCID, "GSCPCLRFUNCID"}, + {GUBPGETBITRATE, "GUBPGETBITRATE"}, + {GUBPSETBITRATE, "GUBPSETBITRATE"}, + {GUBPGETINTERBYTE, "GUBPGETINTERBYTE"}, + {GUBPSETINTERBYTE, "GUBPSETINTERBYTE"}, + {GUBPGETNACKMODE, "GUBPGETNACKMODE"}, + {GUBPSETNACKMODE, "GUBPSETNACKMODE"}, + {GUBPGETRETRYDELAY, "GUBPGETRETRYDELAY"}, + {GUBPSETRETRYDELAY, "GUBPSETRETRYDELAY"}, + {GRESETHC08, "GRESETHC08: Reset the HC08 processor"}, + {GTESTHC08COP, "GTESTHC08COP: Stop updating the HC08 watchdog timer"}, + {GSJAGETLISTEN, "GSJAGETLISTEN"}, + {GSJASETLISTEN, "GSJASETLISTEN"}, + {GSJAGETSELFTEST, "GSJAGETSELFTEST"}, + {GSJASETSELFTEST, "GSJASETSELFTEST"}, + {GSJAGETXMITONCE, "GSJAGETXMITONCE"}, + {GSJASETXMITONCE, "GSJASETXMITONCE"}, + {GSJAGETTRIGSTATE, "GSJAGETTRIGSTATE"}, + {GSJASETTRIGCTRL, "GSJASETTRIGCTRL"}, + {GSJAGETTRIGCTRL, "GSJAGETTRIGCTRL"}, + {GSJAGETOUTSTATE, "GSJAGETOUTSTATE"}, + {GSJASETOUTSTATE, "GSJASETOUTSTATE"}, + {GSJAGETFILTER, "GSJAGETFILTER"}, + {GSJASETFILTER, "GSJASETFILTER"}, + {GSJAGETMASK, "GSJAGETMASK"}, + {GSJASETMASK, "GSJASETMASK"}, + {GSJAGETINTTERM, "GSJAGETINTTERM"}, + {GSJASETINTTERM, "GSJASETINTTERM"}, + {GSJAGETFTTRANS, "GSJAGETFTTRANS"}, + {GSJASETFTTRANS, "GSJASETFTTRANS"}, + {GSJAGETFTERROR, "GSJAGETFTERROR"}, + {GLINGETBITRATE, "GLINGETBITRATE: Get the current bit rate"}, + {GLINSETBITRATE, "GLINSETBITRATE: Set the bit rate"}, + {GLINGETBRKSPACE, "GLINGETBRKSPACE"}, + {GLINSETBRKSPACE, "GLINSETBRKSPACE"}, + {GLINGETBRKMARK, "GLINGETBRKMARK"}, + {GLINSETBRKMARK, "GLINSETBRKMARK"}, + {GLINGETIDDELAY, "GLINGETIDDELAY"}, + {GLINSETIDDELAY, "GLINSETIDDELAY"}, + {GLINGETRESPDELAY, "GLINGETRESPDELAY"}, + {GLINSETRESPDELAY, "GLINSETRESPDELAY"}, + {GLINGETINTERBYTE, "GLINGETINTERBYTE"}, + {GLINSETINTERBYTE, "GLINSETINTERBYTE"}, + {GLINGETWAKEUPDELAY, "GLINGETWAKEUPDELAY"}, + {GLINSETWAKEUPDELAY, "GLINSETWAKEUPDELAY"}, + {GLINGETWAKEUPTIMEOUT, "GLINGETWAKEUPTIMEOUT"}, + {GLINSETWAKEUPTIMEOUT, "GLINSETWAKEUPTIMEOUT"}, + {GLINGETWUTIMOUT3BR, "GLINGETWUTIMOUT3BR"}, + {GLINSETWUTIMOUT3BR, "GLINSETWUTIMOUT3BR"}, + {GLINSENDWAKEUP, "GLINSENDWAKEUP"}, + {GLINGETMODE, "GLINGETMODE"}, + {GLINSETMODE, "GLINSETMODE"}, + /* 20171109 lin LDF */ + {GLINGETSLEW, "GLINGETSLEW: get slew rate"}, + {GLINSETSLEW, "GLINSETSLEW: set slew rate"}, + {GLINADDSCHED, "GLINADDSCHED: add a LIN schedule"}, + {GLINGETSCHED, "GLINGETSCHED: get a LIN schedule"}, + {GLINGETSCHEDSIZE, "GLINGETSCHEDSIZE: get schedule size"}, + {GLINDELSCHED, "GLINDELSCHED: delete a LIN schedule"}, + {GLINACTSCHED, "GLINACTSCHED: activate a LIN schedule"}, + {GLINDEACTSCHED, "GLINDEACTSCHED: deactivate a LIN schedule"}, + {GLINGETACTSCHED, "GLINGETACTSCHED: get active LIN schedule"}, + {GLINGETNUMSCHEDS, "GLINGETNUMSCHED: get number of LIN schedules"}, + {GLINGETSCHEDNAMES, "GLINGETSCHEDNAMES: get LIN schedule names"}, + {GLINGETMASTEREVENTENABLE, "GLINGETMASTEREVENTENABLE: get LIN master schedule event enable flag"}, + {GLINSETMASTEREVENTENABLE, "GLINSETMASTEREVENTENABLE: set LIN master schedule event enable flag"}, + {GLINGETNSLAVETABLE, "GLINGETNSLAVETABLE: set number of LIN slave table entries"}, + {GLINGETSLAVETABLEPIDS, "GLINGETSLAVETABLEPIDS: get list of LIN slave table PIDs"}, + {GLINGETSLAVETABLE, "GLINGETSLAVETABLE: get LIN slave table entry for this PID"}, + {GLINSETSLAVETABLE, "GLINSETSLAVETABLE: set LIN slave table entry for this PID"}, + {GLINCLEARSLAVETABLE, "GLINCLEARSLAVETABLE: clear LIN slave table entry for this PID"}, + {GLINCLEARALLSLAVETABLE, "GLINCLEARALLSLAVETABLE: clear all LIN slave table entries"}, + {GLINGETONESHOT, "GLINGETONESHOT: get LIN one-shot entry"}, + {GLINSETONESHOT, "GLINSETONESHOT: set LIN one-shot entry"}, + {GLINCLEARONESHOT, "GLINCLEARONESHOT: clear LIN one-shot entry"}, + {GLINSETFLAGS, "GLINSETFLAGS"}, + {GLINGETAUTOCHECKSUM, "GLINGETAUTOCHECKSUM: get LIN auto checksum"}, + {GLINSETAUTOCHECKSUM, "GLINSETAUTOCHECKSUM: set LIN auto checksum"}, + {GLINGETAUTOPARITY, "GLINGETAUTOPARITY: get LIN auto parity"}, + {GLINSETAUTOPARITY, "GLINSETAUTOPARITY: set LIN auto parity"}, + {GLINGETSLAVETABLEENABLE, "GLINGETSLAVETABLEENABLE: get LIN slave table enable"}, + {GLINSETSLAVETABLEENABLE, "GLINSETSLAVETABLEENABLE: set LIN slave table enable"}, + {GLINGETFLAGS, "GLINGETFLAGS"}, + {GLINGETWAKEUPMODE, "GLINGETWAKEUPMODE: get LIN wakeup mode"}, + {GLINSETWAKEUPMODE, "GLINSETWAKEUPMODE: set LIN wakeup mode"}, + {GDLYGETHIVALUE, "GDLYGETHIVALUE: get the high water value"}, + {GDLYSETHIVALUE, "GDLYSETHIVALUE: set the high water value"}, + {GDLYGETLOVALUE, "GDLYGETLOVALUE: get the low water value"}, + {GDLYSETLOVALUE, "GDLYSETLOVALUE: set the low water value"}, + {GDLYGETHITIME, "GDLYGETHITIME: get the high water time"}, + {GDLYSETHITIME, "GDLYSETHITIME: set the high water time"}, + {GDLYGETLOTIME, "GDLYGETLOTIME: get the low water time"}, + {GDLYSETLOTIME, "GDLYSETLOTIME: set the low water time"}, + {GDLYGETLOREPORT, "GDLYGETLOREPORT:get the low water report flag"}, + {GDLYFLUSHSTREAM, "GDLYFLUSHSTREAM: flush the delay buffer"}, + {GDLYINITSTREAM, "GDLYINITSTREAM: set default hi & lo water marks"}, + {GDLYPARTIALFLUSHSTREAM, "GDLYPARTIALFLUSHSTREAM: flush the delay buffer"}, + {GINPGETINP, "GINPGETINP: Read current digital inputs"}, + {GINPGETLATCH, "GINPGETLATCH: Read latched digital inputs"}, + {GINPCLRLATCH, "GINPCLRLATCH: Read and clear latched digital inputs"}, + {GOUTGET, "GOUTGET: Read digital outputs"}, + {GOUTSET, "GOUTSET: Write digital outputs"}, + {GOUTSETBIT, "GOUTSETBIT: Set digital output bits"}, + {GOUTCLEARBIT, "GOUTCLEARBIT"}, + {GPWRGETWHICH, "GPWRGETWHICH"}, + {GPWROFF, "GPWROFF"}, + {GPWROFFRESET, "GPWROFFRESET"}, + {GPWRRESET, "GPWRRESET"}, + {0, NULL}, +}; + + +static const value_string cmd_sort_type[] = { + {0, "Do not sort messages"}, + {1, "Sort into blocks of up to 16 messages"}, + {0, NULL} +}; + +static const value_string protocol_types[] = { + {GDUMMY * 256 + GDGDMARKONE, "Dummy device driver"}, + {GCAN * 256 + G82527, "CAN, 82527 subtype"}, + {GCAN * 256 + GSJA1000, "CAN, SJA1000 subtype"}, + {GCAN * 256 + G82527SW, "CAN, 82527 single wire subtype"}, + {GCAN * 256 + G82527ISO11992, "CAN, 82527 ISO11992 subtype"}, + {GCAN * 256 + G82527_SINGLECHAN, "CAN, Fiber Optic 82527 subtype"}, + {GCAN * 256 + G82527SW_SINGLECHAN, "CAN, Fiber Optic 82527 single wire subtype"}, + {GCAN * 256 + G82527ISO11992_SINGLECHAN, "CAN, Fiber Optic ISO11992 subtype"}, + {GCAN * 256 + GSJA1000FT, "CAN, SJA1000 Fault Tolerant subtype"}, + {GCAN * 256 + GSJA1000C, "CAN, SJA1000 onboard subtype"}, + {GCAN * 256 + GSJA1000FT_FO, "CAN, SJA1000 Fiber Optic Fault Tolerant subtype"}, + {GCAN * 256 + GSJA1000_BEACON_CANFD, "CAN, SJA1000 BEACON CAN-FD subtype"}, + {GCAN * 256 + GSJA1000_BEACON_SW, "CAN, SJA1000 BEACON CAN single wire subtype"}, + {GCAN * 256 + GSJA1000_BEACON_FT, "CAN, SJA1000 BEACON CAN Fault Tolerant subtype"}, + {GJ1850 * 256 + GHBCCPAIR, "J1850, HBCC subtype"}, + {GJ1850 * 256 + GDLC, "J1850, GM DLC subtype"}, + {GJ1850 * 256 + GCHRYSLER, "J1850, Chrysler subtype"}, + {GJ1850 * 256 + GDEHC12, "J1850, DE HC12 KWP/BDLC subtype"}, + {GKWP2000 * 256 + GDEHC12KWP, "Keyword protocol 2000/ISO 9141"}, + {GHONDA * 256 + GDGHC08, "Honda UART, DG HC08 subtype"}, + {GFORDUBP * 256 + GDGUBP08, "Ford UBP, DG HC08 subtype"}, + {GSCI * 256 + G16550SCI, "Chrysler SCI, UART subtype"}, + {GCCD * 256 + G16550CDP68HC68, "Chrysler C2D, UART / CDP68HC68S1 subtype"}, + {GLIN * 256 + GDGLIN08, "LIN, DG HC08 subtype"}, + {GLIN * 256 + GDGLIN_BEACON, "LIN, BEACON LIN updated subtype"}, + {0, NULL}, +}; + +/* + * Note: using external tfs strings doesn't work in a plugin. + * The address of a data item exported from a shared library + * such as libwireshark is not known until the library is + * loaded, so "&data_item" is not a constant; MSVC complains + * about that. + * + * (*Direct* references to the item in code can execute a + * different code sequence to get the address and then load + * from that address, but references from a data structure + * can't do that.) + */ +static const true_false_string tfs_wait_response = { "Wait", "Don't Wait" }; +static const true_false_string true_false = { "True", "False" }; +static const true_false_string register_unregister_action_flags = { "Register", "Unregister" }; +static const true_false_string tfs_passed_blocked = { "Pass", "Block" }; +static const true_false_string active_inactive = { "Active", "Inactive" }; +static const true_false_string critical_normal = { "Critical", "Normal" }; +static const true_false_string skip_not_skip = { "Skip", "Do not skip" }; +static const true_false_string frames_01seconds = { "Frames", "0.01 seconds" }; +static const true_false_string present_not_present = { "Present", "Not present" }; +static const true_false_string yes_no = { "Yes", "No" }; +static const true_false_string set_not_set = { "Set", "Not set" }; + +/* + * returns 1 if the ID is one of the special servers + * return 0 otherwise + */ +static int is_special_client(guint32 id) +{ + if((id == SD_SERVER) || (id == SD_CLIENT)) { + return 1; + } + return 0; +} + +static int +decode_data(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree *tree; + int hdrsize, datasize, extrasize, msgsize, padding; + nstime_t timestamp; + /*int hdrbits;*/ + + static int * const data_mode_flags[] = { + &hf_gryphon_data_mode_transmitted, + &hf_gryphon_data_mode_receive, + &hf_gryphon_data_mode_local, + &hf_gryphon_data_mode_remote, + &hf_gryphon_data_mode_oneshot, + &hf_gryphon_data_mode_combined, + &hf_gryphon_data_mode_nomux, + &hf_gryphon_data_mode_internal, + NULL + }; + + hdrsize = tvb_get_guint8(tvb, offset+0); + /* hdrbits = tvb_get_guint8(tvb, offset+1); */ + datasize = tvb_get_ntohs(tvb, offset+2); + extrasize = tvb_get_guint8(tvb, offset+4); + padding = 3 - (hdrsize + datasize + extrasize + 3) % 4; + msgsize = hdrsize + datasize + extrasize + padding + 16; + + tree = proto_tree_add_subtree(pt, tvb, offset, 16, ett_gryphon_data_header, NULL, "Message header"); + + /* fixed major problem with header length, length is 1-byte not 2-bytes */ + proto_tree_add_item(tree, hf_gryphon_data_header_length, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gryphon_data_header_length_bits, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gryphon_data_data_length, tvb, offset+2, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gryphon_data_extra_data_length, tvb, offset+4, 1, ENC_BIG_ENDIAN); + + /* 20171012 always display mode bits, not just conditionally */ + proto_tree_add_bitmask(tree, tvb, offset+5, hf_gryphon_data_mode, ett_gryphon_flags, data_mode_flags, ENC_BIG_ENDIAN); + + proto_tree_add_item(tree, hf_gryphon_data_priority, tvb, offset+6, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gryphon_data_error_status, tvb, offset+7, 1, ENC_BIG_ENDIAN); + + timestamp.secs = tvb_get_ntohl(tvb, offset+8)/100000; + timestamp.nsecs = (tvb_get_ntohl(tvb, offset+8)%100000)*1000; + proto_tree_add_time(tree, hf_gryphon_data_time, tvb, offset+8, 4, ×tamp); + + proto_tree_add_item(tree, hf_gryphon_data_context, tvb, offset+12, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gryphon_reserved, tvb, offset+13, 3, ENC_NA); + offset += 16; + + tree = proto_tree_add_subtree(pt, tvb, offset, msgsize-16-padding, ett_gryphon_data_body, NULL, "Message Body"); + if (hdrsize) { + proto_tree_add_item(tree, hf_gryphon_data_header_data, tvb, offset, hdrsize, ENC_NA); + offset += hdrsize; + } + if (datasize) { + proto_tree_add_item(tree, hf_gryphon_data_data, tvb, offset, datasize, ENC_NA); + offset += datasize; + } + if (extrasize) { + proto_tree_add_item(tree, hf_gryphon_data_extra_data, tvb, offset, extrasize, ENC_NA); + offset += extrasize; + } + if (padding) { + proto_tree_add_item(tree, hf_gryphon_data_padding, tvb, offset, padding, ENC_NA); + offset += padding; + } + /*proto_tree_add_debug_text(pt, "decode_data() debug offset=%d msgsize=%d", offset, msgsize);*/ + return offset; +} + +static int +decode_event(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen, msgend, padding, length; + nstime_t timestamp; + + msglen = tvb_reported_length_remaining(tvb, offset); + padding = 3 - (msglen + 3) % 4; + msgend = offset + msglen; + + proto_tree_add_item(pt, hf_gryphon_event_id, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_event_context, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+2, 2, ENC_NA); + offset += 4; + + timestamp.secs = tvb_get_ntohl(tvb, offset)/100000; + timestamp.nsecs = (tvb_get_ntohl(tvb, offset)%100000)*1000; + proto_tree_add_time(pt, hf_gryphon_event_time, tvb, offset, 4, ×tamp); + offset += 4; + + if (offset < msgend) { + length = msgend - offset; + proto_tree_add_item(pt, hf_gryphon_event_data, tvb, offset, length, ENC_NA); + offset += length; + } + if (padding) { + proto_tree_add_item(pt, hf_gryphon_event_padding, tvb, offset, padding, ENC_NA); + offset += padding; + } + return offset; +} + +static int +decode_misc (tvbuff_t *tvb, int offset, packet_info* pinfo, proto_tree *pt) +{ + tvbuff_t *next_tvb; + + /* proto_tree_add_debug_text(pt, "decode_misc() debug a offset=%d msglen=%d",offset, msglen); */ + while(tvb_reported_length_remaining(tvb, offset) > 0) { + /* + * 20180221 + * This function is called because Gryphon Protocol MISC packets contain within + * them Gryphon Protocol packets (including possibly MISC packets!). So, this + * function decodes that packet and return the offset. Loop thru all such packets + * in the MISC packet. + */ + + next_tvb = tvb_new_subset_remaining(tvb, offset); + offset += dissect_gryphon_message(next_tvb, pinfo, pt, TRUE); + } + return offset; +} + +static int +decode_text (tvbuff_t *tvb, int offset, int msglen, proto_tree *pt) +{ + int padding, length; + + padding = 3 - (msglen + 3) % 4; + + proto_tree_add_item_ret_length(pt, hf_gryphon_misc_text, tvb, offset, -1, ENC_NA|ENC_ASCII, &length); + offset += length; + if (padding) { + proto_tree_add_item(pt, hf_gryphon_misc_padding, tvb, offset, padding, ENC_NA); + offset += padding; + } + return offset; +} + +static int +cmd_init(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + guint8 mode = tvb_get_guint8(tvb, offset); + + if (mode == 0) + proto_tree_add_uint_format_value(pt, hf_gryphon_cmd_mode, tvb, offset, 1, mode, "Always initialize"); + else + proto_tree_add_uint_format_value(pt, hf_gryphon_cmd_mode, tvb, offset, 1, mode, "Initialize if not previously initialized"); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + return offset; +} +static int +eventnum(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + guint8 event = tvb_get_guint8(tvb, offset); + + if (event) + proto_tree_add_item(pt, hf_gryphon_eventnum, tvb, offset, 1, ENC_BIG_ENDIAN); + else + proto_tree_add_uint_format_value(pt, hf_gryphon_eventnum, tvb, offset, 1, 0, "All Events."); + offset += 1; + return offset; +} + +static int +resp_time(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + guint64 val; + nstime_t timestamp; + + val = tvb_get_ntoh64(tvb, offset); + timestamp.secs = (time_t)(val/100000); + timestamp.nsecs = (int)((val%100000)*1000); + + proto_tree_add_time(pt, hf_gryphon_resp_time, tvb, offset, 8, ×tamp); + offset += 8; + + return offset; +} + +static int +cmd_setfilt(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int flag = tvb_get_ntohl(tvb, offset); + int length, padding; + + length = tvb_get_guint8(tvb, offset+4) + tvb_get_guint8(tvb, offset+5) + + tvb_get_ntohs(tvb, offset+6); + + proto_tree_add_uint_format_value(pt, hf_gryphon_setfilt, tvb, offset, 4, + flag, "%s%s", ((flag) ? "Pass" : "Block"), ((length == 0) ? " all" : "")); + proto_tree_add_uint(pt, hf_gryphon_setfilt_length, tvb, offset+4, 4, length); + offset += 8; + if (length) { + proto_tree_add_item(pt, hf_gryphon_setfilt_discard_data, tvb, offset, length * 2, ENC_NA); + offset += length * 2; + } + padding = 3 - (length * 2 + 3) % 4; + if (padding) { + proto_tree_add_item(pt, hf_gryphon_setfilt_padding, tvb, offset, padding, ENC_NA); + offset += padding; + } + return offset; +} + +static int +cmd_ioctl_details(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt, guint32 ui_command, int msglen) +{ + char *string; + int length; + gint32 nbytes; + gint32 block_nbytes; + gint16 us_stream; + gint16 us_value; + proto_tree *tree; + unsigned int msg; + guint8 number_ids; + guint8 number_bytes; + guint8 number_extra_bytes; + guint8 flags; + guint8 pid; + guint8 datalen; + guint8 extralen; + int i; + guint32 mtime; + guint16 us_nsched; + float value; + static int * const ldf_schedule_flags[] = { + &hf_gryphon_ldf_schedule_event, + &hf_gryphon_ldf_schedule_sporadic, + NULL + }; + + /* TODO Gryphon Protocol has LOTS more ioctls, for CANbus, etc. */ + /* 20171109 mc */ + switch(ui_command) { + case GLINDEACTSCHED: + { + /* 20180104 done */ + } + break; + case GLINACTSCHED: + { + /* schedule name */ + proto_tree_add_item(pt, hf_gryphon_ldf_schedule_name, tvb, offset, 32, ENC_ASCII|ENC_NA); + offset += 32; + } + break; + case GLINGETNUMSCHEDS: + { + /* 20180227 */ + us_nsched = tvb_get_letohs(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_sched_numb_place, tvb, offset, 2, us_nsched, "%d", us_nsched); + offset += 2; + } + break; + case GLINGETSCHEDNAMES: + { + nbytes = tvb_reported_length_remaining(tvb, offset); + while(nbytes > 0) + { + /* schedule name */ + proto_tree_add_item(pt, hf_gryphon_ldf_schedule_name, tvb, offset, 32, ENC_ASCII|ENC_NA); + offset += 32; + nbytes -= 32; + } + } + break; + case GLINGETSCHED: + { + /* 20180227 */ + nbytes = tvb_get_letohl(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_sched_size, tvb, offset, 4, nbytes, "%d", nbytes); + offset += 4; + /* schedule name */ + proto_tree_add_item(pt, hf_gryphon_ldf_schedule_name, tvb, offset, 32, ENC_ASCII|ENC_NA); + offset += 32; + + /* delay time */ + mtime = tvb_get_letohl(tvb, offset); + value = (float)mtime / (float)10.0; + proto_tree_add_float_format_value(pt, hf_gryphon_init_strat_delay, tvb, offset, 4, value, "%.1f milliseconds", value); + offset += 4; + + number_ids = tvb_get_guint8(tvb, offset); + + /* header length, number of IDs to follow */ + proto_tree_add_item(pt, hf_gryphon_data_header_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + number_bytes = tvb_get_guint8(tvb, offset); + number_bytes &= 0x0F; /* bit0 thru bit3 */ + + /* data length, number data bytes to follow */ + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_schedule_msg_dbytes, tvb, offset, 1, number_bytes, "%d", number_bytes); + /* sporadic, event-driven flags */ + proto_tree_add_bitmask(pt, tvb, offset, hf_gryphon_ldf_schedule_flags, ett_gryphon_flags, ldf_schedule_flags, ENC_BIG_ENDIAN); + offset += 1; + + /* id's */ + proto_tree_add_item(pt, hf_gryphon_data_header_data, tvb, offset, number_ids, ENC_NA); + offset += number_ids; + proto_tree_add_item(pt, hf_gryphon_data_data, tvb, offset, number_bytes, ENC_NA); + offset += number_bytes; + } + break; + case GLINGETSCHEDSIZE: + { + /* 20180227 */ + nbytes = tvb_get_letohl(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_sched_size_place, tvb, offset, 4, nbytes, "%d", nbytes); + offset += 4; + /* schedule name */ + proto_tree_add_item(pt, hf_gryphon_ldf_schedule_name, tvb, offset, 32, ENC_ASCII|ENC_NA); + offset += 32; + } + break; + case GLINDELSCHED: + { + string = tvb_get_stringz_enc(pinfo->pool, tvb, offset, &length, ENC_ASCII); + /*proto_tree_add_debug_text(pt, "cmd_ioctl_details() debug offset=%d length=%d string='%s'",offset,length,string); */ + if(string[0] == '\0') { + proto_tree_add_string(pt, hf_gryphon_ldf_schedule_name, tvb, offset, 32, "All schedules"); + } else { + proto_tree_add_string(pt, hf_gryphon_ldf_schedule_name, tvb, offset, 32, string); + } + offset += 32; + } + break; + case GLINADDSCHED: + { + /* 20180227 */ + /* number of bytes to follow */ + nbytes = tvb_get_letohl(tvb, offset); + /*proto_tree_add_item(pt, hf_gryphon_ioctl_nbytes, tvb, offset, 4, ENC_BIG_ENDIAN);*/ + proto_tree_add_uint_format_value(pt, hf_gryphon_ioctl_nbytes, tvb, offset, 4, nbytes, "%d", nbytes); + offset += 4; + nbytes -= 4; + /* schedule name */ + proto_tree_add_item(pt, hf_gryphon_ldf_schedule_name, tvb, offset, 32, ENC_ASCII|ENC_NA); + offset += 32; + nbytes -= 32; + + /* messages */ + msg = 1; + while(nbytes > 0) { + + /* calc the number of bytes in this block */ + number_ids = tvb_get_guint8(tvb, offset+4); + number_bytes = tvb_get_guint8(tvb, offset+5); + + number_bytes &= 0x0F; /* bit0 thru bit3 */ + block_nbytes = 4 + 1 + 1 + number_ids + number_bytes; + + /* message number */ + tree = proto_tree_add_subtree_format(pt, tvb, offset, block_nbytes, ett_gryphon_lin_schedule_msg, NULL, "LIN message %u", msg); + + /* delay time */ + /*mtime = tvb_get_ntohl(tvb, offset);*/ + mtime = tvb_get_letohl(tvb, offset); + value = (float)mtime / (float)10.0; + proto_tree_add_float_format_value(tree, hf_gryphon_init_strat_delay, tvb, offset, 4, value, "%.1f milliseconds", value); + offset += 4; + + /* header length, number of IDs to follow */ + proto_tree_add_item(tree, hf_gryphon_data_header_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* data length, number data bytes to follow */ + /*proto_tree_add_item(tree, hf_gryphon_data_data_length, tvb, offset, 1, ENC_BIG_ENDIAN);*/ + proto_tree_add_uint_format_value(tree, hf_gryphon_ldf_schedule_msg_dbytes, tvb, offset, 1, number_bytes, "%d", number_bytes); + /* sporadic, event-driven flags */ + proto_tree_add_bitmask(tree, tvb, offset, hf_gryphon_ldf_schedule_flags, ett_gryphon_flags, ldf_schedule_flags, ENC_BIG_ENDIAN); + offset += 1; + + /* id's */ + proto_tree_add_item(tree, hf_gryphon_data_header_data, tvb, offset, number_ids, ENC_NA); + offset += number_ids; + proto_tree_add_item(tree, hf_gryphon_data_data, tvb, offset, number_bytes, ENC_NA); + offset += number_bytes; + + nbytes -= block_nbytes; + msg++; + /* proto_tree_add_debug_text(pt, "cmd_ioctl_details() debug offset=%d msglen=%d nbytes=%d",offset,msglen,nbytes);*/ + } + } + break; + case GLINSETFLAGS: + { + /* 20171113 */ + proto_tree_add_item(pt, hf_gryphon_ldf_ioctl_setflags, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + number_ids = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_numb_ids, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + for(i = 0; i < number_ids; i++) { + flags = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_ioctl_setflags_flags, tvb, offset, 1, flags, "0x%x %s",i,flags==0 ? "Classic checksum" : (flags==0x80?"Enhanced checksum":(flags==0x40?"Event":"UNKNOWN"))); + offset += 1; + } + } + break; + case GLINSETBITRATE: + { + /* 20180227 */ + /* 20171113 */ + mtime = tvb_get_letohl(tvb, offset); + value = (float)mtime / (float)1000.0; + proto_tree_add_float_format_value(pt, hf_gryphon_ldf_bitrate, tvb, offset, 4, value, "%.3f Kbps", value); + offset += 4; + } + break; + case GLINGETNSLAVETABLE: + { + /* 20180104 */ + proto_tree_add_item(pt, hf_gryphon_ldf_numb_ids, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + } + break; + case GLINGETSLAVETABLEPIDS: + { + /* 20180104 */ + number_ids = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_numb_ids, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + for(i = 0; i < number_ids; i++) { + pid = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_ioctl_setflags_flags, tvb, offset, 1, pid, "0x%x ",pid); + offset += 1; + } + } + break; + case GLINGETSLAVETABLE: + { + /* 20180104 */ + /* + * byte 0: PID + * byte 1: datalen + * byte 2: extralen + * byte 3: enabled=1 or disabled=0, 2=has one-shot + * byte 4: good cs=0 or bad cs=1 + * byte 5-13: data[datalen] + * byte n: checksum + */ + pid = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_ioctl_setflags_flags, tvb, offset, 1, pid, "0x%02x ",pid); + offset += 1; + datalen = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_lin_data_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + extralen = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_data_extra_data_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(pt, hf_gryphon_lin_slave_table_enable, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(pt, hf_gryphon_lin_slave_table_cs, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + if(datalen != 0) { + proto_tree_add_item(pt, hf_gryphon_lin_slave_table_data, tvb, offset, datalen, ENC_NA); + offset += datalen; + } + if(extralen != 0) { + proto_tree_add_item(pt, hf_gryphon_lin_slave_table_datacs, tvb, offset, 1, ENC_NA); + offset += 1; + } + } + break; + case GLINSETSLAVETABLE: + { + /* 20180104 */ + /* + * byte 0: PID + * byte 1: datalen + * byte 2: extralen + * byte 3: enabled=1 or disabled=0 + * byte 4-12: data[datalen] + * byte n: checksum + */ + pid = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_ioctl_setflags_flags, tvb, offset, 1, pid, "0x%02x ",pid); + offset += 1; + datalen = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_lin_data_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + extralen = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_data_extra_data_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(pt, hf_gryphon_lin_slave_table_enable, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + if(datalen != 0) { + proto_tree_add_item(pt, hf_gryphon_lin_slave_table_data, tvb, offset, datalen, ENC_NA); + offset += datalen; + } + if(extralen != 0) { + proto_tree_add_item(pt, hf_gryphon_lin_slave_table_datacs, tvb, offset, 1, ENC_NA); + offset += 1; + } + } + break; + case GLINCLEARSLAVETABLE: + { + /* 20180104 done */ + pid = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_ioctl_setflags_flags, tvb, offset, 1, pid, "0x%02x ",pid); + offset += 1; + } + break; + case GLINCLEARALLSLAVETABLE: + { + /* 20180104 done */ + } + break; + case GLINGETMASTEREVENTENABLE: + case GLINSETMASTEREVENTENABLE: + { + /* 20180227 */ + proto_tree_add_item(pt, hf_gryphon_lin_masterevent, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + } + break; + case GLINGETONESHOT: + case GLINSETONESHOT: + { + /* 20180104 */ + /* 20180228 */ + number_bytes = tvb_get_guint8(tvb, offset+1); + number_extra_bytes = tvb_get_guint8(tvb, offset+2); + /* id */ + proto_tree_add_item(pt, hf_gryphon_data_header_data, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(pt, hf_gryphon_lin_numdata, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item(pt, hf_gryphon_lin_numextra, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + if (number_bytes) { + proto_tree_add_item(pt, hf_gryphon_data_data, tvb, offset, number_bytes, ENC_NA); + offset += number_bytes; + } + if (number_extra_bytes) { + proto_tree_add_item(pt, hf_gryphon_data_extra_data, tvb, offset, number_extra_bytes, ENC_NA); + offset += number_extra_bytes; + } + } + break; + case GLINCLEARONESHOT: + { + /* 20180104 */ + /* 20180227 done */ + } + break; + case GDLYGETHIVALUE: + case GDLYSETHIVALUE: + case GDLYGETLOVALUE: + case GDLYSETLOVALUE: + { + /* 20180227 */ + /* 20180104 */ + us_stream = tvb_get_letohs(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_dd_stream, tvb, offset, 2, us_stream, "%d (0x%04X)", us_stream, us_stream); + offset += 2; + us_value = tvb_get_letohs(tvb, offset); + /* proto_tree_add_item(pt, hf_gryphon_dd_value, tvb, offset, 2, ENC_BIG_ENDIAN);*/ + proto_tree_add_uint_format_value(pt, hf_gryphon_dd_value, tvb, offset, 2, us_value, "%d (0x%04X)", us_value, us_value); + offset += 2; + } + break; + case GDLYGETHITIME: + case GDLYSETHITIME: + case GDLYGETLOTIME: + case GDLYSETLOTIME: + { + /* 20180227 */ + /* 20180104 */ + us_stream = tvb_get_letohs(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_dd_stream, tvb, offset, 2, us_stream, "%d (0x%04X)", us_stream, us_stream); + offset += 2; + mtime = tvb_get_letohs(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_dd_time, tvb, offset, 2, mtime, "%d", mtime); + offset += 2; + } + break; +/* TODO implement remaining delay driver ioctls */ +#if 0 + case GDLYGETLOREPORT: /*get the low water report flag*/ + break; + case GDLYFLUSHSTREAM: /*flush the delay buffer*/ + break; + case GDLYINITSTREAM: /*set default hi & lo water marks*/ + break; + case GDLYPARTIALFLUSHSTREAM: /*flush the delay buffer */ + break; +#endif + default: + proto_tree_add_item(pt, hf_gryphon_ioctl_data, tvb, offset, msglen, ENC_NA); + offset += msglen; + break; + } + return offset; +} + +/* + * cmd_ioctl() performs the initial decode of the IOCTL command, then + * calls cmd_ioctl_details() + */ +static int +cmd_ioctl(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt, guint32 ui_command) +{ + int msglen; + /*guint32 ioctl;*/ + int padding; + + msglen = tvb_reported_length_remaining(tvb, offset); + /* 20171109 mc */ + /*ioctl = tvb_get_ntohl(tvb, offset);*/ + + /* 20171012 debug */ + /*proto_tree_add_debug_text(pt, "cmd_ioctl() debug offset=%d msglen=%d",offset,msglen);*/ + proto_tree_add_item(pt, hf_gryphon_ioctl, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + msglen -= 4; + + if (msglen > 0) { + offset = cmd_ioctl_details(tvb, pinfo, offset, pt, ui_command, msglen); + } + + padding = tvb_reported_length_remaining(tvb, offset); + /*proto_tree_add_debug_text(pt, "cmd_ioctl() debug offset=%d msglen=%d padding=%d",offset,msglen,padding);*/ + if (padding > 0) { + proto_tree_add_item(pt, hf_gryphon_setfilt_padding, tvb, offset, padding, ENC_NA); + offset += padding; + } + return offset; +} + +/* + * cmd_ioctl_resp() + * displays the IOCTL data in the IOCTL response to the IOCTL request + * Here is an issue with the IOCTLs. The IOCTL request contains the IOCTL number, + * but the IOCTL response does not contain the number. IOCTL response + * contains the context byte of the request, so application software can match + * the IOCTL response to the request. + */ +static int +cmd_ioctl_resp(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt, guint32 ui_command) +{ + int msglen = tvb_reported_length_remaining(tvb, offset); + + /* 20171012 debug */ + /*proto_tree_add_debug_text(pt, "cmd_ioctl_resp() debug offset=%d msglen=%d",offset,msglen);*/ + + if (msglen > 0) { + /*proto_tree_add_item(pt, hf_gryphon_ioctl_data, tvb, offset, msglen, ENC_NA);*/ + /*offset += msglen;*/ + offset = cmd_ioctl_details(tvb, pinfo, offset, pt, ui_command, msglen); + } + return offset; +} + +static int +filter_block(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + guint32 op, length, padding; + + /* 20171017 fixed display of filter block padding */ + + /* start 2bytes */ + proto_tree_add_item(pt, hf_gryphon_filter_block_filter_start, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* length 2bytes */ + proto_tree_add_item_ret_uint(pt, hf_gryphon_filter_block_filter_length, tvb, offset, 2, ENC_BIG_ENDIAN, &length); + offset += 2; + + /* type 1byte */ + proto_tree_add_item(pt, hf_gryphon_filter_block_filter_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* operator 1byte */ + proto_tree_add_item_ret_uint(pt, hf_gryphon_filter_block_filter_operator, tvb, offset, 1, ENC_BIG_ENDIAN, &op); + offset += 1; + + /* rsvd 2bytes */ + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + if (op == BIT_FIELD_CHECK) { + proto_tree_add_item(pt, hf_gryphon_filter_block_pattern, tvb, offset, length, ENC_NA); + proto_tree_add_item(pt, hf_gryphon_filter_block_mask, tvb, offset + length, length, ENC_NA); + + offset += length * 2; + padding = (length * 2) % 4; + if (padding) { + proto_tree_add_item(pt, hf_gryphon_padding, tvb, offset, padding, ENC_NA); + offset += padding; + } + } + else { + switch (length) { + case 1: + proto_tree_add_item(pt, hf_gryphon_filter_block_filter_value1, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + break; + case 2: + proto_tree_add_item(pt, hf_gryphon_filter_block_filter_value2, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + break; + case 4: + proto_tree_add_item(pt, hf_gryphon_filter_block_filter_value4, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + break; + default: + proto_tree_add_item(pt, hf_gryphon_filter_block_filter_value_bytes, tvb, offset, length, ENC_NA); + offset += length; + } + + padding = 3 - ((length + 3) % 4); + if (padding) { + proto_tree_add_item(pt, hf_gryphon_padding, tvb, offset, padding, ENC_NA); + offset += padding; + } + } + return offset; +} + +static int +cmd_addfilt(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree *tree; + int blocks, i, length; + int padding; + + tree = proto_tree_add_subtree(pt, tvb, offset, 1, ett_gryphon_flags, NULL, "Flags"); + proto_tree_add_item(tree, hf_gryphon_addfilt_pass, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gryphon_addfilt_active, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + blocks = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_addfilt_blocks, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 6, ENC_NA); + offset += 7; + + for (i = 1; i <= blocks; i++) { + length = tvb_get_ntohs(tvb, offset+2) + 8; + /*length += 3 - (length + 3) % 4; */ + padding = 3 - (length + 3) % 4; + tree = proto_tree_add_subtree_format(pt, tvb, offset, length + padding, ett_gryphon_cmd_filter_block, NULL, "Filter block %d", i); + offset = filter_block(tvb, offset, tree); + } + return offset; +} + +static int +resp_addfilt(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_addfilt_handle, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + return offset; +} + +static int +cmd_modfilt(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + guint8 filter_handle = tvb_get_guint8(tvb, offset); + + if (filter_handle) + proto_tree_add_item(pt, hf_gryphon_modfilt, tvb, offset, 1, ENC_BIG_ENDIAN); + else + proto_tree_add_uint_format_value(pt, hf_gryphon_modfilt, tvb, offset, 1, + 0, "Filter handles: all"); + + proto_tree_add_item(pt, hf_gryphon_modfilt_action, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+2, 2, ENC_NA); + offset += 4; + return offset; +} + +static int +resp_filthan(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int handles = tvb_get_guint8(tvb, offset); + int i, padding, handle; + + proto_tree_add_item(pt, hf_gryphon_filthan, tvb, offset, 1, ENC_BIG_ENDIAN); + for (i = 1; i <= handles; i++){ + handle = tvb_get_guint8(tvb, offset+i); + proto_tree_add_uint_format_value(pt, hf_gryphon_filthan_id, tvb, offset+i, 1, + handle, "Handle %d: %u", i, handle); + } + padding = 3 - (handles + 1 + 3) % 4; + if (padding) + proto_tree_add_item(pt, hf_gryphon_filthan_padding, tvb, offset+1+handles, padding, ENC_NA); + offset += 1+handles+padding; + return offset; +} + +static int +dfiltmode(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_dfiltmode, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + return offset; +} + +static int +filtmode(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_filtmode, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + return offset; +} + +static int +resp_events(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + unsigned int i; + proto_tree *tree; + + msglen = tvb_reported_length_remaining(tvb, offset); + i = 1; + while (msglen != 0) { + tree = proto_tree_add_subtree_format(pt, tvb, offset, 20, ett_gryphon_cmd_events_data, NULL, "Event %d:", i); + proto_tree_add_item(tree, hf_gryphon_event_id, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gryphon_event_name, tvb, offset+1, 19, ENC_NA|ENC_ASCII); + offset += 20; + msglen -= 20; + i++; + } + return offset; +} + +static int +cmd_register(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_register_username, tvb, offset, 16, ENC_NA|ENC_ASCII); + offset += 16; + proto_tree_add_item(pt, hf_gryphon_register_password, tvb, offset, 32, ENC_NA|ENC_ASCII); + offset += 32; + return offset; +} + +static int +resp_register(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_register_client_id, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_register_privileges, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+2, 2, ENC_NA); + offset += 4; + return offset; +} + + +static int +resp_getspeeds(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int indx, + size = tvb_get_guint8(tvb, offset+8), + number = tvb_get_guint8(tvb, offset+9); + + proto_tree_add_item(pt, hf_gryphon_getspeeds_set_ioctl, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_getspeeds_get_ioctl, tvb, offset+4, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_getspeeds_size, tvb, offset+8, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_getspeeds_preset, tvb, offset+9, 1, ENC_BIG_ENDIAN); + offset += 10; + + for (indx = 1; indx <= number; indx++) { + proto_tree_add_bytes_format(pt, hf_gryphon_getspeeds_data, tvb, offset, size, + tvb_get_ptr(tvb, offset, size), "Data for preset %d", indx); + offset += size; + } + return offset; +} + +static int +cmd_sort(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_cmd_sort, tvb, offset, 1, ENC_BIG_ENDIAN); + return (offset+1); +} + +static int +cmd_optimize(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_cmd_optimize, tvb, offset, 1, ENC_BIG_ENDIAN); + return (offset+1); +} + +static int +resp_config(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree *ft, *tree; + int devices; + int i; + unsigned int j, x; + + proto_tree_add_item(pt, hf_gryphon_config_device_name, tvb, offset, 20, ENC_NA|ENC_ASCII); + offset += 20; + + proto_tree_add_item(pt, hf_gryphon_config_device_version, tvb, offset, 8, ENC_NA|ENC_ASCII); + offset += 8; + + proto_tree_add_item(pt, hf_gryphon_config_device_serial_number, tvb, offset, 20, ENC_NA|ENC_ASCII); + offset += 20; + + devices = tvb_get_guint8(tvb, offset); + + proto_tree_add_item(pt, hf_gryphon_config_num_channels, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_config_name_version_ext, tvb, offset+1, 11, ENC_NA|ENC_ASCII); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+12, 4, ENC_NA); + offset += 16; + + for (i = 1; i <= devices; i++) { + ft = proto_tree_add_subtree_format(pt, tvb, offset, 80, ett_gryphon_cmd_config_device, NULL, "Channel %d:", i); + + proto_tree_add_item(ft, hf_gryphon_config_driver_name, tvb, offset, 20, ENC_NA|ENC_ASCII); + offset += 20; + + proto_tree_add_item(ft, hf_gryphon_config_driver_version, tvb, offset, 8, ENC_NA|ENC_ASCII); + offset += 8; + + proto_tree_add_item(ft, hf_gryphon_config_device_security, tvb, offset, 16, ENC_NA|ENC_ASCII); + offset += 16; + + x = tvb_get_ntohl (tvb, offset); + if (x) { + tree = proto_tree_add_subtree(ft, tvb, offset, 4, ett_gryphon_valid_headers, NULL, "Valid Header lengths"); + for (j = 0; ; j++) { + if (x & 1) { + proto_tree_add_uint_format(tree, hf_gryphon_valid_header_length, tvb, offset, 4, j, "%d byte%s", j, + j == 1 ? "" : "s"); + } + if ((x >>= 1) == 0) + break; + } + } + offset += 4; + + proto_tree_add_item(ft, hf_gryphon_config_max_data_length, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(ft, hf_gryphon_config_min_data_length, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(ft, hf_gryphon_config_hardware_serial_number, tvb, offset, 20, ENC_NA|ENC_ASCII); + offset += 20; + + proto_tree_add_item(ft, hf_gryphon_config_protocol_type, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(ft, hf_gryphon_config_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item(ft, hf_gryphon_config_card_slot_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset ++; + + proto_tree_add_item(ft, hf_gryphon_config_max_extra_data, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(ft, hf_gryphon_config_min_extra_data, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + } + return offset; +} + +static int +cmd_sched(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + proto_item *item, *item1; + proto_tree *tree, *tree1; + int save_offset; + unsigned int i, x, length; + guint8 def_chan = tvb_get_guint8(tvb, offset-9); + + msglen = tvb_reported_length_remaining(tvb, offset); + + if (tvb_get_ntohl(tvb, offset) == 0xFFFFFFFF) + proto_tree_add_uint_format_value(pt, hf_gryphon_sched_num_iterations, tvb, offset, 4, + 0, "\"infinite\""); + else + proto_tree_add_item(pt, hf_gryphon_sched_num_iterations, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + msglen -= 4; + + + item = proto_tree_add_item(pt, hf_gryphon_sched_flags, tvb, offset, 4, ENC_BIG_ENDIAN); + tree = proto_item_add_subtree (item, ett_gryphon_flags); + proto_tree_add_item(tree, hf_gryphon_sched_flags_scheduler, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + msglen -= 4; + + i = 1; + while (msglen > 0) { + + length = 16 + tvb_get_guint8(tvb, offset+16) + tvb_get_ntohs(tvb, offset+18) + tvb_get_guint8(tvb, offset+20) + 16; + length += 3 - (length + 3) % 4; + + tree = proto_tree_add_subtree_format(pt, tvb, offset, length, ett_gryphon_cmd_sched_data, NULL, "Message %d", i); + proto_tree_add_item(tree, hf_gryphon_sched_sleep, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + msglen -= 4; + + proto_tree_add_item(tree, hf_gryphon_sched_transmit_count, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + msglen -= 4; + + proto_tree_add_item(tree, hf_gryphon_sched_transmit_period, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + msglen -= 4; + + item1 = proto_tree_add_item(tree, hf_gryphon_sched_transmit_flags, tvb, offset, 2, ENC_BIG_ENDIAN); + tree1 = proto_item_add_subtree (item1, ett_gryphon_flags); + proto_tree_add_item(tree1, hf_gryphon_sched_skip_transmit_period, tvb, offset, 2, ENC_BIG_ENDIAN); + if (i == 1) { + /* N.B. Same bit as skip_transmit_period..? */ + proto_tree_add_item(tree1, hf_gryphon_sched_skip_sleep, tvb, offset, 2, ENC_BIG_ENDIAN); + } + + x = tvb_get_guint8(tvb, offset+2); + /* 20171026 */ + if (x == 0) { + x = def_chan; + proto_tree_add_uint(tree, hf_gryphon_sched_channel0, tvb, offset+2, 1, x); + } else { + proto_tree_add_uint(tree, hf_gryphon_sched_channel, tvb, offset+2, 1, x); + } + + proto_tree_add_item(tree, hf_gryphon_reserved, tvb, offset+3, 1, ENC_NA); + offset += 4; + msglen -= 4; + + tree1 = proto_tree_add_subtree(tree, tvb, offset, msglen, ett_gryphon_cmd_sched_cmd, NULL, "Message"); + save_offset = offset; + offset = decode_data(tvb, offset, tree1); + msglen -= offset - save_offset; + i++; + } + return offset; +} + +static int +cmd_sched_rep(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + unsigned int x; + const char *type; + + x = tvb_get_ntohl(tvb, offset); + if (x & 0x80000000) + type = "Critical"; + else + type = "Normal"; + proto_tree_add_uint_format_value(pt, hf_gryphon_sched_rep_id, tvb, + offset, 4, x, "%s schedule ID: %u", type, x); + offset += 4; + + proto_tree_add_item(pt, hf_gryphon_sched_rep_message_index, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + offset = decode_data(tvb, offset, pt); + return offset; +} + +static int +resp_blm_data(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int x; + + nstime_t timestamp; + + timestamp.secs = tvb_get_ntohl(tvb, offset)/100000; + timestamp.nsecs = (tvb_get_ntohl(tvb, offset)%100000)*1000; + proto_tree_add_time(pt, hf_gryphon_blm_data_time, tvb, offset, 4, ×tamp); + offset += 4; + + x = tvb_get_ntohs(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_blm_data_bus_load, tvb, + offset, 2, x, "%d.%02d%%", x / 100, x % 100); + offset += 2; + x = tvb_get_ntohs(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_blm_data_current_bus_load, tvb, + offset, 2, x, "%d.%02d%%", x / 100, x % 100); + offset += 2; + x = tvb_get_ntohs(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_blm_data_peak_bus_load, tvb, + offset, 2, x, "%d.%02d%%", x / 100, x % 100); + offset += 2; + x = tvb_get_ntohs(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_blm_data_historic_peak_bus_load, tvb, + offset, 2, x, "%d.%02d%%", x / 100, x % 100); + offset += 2; + + return offset; +} + +static int +resp_blm_stat(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + offset = resp_blm_data(tvb, offset, pt); + + proto_tree_add_item(pt, hf_gryphon_blm_stat_receive_frame_count, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(pt, hf_gryphon_blm_stat_transmit_frame_count, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(pt, hf_gryphon_blm_stat_receive_dropped_frame_count, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(pt, hf_gryphon_blm_stat_transmit_dropped_frame_count, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(pt, hf_gryphon_blm_stat_receive_error_count, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(pt, hf_gryphon_blm_stat_transmit_error_count, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + return offset; +} + +/* + * command to get a list of LDFs + */ +static int +cmd_ldf_list(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + + /* block index */ + proto_tree_add_item(pt, hf_gryphon_ldf_list, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + return offset; +} + +static int +resp_ldf_list(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int blocks; + int i; + proto_tree *localTree; + + /* block index */ + blocks = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* rsvd */ + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + + /* number remaining */ + proto_tree_add_item(pt, hf_gryphon_ldf_remaining, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* LDF blocks */ + for(i=0;i 0) { + /* slave node names */ + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_slave_node_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + us_num -= 1; + } + return offset; +} + +static int +cmd_ldf_get_frames(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_get_frame, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + return offset; +} + +static int +resp_ldf_get_frames(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + guint16 us_num; + guint8 pid; + /* number */ + us_num = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_num_frames, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + while(us_num > 0) { + /* id */ + pid = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_ioctl_setflags_flags, tvb, offset, 1, pid, "0x%x ",pid); + offset += 1; + /* frame name */ + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_get_frame, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + us_num -= 1; + } + return offset; +} + +static int +cmd_ldf_get_frame_info(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt) +{ + char *string; + int length; + guint8 id; + string = tvb_get_stringz_enc(pinfo->pool, tvb, offset, &length, ENC_ASCII); + if(length > 1) { + proto_tree_add_string(pt, hf_gryphon_ldf_get_frame, tvb, offset, length, string); + offset += length; + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_ioctl_setflags_flags, tvb, offset, 1, 0, "(Id not used)"); + offset += 1; + } else { + id = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_ldf_ioctl_setflags_flags, tvb, offset, 1, id, "0x%x ",id); + offset += 1; + } + return offset; +} + +static int +resp_ldf_get_frame_info(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + guint8 count, i; + proto_tree_add_item(pt, hf_gryphon_ldf_get_frame_num, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_get_frame_pub, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + count = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_get_frame_num_signals, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + for (i = 0; i < count; i++) { + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + } + return offset; +} + +static int +cmd_ldf_get_signal_info(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + return offset; +} + +static int +resp_ldf_get_signal_info(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; +/* offset */ + proto_tree_add_item(pt, hf_gryphon_ldf_signal_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + +/* length */ + proto_tree_add_item(pt, hf_gryphon_ldf_signal_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + +/* signal encoding name */ + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_encoding_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + return offset; +} + +static int +cmd_ldf_get_signal_detail(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + return offset; +} + +static int +resp_ldf_do_encoding_block(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt) +{ + char *string; + int length; + /* encoding */ + string = tvb_get_stringz_enc(pinfo->pool, tvb, offset, &length, ENC_ASCII); + proto_tree_add_string(pt, hf_gryphon_ldf_signal_encoding_type, tvb, offset, 12, string); + offset += 12; + if(string[0] == 'l') { + /* logical */ + proto_tree_add_item(pt, hf_gryphon_ldf_encoding_value, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_encoding_logical, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + } else if(string[0] == 'p') { + /* physical */ + proto_tree_add_item(pt, hf_gryphon_ldf_encoding_min, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + proto_tree_add_item(pt, hf_gryphon_ldf_encoding_max, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_encoding_logical, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_encoding_logical, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_encoding_logical, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + } else if(string[0] == 'b') { + proto_tree_add_item(pt, hf_gryphon_ldf_encoding_value, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + /* bcd */ + } else if(string[0] == 'a') { + proto_tree_add_item(pt, hf_gryphon_ldf_encoding_value, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + /* ascii */ + } else { + /* error */ + } + return(offset); +} + +static int +resp_ldf_get_signal_detail(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt) +{ + guint16 us_num; +/* offset */ + proto_tree_add_item(pt, hf_gryphon_ldf_signal_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + +/* length */ + proto_tree_add_item(pt, hf_gryphon_ldf_signal_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + +/* number */ + us_num = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_num_encodings, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + while(us_num > 0) { + offset = resp_ldf_do_encoding_block(tvb, pinfo, offset, pt); + us_num -= 1; + } + + return offset; +} + +static int +cmd_ldf_get_encoding_info(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_encoding_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + return offset; +} + +static int +resp_ldf_get_encoding_info(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt) +{ + guint16 us_num; + /* number */ + us_num = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_num_encodings, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + while(us_num > 0) { + /* encoding data */ + offset = resp_ldf_do_encoding_block(tvb, pinfo, offset, pt); + us_num -= 1; + } + return offset; +} + +static int +cmd_ldf_save_session(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + msglen = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_restore_session, tvb, offset, msglen, ENC_NA); + offset += msglen; + return offset; +} + +static int +cmd_ldf_emulate_nodes(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt) +{ + int nnodes; + int node_numb=1; + int i; + unsigned int xchannel; + char *string; + int length; + proto_tree *tree2; + + nnodes = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_nodenumber, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + for(i=0;ipool, tvb, offset+1, &length, ENC_ASCII); + + tree2 = proto_tree_add_subtree_format(pt, tvb, offset, 1+length, ett_gryphon_lin_emulate_node, NULL, "Node %u", node_numb); + + xchannel = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(tree2, hf_gryphon_sched_channel, tvb, offset, 1, xchannel); + offset += 1; + + proto_tree_add_string(tree2, hf_gryphon_lin_nodename, tvb, offset, length, string); + offset += length; + + node_numb++; + } + return offset; +} + +static int +resp_ldf_get_schedules(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + guint16 us_num; + /* number */ + us_num = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_num_schedules, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + while(us_num > 0) { + /* slave node names */ + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_schedule_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + us_num -= 1; + } + return offset; +} + +static int +cmd_ldf_start_schedule(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_schedule_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + return offset; +} + +static int +cmd_ldf_get_node_signals(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_node_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + return offset; +} + +static int +resp_ldf_get_node_signals(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int length; + guint16 us_num; + /* number */ + us_num = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_num_signal_names, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + while(us_num > 0) { + /* signal names */ + proto_tree_add_item_ret_length(pt, hf_gryphon_ldf_signal_name, tvb, offset, -1, ENC_NA | ENC_ASCII, &length); + offset += length; + us_num -= 1; + } + return offset; +} + +static int +cmd_restore_session(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + msglen = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_ldf_restore_session, tvb, offset, msglen, ENC_NA); + offset += msglen; + return offset; +} + +static int +resp_restore_session(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_ldf_name, tvb, offset, 32, ENC_ASCII|ENC_NA); + offset += 32; + return offset; +} + +static int +cmd_addresp(tvbuff_t *tvb, int offset, packet_info* pinfo, proto_tree *pt) +{ + proto_item *item; + proto_tree *tree; + guint blocks, responses, i, msglen, length; + int padding; + int action, actionType, actionValue; + tvbuff_t *next_tvb; + + actionType = 0; + /* flags */ + item = proto_tree_add_item(pt, hf_gryphon_addresp_flags, tvb, offset, 1, ENC_BIG_ENDIAN); + tree = proto_item_add_subtree (item, ett_gryphon_flags); + /* 20171017 fixed display of filter flags */ + /* flags: active */ + proto_tree_add_item(tree, hf_gryphon_addresp_flags_active, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + + /* number of filter blocks */ + proto_tree_add_item_ret_uint(pt, hf_gryphon_addresp_blocks, tvb, offset, 1, ENC_BIG_ENDIAN, &blocks); + offset += 1; + + /* number of responses */ + proto_tree_add_item_ret_uint(pt, hf_gryphon_addresp_responses, tvb, offset, 1, ENC_BIG_ENDIAN, &responses); + offset += 1; + + /* old handle */ + proto_tree_add_item(pt, hf_gryphon_addresp_old_handle, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* action */ + action = tvb_get_guint8(tvb, offset); + item = proto_tree_add_item(pt, hf_gryphon_addresp_action, tvb, offset, 1, ENC_BIG_ENDIAN); + tree = proto_item_add_subtree (item, ett_gryphon_flags); + actionValue = tvb_get_ntohs(tvb, offset+2); + if (actionValue) { + if (action & FR_PERIOD_MSGS) { + actionType = 1; + } else { + actionType = 0; + } + + proto_tree_add_item(tree, hf_gryphon_addresp_action_period, tvb, offset, 1, ENC_BIG_ENDIAN); + } + + proto_tree_add_item(tree, hf_gryphon_addresp_action_deact_on_event, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_gryphon_addresp_action_deact_after_period, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* reserved */ + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + if (actionValue) { + if (actionType == 1) { + proto_tree_add_uint_format_value(pt, hf_gryphon_addresp_action_period_type, tvb, + offset, 2, actionValue, "Period: %d messages", actionValue); + } else { + proto_tree_add_uint_format_value(pt, hf_gryphon_addresp_action_period_type, tvb, + offset, 2, actionValue, "Period: %d.%02d seconds", actionValue/100, actionValue%100); + } + } else { + /* 20171017 */ + /* value 2-bytes */ + proto_tree_add_uint_format_value(pt, hf_gryphon_addresp_action_period_type, tvb, offset, 2, actionValue, "(not used)"); + } + offset += 2; + + for (i = 1; i <= blocks; i++) { + length = tvb_get_ntohs(tvb, offset+2) + 8; + padding = 3 - (length + 3) % 4; + tree = proto_tree_add_subtree_format(pt, tvb, offset, length + padding, ett_gryphon_cmd_filter_block, NULL, "Filter block %d", i); + /* 20171017 fixed display of filter block padding */ + offset = filter_block(tvb, offset, tree); + } + for (i = 1; i <= responses; i++) { + msglen = tvb_get_ntohs(tvb, offset+4) + 8; + padding = 3 - (msglen + 3) % 4; + tree = proto_tree_add_subtree_format(pt, tvb, offset, msglen + padding, ett_gryphon_cmd_response_block, NULL, "Response block %d", i); + next_tvb = tvb_new_subset_length(tvb, offset, msglen + padding); + dissect_gryphon_message(next_tvb, pinfo, tree, TRUE); + offset += msglen + padding; + } + return offset; +} + +static int +resp_addresp(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_addresp_handle, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + return offset; +} + +static int +cmd_modresp(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + guint8 dest = tvb_get_guint8(tvb, offset-5), + resp_handle = tvb_get_guint8(tvb, offset); + + if (resp_handle) + proto_tree_add_item(pt, hf_gryphon_modresp_handle, tvb, offset, 1, ENC_BIG_ENDIAN); + else if (dest) + proto_tree_add_uint_format_value(pt, hf_gryphon_modresp_handle, tvb, + offset, 1, dest, "Response handles: all on channel %c", dest); + else + proto_tree_add_uint_format_value(pt, hf_gryphon_modresp_handle, tvb, offset, 1, + 0, "Response handles: all"); + + proto_tree_add_item(pt, hf_gryphon_modresp_action, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+2, 2, ENC_NA); + offset += 4; + return offset; +} + +static int +resp_resphan(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int handles = tvb_get_guint8(tvb, offset); + int i, padding, handle; + + proto_tree_add_item(pt, hf_gryphon_num_resphan, tvb, offset, 1, ENC_BIG_ENDIAN); + for (i = 1; i <= handles; i++){ + handle = tvb_get_guint8(tvb, offset+i); + proto_tree_add_uint_format(pt, hf_gryphon_handle, tvb, offset+i, 1, handle, "Handle %d: %u", i, + handle); + } + padding = 3 - (handles + 1 + 3) % 4; + if (padding) + proto_tree_add_item(pt, hf_gryphon_padding, tvb, offset+1+handles, padding, ENC_NA); + offset += 1+handles+padding; + return offset; +} + +static int +resp_sched(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_transmit_sched_id, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + return offset; +} + +static int +cmd_desc(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_desc_program_size, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + proto_tree_add_item(pt, hf_gryphon_desc_program_name, tvb, offset, 32, ENC_NA|ENC_ASCII); + offset += 32; + + proto_tree_add_item(pt, hf_gryphon_desc_program_description, tvb, offset, 80, ENC_NA|ENC_ASCII); + offset += 80; + + return offset; +} + +static int +resp_desc(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_item *item; + proto_tree *tree; + + item = proto_tree_add_item(pt, hf_gryphon_desc_flags, tvb, offset, 1, ENC_BIG_ENDIAN); + tree = proto_item_add_subtree (item, ett_gryphon_flags); + proto_tree_add_item(tree, hf_gryphon_desc_flags_program, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_desc_handle, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+2, 2, ENC_NA); + offset += 4; + return offset; +} + +static int +cmd_upload(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + unsigned int length; + + msglen = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_upload_block_number, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_upload_handle, tvb, offset+2, 1, ENC_BIG_ENDIAN); + offset += 3; + msglen -= 3; + + length = msglen; + proto_tree_add_item(pt, hf_gryphon_upload_data, tvb, offset, length, ENC_NA); + offset += length; + + length = 3 - (length + 3) % 4; + if (length) { + proto_tree_add_item(pt, hf_gryphon_padding, tvb, offset, length, ENC_NA); + offset += length; + } + return offset; +} + +static int +cmd_delete(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_delete, tvb, offset, 32, ENC_NA|ENC_ASCII); + offset += 32; + return offset; +} + +static int +cmd_list(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_list_block_number, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + return offset; +} + +static int +resp_list(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree *tree; + guint32 i, count; + + proto_tree_add_item_ret_uint(pt, hf_gryphon_list_num_programs, tvb, offset, 1, ENC_BIG_ENDIAN, &count); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 1, ENC_NA); + offset += 2; + + proto_tree_add_item(pt, hf_gryphon_list_num_remain_programs, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + for (i = 1; i <= count; i++) { + tree = proto_tree_add_subtree_format(pt, tvb, offset, 112, ett_gryphon_pgm_list, NULL, "Program %u", i); + proto_tree_add_item(tree, hf_gryphon_list_name, tvb, offset, 32, ENC_NA|ENC_ASCII); + offset += 32; + + proto_tree_add_item(tree, hf_gryphon_list_description, tvb, offset, 80, ENC_NA|ENC_ASCII); + offset += 80; + } + return offset; +} + +static int +cmd_start(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *pt) +{ + char *string; + gint length; + int msglen; + int hdr_stuff = offset; + + msglen = tvb_reported_length_remaining(tvb, offset); + offset = cmd_delete(tvb, offset, pt); /* decode the name */ + if (offset < msglen + hdr_stuff) { + string = tvb_get_stringz_enc(pinfo->pool, tvb, offset, &length, ENC_ASCII); + if (length > 1) { + proto_tree_add_string(pt, hf_gryphon_start_arguments, tvb, offset, + length, string); + offset += length; + + length = 3 - (length + 3) % 4; + if (length) { + proto_tree_add_item(pt, hf_gryphon_padding, tvb, offset, length, ENC_NA); + offset += length; + } + } + } + return offset; +} + +static int +resp_start(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + + msglen = tvb_reported_length_remaining(tvb, offset); + if (msglen > 0) { + proto_tree_add_item(pt, hf_gryphon_start_channel, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + } + return offset; +} + +static int +resp_status(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_item *item; + proto_tree *tree; + unsigned int i, copies, length, channel; + + copies = tvb_get_guint8(tvb, offset); + item = proto_tree_add_item(pt, hf_gryphon_status_num_running_copies, tvb, offset, 1, ENC_BIG_ENDIAN); + tree = proto_item_add_subtree (item, ett_gryphon_pgm_status); + offset += 1; + if (copies) { + for (i = 1; i <= copies; i++) { + channel = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format(tree, hf_gryphon_program_channel_number, tvb, offset, 1, channel, + "Program %u channel (client) number %u", i, channel); + offset += 1; + } + } + length = 3 - (copies + 1 + 3) % 4; + if (length) { + proto_tree_add_item(pt, hf_gryphon_padding, tvb, offset, length, ENC_NA); + offset += length; + } + return offset; +} + +static int +cmd_options(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + proto_tree *tree; + unsigned int i, size, padding, option, option_length, option_value; + const char *string, *string1; + + msglen = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_options_handle, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + msglen -= 4; + + for (i = 1; msglen > 0; i++) { + option_length = tvb_get_guint8(tvb, offset+1); + size = option_length + 2; + padding = 3 - ((size + 3) %4); + tree = proto_tree_add_subtree_format(pt, tvb, offset, size + padding, ett_gryphon_pgm_options, NULL, "Option number %u", i); + option = tvb_get_guint8(tvb, offset); + switch (option_length) { + case 1: + option_value = tvb_get_guint8(tvb, offset+2); + break; + case 2: + option_value = tvb_get_ntohs(tvb, offset+2); + break; + case 4: + option_value = tvb_get_ntohl(tvb, offset+2); + break; + default: + option_value = 0; + } + string = "unknown option"; + string1 = "unknown option data"; + switch (option) { + case PGM_CONV: + string = "Type of data in the file"; + switch (option_value) { + case PGM_BIN: + string1 = "Binary - Don't modify"; + break; + case PGM_ASCII: + string1 = "ASCII - Remove CR's"; + break; + } + break; + case PGM_TYPE: + string = "Type of file"; + switch (option_value) { + case PGM_PGM: + string1 = "Executable"; + break; + case PGM_DATA: + string1 = "Data"; + break; + } + break; + } + proto_tree_add_uint_format_value(tree, hf_gryphon_option, tvb, offset, 1, option, "%s", string); + proto_tree_add_bytes_format_value(tree, hf_gryphon_option_data, tvb, offset+2, option_length, NULL, "%s", string1); + if (padding) + proto_tree_add_item(tree, hf_gryphon_padding, tvb, offset+option_length+2, padding, ENC_NA); + offset += size + padding; + msglen -= size + padding; + } + return offset; +} + +static int +cmd_files(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + guint8 file; + + msglen = tvb_reported_length_remaining(tvb, offset); + file = tvb_get_guint8(tvb, offset); + if (file == 0) + proto_tree_add_uint_format(pt, hf_gryphon_cmd_file, tvb, offset, 1, file, "First group of names"); + else + proto_tree_add_uint_format(pt, hf_gryphon_cmd_file, tvb, offset, 1, file, "Subsequent group of names"); + + proto_tree_add_item(pt, hf_gryphon_files, tvb, offset+1, msglen-1, ENC_NA|ENC_ASCII); + offset += msglen; + return offset; +} + +static int +resp_files(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int msglen; + + msglen = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_more_filenames, tvb, offset, 1, ENC_NA); + proto_tree_add_item(pt, hf_gryphon_filenames, tvb, offset+1, msglen-1, ENC_ASCII|ENC_NA); + offset += msglen; + return offset; +} + +/* 20171012 gryphon command for USDT */ +static int +cmd_usdt_register_non_legacy(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int remain; + unsigned int ui_block; + guint32 ui_ids; + int id_usdtreq; + int id_usdtresp; + int id_uudtresp; + guint8 u8_options; + guint8 u8USDTReqExtAddr_bit; + guint8 u8USDTRespExtAddr_bit; + guint8 u8UUDTRespExtAddr_bit; + guint8 u8USDTReqExtAddr; + guint8 u8USDTRespExtAddr; + guint8 u8UUDTRespExtAddr; + guint8 u8USDTReqHeaderSize; + guint8 u8USDTRespHeaderSize; + guint8 u8UUDTRespHeaderSize; + guint8 flags; + proto_tree *tree1; + proto_tree *tree2; + proto_tree *tree3; + proto_tree *tree4; + proto_tree *tree5; + static int * const transmit_options_flags[] = { + &hf_gryphon_usdt_transmit_options_flags_echo, + &hf_gryphon_usdt_transmit_options_action, + &hf_gryphon_usdt_transmit_options_done_event, + &hf_gryphon_usdt_transmit_options_echo_short, + &hf_gryphon_usdt_transmit_options_rx_nth_fc, + NULL + }; + static int * const receive_options_flags[] = { + &hf_gryphon_usdt_receive_options_action, + &hf_gryphon_usdt_receive_options_firstframe_event, + &hf_gryphon_usdt_receive_options_lastframe_event, + &hf_gryphon_usdt_receive_options_tx_nth_fc, + NULL + }; + static int * const length_options_flags[] = { + &hf_gryphon_usdt_length_control_j1939, + NULL + }; + remain = tvb_reported_length_remaining(tvb, offset); + + /* 20171012 */ + /* Action flags */ + flags = tvb_get_guint8(tvb, offset); + tree1 = proto_tree_add_subtree_format(pt, tvb, offset, 1, ett_gryphon_usdt_action_flags, NULL, "Action flags 0x%02x", flags); + proto_tree_add_item(tree1, hf_gryphon_usdt_action_flags_non_legacy, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + remain -= 1; + + /* tx options */ + flags = tvb_get_guint8(tvb, offset); + tree2 = proto_tree_add_subtree_format(pt, tvb, offset, 1, ett_gryphon_usdt_tx_options_flags, NULL, "Transmit options 0x%02x", flags); + proto_tree_add_bitmask(tree2, tvb, offset, hf_gryphon_usdt_transmit_options_flags, ett_gryphon_flags, transmit_options_flags, ENC_BIG_ENDIAN); + offset += 1; + remain -= 1; + + /* rx options */ + flags = tvb_get_guint8(tvb, offset); + tree3 = proto_tree_add_subtree_format(pt, tvb, offset, 1, ett_gryphon_usdt_rx_options_flags, NULL, "Receive options 0x%02x", flags); + proto_tree_add_bitmask(tree3, tvb, offset, hf_gryphon_usdt_receive_options_flags, ett_gryphon_flags, receive_options_flags, ENC_BIG_ENDIAN); + offset += 1; + remain -= 1; + + /* reserved */ + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + remain -= 1; + + /* blocks */ + ui_block = 1; + while (remain > 0) { + tree4 = proto_tree_add_subtree_format(pt, tvb, offset, 20, ett_gryphon_usdt_data_block, NULL, "Block %u", ui_block); + + /* TODO implement J1939-style length address src and dst byte swap */ + + /* mask the upper bits of the long */ + /* number of IDs in the block */ + ui_ids = tvb_get_ntohl (tvb, offset); + u8_options = ((ui_ids >> 24) & 0xE0); + ui_ids &= 0x1FFFFFFF; /* mask the upper control bits */ + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_nids, tvb, offset, 4, ui_ids, "%u", ui_ids); + + if(ui_ids == 0) { + proto_item_set_len(tree4, 20); + } else { + + + /* display control bits */ + tree5 = proto_tree_add_subtree_format(tree4, tvb, offset, 1, ett_gryphon_usdt_len_options_flags, NULL, "Options 0x%02x", u8_options); + proto_tree_add_bitmask(tree5, tvb, offset, hf_gryphon_usdt_length_options_flags, ett_gryphon_flags, length_options_flags, ENC_BIG_ENDIAN); + offset += 4; + remain -= 4; + + u8UUDTRespExtAddr = tvb_get_guint8(tvb, offset+10); + u8USDTRespExtAddr = tvb_get_guint8(tvb, offset+13); + u8USDTReqExtAddr = tvb_get_guint8(tvb, offset+16); + if(ui_ids == 1) { + /* single ID */ + + /* add extended address display of the IDs */ + /* mask the upper bits of the IDs */ + /* usdt req */ + id_usdtreq = tvb_get_ntohl (tvb, offset); + u8USDTReqExtAddr_bit = ((id_usdtreq >> 24) & 0x20); + u8USDTReqHeaderSize = ((id_usdtreq >> 24) & 0x80); + id_usdtreq &= 0x1FFFFFFF; + /* usdt req */ + if(u8USDTReqExtAddr_bit == 0) { + if(u8USDTReqHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request, tvb, offset, 4, id_usdtreq, "0x%02x (11-bit)", id_usdtreq); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request, tvb, offset, 4, id_usdtreq, "0x%04x (29-bit)", id_usdtreq); + } + } else { + u8USDTReqExtAddr = tvb_get_guint8(tvb, offset+16); + if(u8USDTReqHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request, tvb, offset, 4, id_usdtreq, "0x%02x (11-bit extended address %01x)", id_usdtreq, u8USDTReqExtAddr); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request, tvb, offset, 4, id_usdtreq, "0x%04x (29-bit extended address %01x)", id_usdtreq, u8USDTReqExtAddr); + } + } + offset += 4; + remain -= 4; + + /* usdt resp */ + id_usdtresp = tvb_get_ntohl (tvb, offset); + u8USDTRespExtAddr_bit = ((id_usdtresp >> 24) & 0x20); + u8USDTRespHeaderSize = ((id_usdtresp >> 24) & 0x80); + id_usdtresp &= 0x1FFFFFFF; + /* usdt resp */ + if(u8USDTRespExtAddr_bit == 0) { + if(u8USDTRespHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response, tvb, offset, 4, id_usdtresp, "0x%02x (11-bit)", id_usdtresp); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response, tvb, offset, 4, id_usdtresp, "0x%04x (29-bit)", id_usdtresp); + } + } else { + u8USDTRespExtAddr = tvb_get_guint8(tvb, offset+13); + if(u8USDTRespHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response, tvb, offset, 4, id_usdtresp, "0x%02x (11-bit extended address %01x)", id_usdtresp, u8USDTRespExtAddr); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response, tvb, offset, 4, id_usdtresp, "0x%04x (29-bit extended address %01x)", id_usdtresp, u8USDTRespExtAddr); + } + } + offset += 4; + remain -= 4; + + + /* uudt resp */ + id_uudtresp = tvb_get_ntohl (tvb, offset); + u8UUDTRespExtAddr_bit = ((id_uudtresp >> 24) & 0x20); + u8UUDTRespHeaderSize = ((id_uudtresp >> 24) & 0x80); + id_uudtresp &= 0x1FFFFFFF; + /* uudt resp */ + if(u8UUDTRespExtAddr_bit == 0) { + if(u8UUDTRespHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response, tvb, offset, 4, id_uudtresp, "0x%02x (11-bit)", id_uudtresp); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response, tvb, offset, 4, id_uudtresp, "0x%04x (29-bit)", id_uudtresp); + } + } else { + u8UUDTRespExtAddr = tvb_get_guint8(tvb, offset+10); + if(u8UUDTRespHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response, tvb, offset, 4, id_uudtresp, "0x%02x (11-bit extended address %01x)", id_uudtresp, u8UUDTRespExtAddr); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response, tvb, offset, 4, id_uudtresp, "0x%04x (29-bit extended address %01x)", id_uudtresp, u8UUDTRespExtAddr); + } + } + offset += 4; + remain -= 4; + + + } else { + /* multiple IDs */ + + /* add extended address display of the IDs */ + /* mask the upper bits of the IDs */ + + /* usdt req */ + id_usdtreq = tvb_get_ntohl (tvb, offset); + u8USDTReqExtAddr_bit = ((id_usdtreq >> 24) & 0x20); + u8USDTReqHeaderSize = ((id_usdtreq >> 24) & 0x80); + id_usdtreq &= 0x1FFFFFFF; + /* usdt req */ + if(u8USDTReqExtAddr_bit == 0) { + if(u8USDTReqHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request, tvb, offset, 4, id_usdtreq, "0x%02x through 0x%02x (11-bit)", id_usdtreq, id_usdtreq + ui_ids-1); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request, tvb, offset, 4, id_usdtreq, "0x%04x through 0x%04x (29-bit)", id_usdtreq, id_usdtreq + ui_ids-1); + } + } else { + u8USDTReqExtAddr = tvb_get_guint8(tvb, offset+16); + if(u8USDTReqHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request, tvb, offset, 4, id_usdtreq, "0x%02x through 0x%02x (11-bit extended address %0x)", id_usdtreq, id_usdtreq + ui_ids-1, u8USDTReqExtAddr); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request, tvb, offset, 4, id_usdtreq, "0x%04x through 0x%04x (29-bit extended address %0x)", id_usdtreq, id_usdtreq + ui_ids-1, u8USDTReqExtAddr); + } + } + offset += 4; + remain -= 4; + + /* usdt resp */ + id_usdtresp = tvb_get_ntohl (tvb, offset); + u8USDTRespExtAddr_bit = ((id_usdtresp >> 24) & 0x20); + u8USDTRespHeaderSize = ((id_usdtresp >> 24) & 0x80); + id_usdtresp &= 0x1FFFFFFF; + /* usdt resp */ + if(u8USDTRespExtAddr_bit == 0) { + if(u8USDTRespHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response, tvb, offset, 4, id_usdtresp, "0x%02x through 0x%02x (11-bit)", id_usdtresp, id_usdtresp + ui_ids-1); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response, tvb, offset, 4, id_usdtresp, "0x%04x through 0x%04x (29-bit)", id_usdtresp, id_usdtresp + ui_ids-1); + } + } else { + u8USDTRespExtAddr = tvb_get_guint8(tvb, offset+13); + if(u8USDTRespHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response, tvb, offset, 4, id_usdtresp, "0x%02x through 0x%02x (11-bit extended address %01x)", id_usdtresp, id_usdtresp + ui_ids-1, u8USDTRespExtAddr); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response, tvb, offset, 4, id_usdtresp, "0x%04x through 0x%04x (29-bit extended address %01x)", id_usdtresp, id_usdtresp + ui_ids-1, u8USDTRespExtAddr); + } + } + offset += 4; + remain -= 4; + + /* uudt resp */ + id_uudtresp = tvb_get_ntohl (tvb, offset); + u8UUDTRespExtAddr_bit = ((id_uudtresp >> 24) & 0x20); + u8UUDTRespHeaderSize = ((id_uudtresp >> 24) & 0x80); + id_uudtresp &= 0x1FFFFFFF; + /* uudt resp */ + if(u8UUDTRespExtAddr_bit == 0) { + if(u8UUDTRespHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response, tvb, offset, 4, id_uudtresp, "0x%02x through 0x%02x (11-bit)", id_uudtresp, id_uudtresp + ui_ids-1); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response, tvb, offset, 4, id_uudtresp, "0x%04x through 0x%04x (29-bit)", id_uudtresp, id_uudtresp + ui_ids-1); + } + } else { + u8UUDTRespExtAddr = tvb_get_guint8(tvb, offset+10); + if(u8UUDTRespHeaderSize == 0) { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response, tvb, offset, 4, id_uudtresp, "0x%02x through 0x%02x (11-bit extended address %01x)", id_uudtresp, id_uudtresp + ui_ids-1, u8UUDTRespExtAddr); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response, tvb, offset, 4, id_uudtresp, "0x%04x through 0x%04x (29-bit extended address %01x)", id_uudtresp, id_uudtresp + ui_ids-1, u8UUDTRespExtAddr); + } + } + offset += 4; + remain -= 4; + } + + if(u8USDTReqExtAddr_bit == 0) { + /* proto_tree_add_item(tree4, hf_gryphon_reserved, tvb, offset, 1, ENC_NA); */ + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request_ext, tvb, offset, 1, 0, "(no extended address)"); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_request_ext, tvb, offset, 1, u8USDTReqExtAddr, "0x%01x", u8USDTReqExtAddr); + } + offset += 1; + remain -= 1; + + if(u8USDTRespExtAddr_bit == 0) { + /* proto_tree_add_item(tree4, hf_gryphon_reserved, tvb, offset, 1, ENC_NA); */ + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response_ext, tvb, offset, 1, 0, "(no extended address)"); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_usdt_response_ext, tvb, offset, 1, u8USDTRespExtAddr, "0x%01x", u8USDTRespExtAddr); + } + offset += 1; + remain -= 1; + + if(u8UUDTRespExtAddr_bit == 0) { + /* proto_tree_add_item(tree4, hf_gryphon_reserved, tvb, offset, 1, ENC_NA); */ + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response_ext, tvb, offset, 1, 0, "(no extended address)"); + } else { + proto_tree_add_uint_format_value(tree4, hf_gryphon_uudt_response_ext, tvb, offset, 1, u8UUDTRespExtAddr, "0x%01x", u8UUDTRespExtAddr); + } + offset += 1; + remain -= 1; + + proto_tree_add_item(tree4, hf_gryphon_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + remain -= 1; + } + + + ui_block += 1; + } + + return offset; +} + +/* 20171012 gryphon command for USDT */ +static int +cmd_usdt_stmin_fc(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_usdt_stmin_fc, tvb, offset, 1, ENC_NA); + offset += 1; + + return offset; +} + +/* 20171012 gryphon command for USDT */ +static int +cmd_usdt_bsmax_fc(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_usdt_bsmax_fc, tvb, offset, 1, ENC_NA); + offset += 1; + + return offset; +} + +/* 20171012 gryphon command for USDT */ +static int +cmd_usdt_stmin_override(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_usdt_stmin_override, tvb, offset, 1, ENC_NA); + offset += 1; + + return offset; +} + +/* 20171012 gryphon command for USDT */ +static int +cmd_usdt_get_stmin_override(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_usdt_stmin_override, tvb, offset, 1, ENC_NA); + offset += 1; + /* fixed this for get */ + proto_tree_add_item(pt, hf_gryphon_usdt_stmin_override_active, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + return offset; +} + +/* 20171012 gryphon command for USDT */ +static int +cmd_usdt_stmin_override_activate(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_usdt_stmin_override_activate, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + return offset; +} + +/* 20171012 gryphon command for USDT */ +static int +cmd_usdt_set_stmin_mul(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + float value; + /* TODO fix this float value? */ + value = tvb_get_ntohieee_float (tvb, offset); + proto_tree_add_float_format_value(pt, hf_gryphon_usdt_set_stmin_mul, tvb, offset, 4, + value, "%.1f", value); + offset += 4; + + return offset; +} + +/* + * legacy command for usdt register + */ +static int +cmd_usdt(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int ids, id, remain, size, i, bytes; + guint8 flags; + proto_tree *localTree; + proto_item *localItem; + + flags = tvb_get_guint8(tvb, offset); + proto_tree_add_item(pt, hf_gryphon_usdt_flags_register, tvb, offset, 1, ENC_BIG_ENDIAN); + + if (flags & 1) { + static int * const action_flags[] = { + &hf_gryphon_usdt_action_flags_register, + &hf_gryphon_usdt_action_flags_action, + NULL + }; + + static int * const transmit_option_flags[] = { + &hf_gryphon_usdt_transmit_options_flags_echo, + &hf_gryphon_usdt_transmit_options_action, + &hf_gryphon_usdt_transmit_options_send_done, + NULL + }; + + static int * const receive_option_flags[] = { + &hf_gryphon_usdt_receive_options_action, + &hf_gryphon_usdt_receive_options_firstframe, + &hf_gryphon_usdt_receive_options_lastframe, + NULL + }; + + proto_tree_add_bitmask(pt, tvb, offset, hf_gryphon_usdt_action_flags, ett_gryphon_flags, action_flags, ENC_BIG_ENDIAN); + proto_tree_add_bitmask(pt, tvb, offset+1, hf_gryphon_usdt_transmit_options_flags, ett_gryphon_flags, transmit_option_flags, ENC_BIG_ENDIAN); + proto_tree_add_bitmask(pt, tvb, offset+2, hf_gryphon_usdt_receive_options_flags, ett_gryphon_flags, receive_option_flags, ENC_BIG_ENDIAN); + + if ((ids = tvb_get_guint8(tvb, offset+3))) { + localItem = proto_tree_add_item(pt, hf_gryphon_usdt_ext_address, tvb, offset+3, 1, ENC_BIG_ENDIAN); + offset += 4; + + localTree = proto_item_add_subtree (localItem, ett_gryphon_usdt_data); + while (ids) { + proto_tree_add_item(localTree, hf_gryphon_usdt_ext_address_id, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + ids--; + } + } else { + proto_tree_add_uint_format_value(pt, hf_gryphon_usdt_ext_address, tvb, offset+3, 1, + 0, "Using extended addressing for the single, internally defined, ID"); + offset += 4; + } + for (i = 0; i < 2; i++) { + bytes = tvb_reported_length_remaining (tvb, offset); + if (bytes <= 0) + break; + localTree = proto_tree_add_subtree_format(pt, tvb, offset, 16, ett_gryphon_usdt_data, NULL, "%s block of USDT/UUDT IDs", i==0?"First":"Second"); + + size = tvb_get_ntohl (tvb, offset); + localItem = proto_tree_add_item(localTree, hf_gryphon_usdt_block_size, tvb, offset, 4, ENC_BIG_ENDIAN); + localTree = proto_item_add_subtree (localItem, ett_gryphon_usdt_data_block); + if (size == 0) { + proto_item_set_len(localItem, 16); + } else { + offset += 4; + id = tvb_get_ntohl (tvb, offset); + proto_tree_add_uint_format_value(localTree, hf_gryphon_usdt_request, tvb, offset, 4, id, "%04X through %04X", id, id+size-1); + offset += 4; + + id = tvb_get_ntohl (tvb, offset); + proto_tree_add_uint_format_value(localTree, hf_gryphon_usdt_response, tvb, offset, 4, id, "%04X through %04X", id, id+size-1); + offset += 4; + + id = tvb_get_ntohl (tvb, offset); + proto_tree_add_uint_format_value(localTree, hf_gryphon_uudt_response, tvb, offset, 4, id, "%04X through %04X", id, id+size-1); + offset += 4; + } + } + } else { + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + } + + if ((remain = tvb_reported_length_remaining(tvb, offset))) { + proto_tree_add_item(pt, hf_gryphon_ignored, tvb, offset, remain, ENC_NA); + offset += remain; + } + + return offset; +} + +static int +cmd_bits_in (tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int value; + + value = tvb_get_guint8(tvb, offset); + if (value) { + static int * const digital_values[] = { + &hf_gryphon_bits_in_input1, + &hf_gryphon_bits_in_input2, + &hf_gryphon_bits_in_input3, + &hf_gryphon_bits_in_pushbutton, + NULL + }; + proto_tree_add_bitmask(pt, tvb, 1, hf_gryphon_bit_in_digital_data, ett_gryphon_digital_data, digital_values, ENC_NA); + } else { + proto_tree_add_uint_format(pt, hf_gryphon_bit_in_digital_data, tvb, offset, 1, value, "No digital values are set"); + } + + offset++; + return offset; +} + +static int +cmd_bits_out (tvbuff_t *tvb, int offset, proto_tree *pt) +{ + int value; + + value = tvb_get_guint8(tvb, offset); + if (value) { + static int * const digital_values[] = { + &hf_gryphon_bits_out_output1, + &hf_gryphon_bits_out_output2, + NULL + }; + proto_tree_add_bitmask(pt, tvb, 1, hf_gryphon_bit_out_digital_data, ett_gryphon_digital_data, digital_values, ENC_NA); + } else { + proto_tree_add_uint_format(pt, hf_gryphon_bit_out_digital_data, tvb, offset, 1, value, "No digital values are set"); + } + + offset++; + return offset; +} + +static int +cmd_init_strat (tvbuff_t *tvb, int offset, proto_tree *pt) +{ + guint32 reset_limit; + int msglen, indx; + float value; + + msglen = tvb_reported_length_remaining(tvb, offset); + reset_limit = tvb_get_ntohl(tvb, offset); + proto_tree_add_uint_format_value(pt, hf_gryphon_init_strat_reset_limit, tvb, offset, 4, + reset_limit, "Reset Limit = %u messages", reset_limit); + offset += 4; + msglen -= 4; + for (indx = 1; msglen; indx++, offset++, msglen--) { + value = tvb_get_guint8(tvb, offset); + if (value) + proto_tree_add_float_format_value(pt, hf_gryphon_init_strat_delay, tvb, offset, 1, + value/4, "Delay %d = %.2f seconds", indx, value/4); + else + proto_tree_add_float_format_value(pt, hf_gryphon_init_strat_delay, tvb, offset, 1, + 0, "Delay %d = infinite", indx); + } + + return offset; +} + +static int +speed(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_tree_add_item(pt, hf_gryphon_speed_baud_rate_index, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset+1, 3, ENC_NA); + offset += 4; + return offset; +} + +static int +blm_mode(tvbuff_t *tvb, int offset, proto_tree *pt) +{ + proto_item *item; + proto_tree *tree; + guint32 mode, milliseconds; + + item = proto_tree_add_item_ret_uint(pt, hf_gryphon_blm_mode, tvb, offset, 4, ENC_BIG_ENDIAN, &mode); + tree = proto_item_add_subtree(item, ett_gryphon_blm_mode); + offset += 4; + switch (mode) { + case 1: + milliseconds = tvb_get_ntohl(tvb, offset); + proto_tree_add_uint_format_value(tree, hf_gryphon_blm_mode_avg_period, tvb, offset, 4, + milliseconds, "%d.%03d seconds", milliseconds/1000, milliseconds%1000); + break; + case 2: + proto_tree_add_item(tree, hf_gryphon_blm_mode_avg_frames, tvb, offset, 4, ENC_BIG_ENDIAN); + break; + default: + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset, 4, ENC_NA); + break; + } + + offset += 4; + return offset; +} + +static gryphon_conversation* +get_conversation_data(packet_info* pinfo) +{ + conversation_t *conversation; + gryphon_conversation *conv_data; + + /* Find a conversation, create a new if no one exists */ + conversation = find_or_create_conversation(pinfo); + conv_data = (gryphon_conversation*)conversation_get_proto_data(conversation, proto_gryphon); + + if (conv_data == NULL) { + conv_data = wmem_new(wmem_file_scope(), gryphon_conversation); + conv_data->request_frame_data = wmem_list_new(wmem_file_scope()); + conversation_add_proto_data(conversation, proto_gryphon, (void *)conv_data); + } + + return conv_data; +} + +static int +decode_command(tvbuff_t *tvb, packet_info* pinfo, int msglen, int offset, int dst, proto_tree *pt) +{ + guint32 cmd; + guint32 context, ioctl_command; + proto_tree *ft; + proto_item *hi; + gryphon_pkt_info_t *pkt_info; + + hi = proto_tree_add_item_ret_uint(pt, hf_gryphon_cmd, tvb, offset, 1, ENC_BIG_ENDIAN, &cmd); + proto_item_set_hidden(hi); + + if (cmd > 0x3F) + cmd += dst * 256; + + pkt_info = (gryphon_pkt_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_gryphon, (guint32)tvb_raw_offset(tvb)); + + if (!pkt_info) { + /* Find a conversation, create a new if no one exists */ + gryphon_conversation *conv_data = get_conversation_data(pinfo); + + pkt_info = wmem_new0(wmem_file_scope(), gryphon_pkt_info_t); + + /* load information into the request frame */ + pkt_info->cmd = cmd; + pkt_info->req_frame_num = pinfo->num; + pkt_info->req_time = pinfo->abs_ts; + + wmem_list_prepend(conv_data->request_frame_data, pkt_info); + + p_add_proto_data(wmem_file_scope(), pinfo, proto_gryphon, (guint32)tvb_raw_offset(tvb), pkt_info); + } + + proto_tree_add_uint(pt, hf_gryphon_command, tvb, offset, 1, cmd); + proto_tree_add_item_ret_uint(pt, hf_gryphon_cmd_context, tvb, offset + 1, 1, ENC_NA, &context); + if (!pinfo->fd->visited) { + pkt_info->cmd_context = context; + } + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset + 2, 2, ENC_NA); + if (pkt_info->rsp_frame_num > 0) { + proto_item* it = proto_tree_add_uint(pt, hf_gryphon_response_in, + tvb, 0, 0, pkt_info->rsp_frame_num); + proto_item_set_generated(it); + } + offset += 4; + msglen -= 4; + + if (msglen > 0) + { + ft = proto_tree_add_subtree_format(pt, tvb, offset, msglen, ett_gryphon_command_data, NULL, + "Data: (%d byte%s)", msglen, plurality(msglen, "", "s")); + + switch (cmd) + { + case CMD_INIT: + offset = cmd_init(tvb, offset, ft); + break; + case CMD_EVENT_ENABLE: + case CMD_EVENT_DISABLE: + offset = eventnum(tvb, offset, ft); + break; + case CMD_SET_TIME: + offset = resp_time(tvb, offset, ft); + break; + case CMD_CARD_SET_SPEED: + offset = speed(tvb, offset, ft); + break; + case CMD_CARD_SET_FILTER: + offset = cmd_setfilt(tvb, offset, ft); + break; + case CMD_CARD_GET_FILTER: + offset = resp_addfilt(tvb, offset, ft); + break; + case CMD_CARD_TX: + offset = decode_data(tvb, offset, ft); + break; + case CMD_CARD_ADD_FILTER: + offset = cmd_addfilt(tvb, offset, ft); + break; + case CMD_CARD_MODIFY_FILTER: + offset = cmd_modfilt(tvb, offset, ft); + break; + case CMD_CARD_SET_DEFAULT_FILTER: + offset = dfiltmode(tvb, offset, ft); + break; + case CMD_CARD_SET_FILTER_MODE: + offset = filtmode(tvb, offset, ft); + break; + case CMD_SERVER_REG: + offset = cmd_register(tvb, offset, ft); + break; + case CMD_SERVER_SET_SORT: + offset = cmd_sort(tvb, offset, ft); + break; + case CMD_SERVER_SET_OPT: + offset = cmd_optimize(tvb, offset, ft); + break; + case CMD_BLM_SET_MODE: + offset = blm_mode(tvb, offset, ft); + break; + case CMD_LDF_LIST: + offset = cmd_ldf_list(tvb, offset, ft); + break; + case CMD_LDF_DELETE: + offset = cmd_ldf_delete(tvb, offset, ft); + break; + case CMD_LDF_DESC: + offset = cmd_ldf_desc(tvb, offset, ft); + break; + case CMD_LDF_UPLOAD: + offset = cmd_ldf_upload(tvb, offset, ft); + break; + case CMD_LDF_PARSE: + offset = cmd_ldf_parse(tvb, offset, ft); + break; + case CMD_GET_NODE_SIGNALS: + offset = cmd_ldf_get_node_signals(tvb, offset, ft); + break; + case CMD_GET_FRAMES: + offset = cmd_ldf_get_frames(tvb, offset, ft); + break; + case CMD_GET_FRAME_INFO: + offset = cmd_ldf_get_frame_info(tvb, pinfo, offset, ft); + break; + case CMD_GET_SIGNAL_INFO: + offset = cmd_ldf_get_signal_info(tvb, offset, ft); + break; + case CMD_GET_SIGNAL_DETAIL: + offset = cmd_ldf_get_signal_detail(tvb, offset, ft); + break; + case CMD_GET_ENCODING_INFO: + offset = cmd_ldf_get_encoding_info(tvb, offset, ft); + break; + case CMD_SAVE_SESSION: + offset = cmd_ldf_save_session(tvb, offset, ft); + break; + case CMD_EMULATE_NODES: + offset = cmd_ldf_emulate_nodes(tvb, pinfo, offset, ft); + break; + case CMD_START_SCHEDULE: + offset = cmd_ldf_start_schedule(tvb, offset, ft); + break; + case CMD_RESTORE_SESSION: + offset = cmd_restore_session(tvb, offset, ft); + break; + case CMD_CNVT_GET_VALUES: + offset = cmd_cnvt_get_values(tvb, offset, ft); + break; + case CMD_CNVT_GET_UNITS: + offset = cmd_cnvt_get_units(tvb, offset, ft); + break; + case CMD_CNVT_SET_VALUES: + offset = cmd_cnvt_set_values(tvb, offset, ft); + break; + case CMD_CNVT_SAVE_SESSION: + offset = cmd_ldf_save_session(tvb, offset, ft); + break; + case CMD_CNVT_RESTORE_SESSION: + offset = cmd_restore_session(tvb, offset, ft); + break; + case CMD_CNVT_DESTROY_SESSION: + offset = cmd_cnvt_destroy_session(tvb, offset, ft); + break; + case CMD_CNVT_GET_NODE_SIGNALS: + offset = cmd_ldf_get_node_signals(tvb, offset, ft); + break; + case CMD_MSGRESP_ADD: + offset = cmd_addresp(tvb, offset, pinfo, ft); + break; + case CMD_MSGRESP_GET: + offset = resp_addresp(tvb, offset, ft); + break; + case CMD_MSGRESP_MODIFY: + offset = cmd_modresp(tvb, offset, ft); + break; + case CMD_PGM_DESC: + offset = cmd_desc(tvb, offset, ft); + break; + case CMD_PGM_UPLOAD: + offset = cmd_upload(tvb, offset, ft); + break; + case CMD_PGM_DELETE: + offset = cmd_delete(tvb, offset, ft); + break; + case CMD_PGM_LIST: + offset = cmd_list(tvb, offset, ft); + break; + case CMD_PGM_START: + offset = cmd_start(tvb, pinfo, offset, ft); + break; + case CMD_PGM_STOP: + offset = resp_start(tvb, offset, ft); + break; + case CMD_PGM_STATUS: + offset = cmd_delete(tvb, offset, ft); + break; + case CMD_PGM_OPTIONS: + offset = cmd_options(tvb, offset, ft); + break; + case CMD_PGM_FILES: + offset = cmd_files(tvb, offset, ft); + break; + case CMD_SCHED_TX: + offset = cmd_sched(tvb, offset, ft); + break; + case CMD_SCHED_KILL_TX: + offset = resp_sched(tvb, offset, ft); + break; + case CMD_SCHED_MSG_REPLACE: + offset = cmd_sched_rep(tvb, offset, ft); + break; + case CMD_USDT_REGISTER: + offset = cmd_usdt(tvb, offset, ft); + break; + case CMD_USDT_SET_FUNCTIONAL: + offset = cmd_usdt(tvb, offset, ft); + break; + case CMD_USDT_SET_STMIN_MULT: + offset = cmd_usdt_set_stmin_mul(tvb, offset, ft); + break; + case CMD_USDT_REGISTER_NON_LEGACY: + offset = cmd_usdt_register_non_legacy(tvb, offset, ft); + break; + case CMD_USDT_SET_STMIN_FC: + offset = cmd_usdt_stmin_fc(tvb, offset, ft); + break; + case CMD_USDT_SET_BSMAX_FC: + offset = cmd_usdt_bsmax_fc(tvb, offset, ft); + break; + case CMD_USDT_SET_STMIN_OVERRIDE: + offset = cmd_usdt_stmin_override(tvb, offset, ft); + break; + case CMD_USDT_ACTIVATE_STMIN_OVERRIDE: + offset = cmd_usdt_stmin_override_activate(tvb, offset, ft); + break; + case CMD_IOPWR_CLRLATCH: + offset = cmd_bits_in(tvb, offset, ft); + break; + case CMD_IOPWR_SETOUT: + case CMD_IOPWR_SETBIT: + case CMD_IOPWR_CLRBIT: + offset = cmd_bits_out(tvb, offset, ft); + break; + case CMD_UTIL_SET_INIT_STRATEGY: + offset = cmd_init_strat(tvb, offset, ft); + break; + case CMD_CARD_IOCTL: + ioctl_command = tvb_get_ntohl(tvb, offset); + /* save the IOCTL in the context array for use during the command response */ + if (!pinfo->fd->visited) { + pkt_info->ioctl_command = ioctl_command; + } + offset = cmd_ioctl(tvb, pinfo, offset, ft, ioctl_command); + break; + default: + proto_tree_add_item(ft, hf_gryphon_data, tvb, offset, msglen, ENC_NA); + offset += msglen; + break; + } + } + + return offset; +} + +static int +decode_response(tvbuff_t *tvb, packet_info* pinfo, int offset, int src, proto_tree *pt) +{ + int msglen; + guint32 cmd; + proto_tree *ft; + gryphon_pkt_info_t *pkt_info, *pkt_info_list; + + msglen = tvb_reported_length_remaining(tvb, offset); + cmd = tvb_get_guint8(tvb, offset); + + if (cmd > 0x3F) + cmd += src * 256; + + pkt_info = (gryphon_pkt_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_gryphon, (guint32)tvb_raw_offset(tvb)); + + if (!pkt_info) { + /* Find a conversation, create a new if no one exists */ + gryphon_conversation *conv_data = get_conversation_data(pinfo); + + pkt_info = wmem_new0(wmem_file_scope(), gryphon_pkt_info_t); + + wmem_list_frame_t *frame = wmem_list_head(conv_data->request_frame_data); + /* Step backward through all logged instances of request frames, looking for a request frame number that + occurred immediately prior to current frame number that has a matching command */ + while (frame) { + pkt_info_list = (gryphon_pkt_info_t*)wmem_list_frame_data(frame); + if ((pinfo->num > pkt_info_list->req_frame_num) && (pkt_info_list->rsp_frame_num == 0) && (pkt_info_list->cmd == cmd)) { + pkt_info->req_frame_num = pkt_info_list->req_frame_num; + pkt_info->cmd_context = pkt_info_list->cmd_context; + pkt_info->ioctl_command = pkt_info_list->ioctl_command; + pkt_info->req_time = pkt_info_list->req_time; + pkt_info_list->rsp_frame_num = pinfo->num; + break; + } + + frame = wmem_list_frame_next(frame); + } + + p_add_proto_data(wmem_file_scope(), pinfo, proto_gryphon, (guint32)tvb_raw_offset(tvb), pkt_info); + } + + /* + * This is the old original way of displaying. + * + * XXX - is there some reason not to display the context for ioctl + * commands, and to display the ioctl code here, rather than in + * the part of the tree for the ioctl response? + */ + proto_tree_add_uint(pt, hf_gryphon_command, tvb, offset, 1, cmd); + if (pkt_info->ioctl_command != 0) { + proto_tree_add_uint(pt, hf_gryphon_cmd_ioctl_context, tvb, 0, 0, pkt_info->ioctl_command); + } else { + proto_tree_add_item(pt, hf_gryphon_cmd_context, tvb, offset + 1, 1, ENC_NA); + } + proto_tree_add_item(pt, hf_gryphon_reserved, tvb, offset + 2, 2, ENC_NA); + offset += 4; + msglen -= 4; + + proto_tree_add_item(pt, hf_gryphon_status, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + msglen -= 4; + + if (pkt_info->req_frame_num) { + proto_item *it; + nstime_t ns; + + it = proto_tree_add_uint(pt, hf_gryphon_response_to, tvb, 0, 0, pkt_info->req_frame_num); + proto_item_set_generated(it); + + nstime_delta(&ns, &pinfo->fd->abs_ts, &pkt_info->req_time); + it = proto_tree_add_time(pt, hf_gryphon_response_time, tvb, 0, 0, &ns); + proto_item_set_generated(it); + } + + if (msglen > 0) { + ft = proto_tree_add_subtree_format(pt, tvb, offset, msglen, ett_gryphon_response_data, NULL, + "Data: (%d byte%s)", msglen, plurality(msglen, "", "s")); + + switch (cmd) + { + case CMD_GET_CONFIG: + offset = resp_config(tvb, offset, ft); + break; + case CMD_GET_TIME: + offset = resp_time(tvb, offset, ft); + break; + case CMD_CARD_GET_SPEED: + offset = speed(tvb, offset, ft); + break; + case CMD_CARD_GET_FILTER: + offset = cmd_addfilt(tvb, offset, ft); + break; + case CMD_CARD_ADD_FILTER: + offset = resp_addfilt(tvb, offset, ft); + break; + case CMD_CARD_GET_FILTER_HANDLES: + offset = resp_filthan(tvb, offset, ft); + break; + case CMD_CARD_GET_DEFAULT_FILTER: + offset = dfiltmode(tvb, offset, ft); + break; + case CMD_CARD_GET_FILTER_MODE: + offset = filtmode(tvb, offset, ft); + break; + case CMD_CARD_GET_EVNAMES: + offset = resp_events(tvb, offset, ft); + break; + case CMD_CARD_GET_SPEEDS: + offset = resp_getspeeds(tvb, offset, ft); + break; + case CMD_SERVER_REG: + offset = resp_register(tvb, offset, ft); + break; + case CMD_BLM_GET_MODE: + offset = blm_mode(tvb, offset, ft); + break; + case CMD_BLM_GET_DATA: + offset = resp_blm_data(tvb, offset, ft); + break; + case CMD_BLM_GET_STATS: + offset = resp_blm_stat(tvb, offset, ft); + break; + case CMD_LDF_LIST: + offset = resp_ldf_list(tvb, offset, ft); + break; + case CMD_LDF_DESC: + offset = resp_ldf_desc(tvb, offset, ft); + break; + case CMD_GET_LDF_INFO: + offset = resp_get_ldf_info(tvb, offset, ft); + break; + case CMD_GET_NODE_NAMES: + offset = resp_ldf_get_node_names(tvb, offset, ft); + break; + case CMD_GET_NODE_SIGNALS: + offset = resp_ldf_get_node_signals(tvb, offset, ft); + break; + case CMD_GET_FRAMES: + offset = resp_ldf_get_frames(tvb, offset, ft); + break; + case CMD_GET_FRAME_INFO: + offset = resp_ldf_get_frame_info(tvb, offset, ft); + break; + case CMD_GET_SIGNAL_INFO: + offset = resp_ldf_get_signal_info(tvb, offset, ft); + break; + case CMD_GET_SIGNAL_DETAIL: + offset = resp_ldf_get_signal_detail(tvb, pinfo, offset, ft); + break; + case CMD_GET_ENCODING_INFO: + offset = resp_ldf_get_encoding_info(tvb, pinfo, offset, ft); + break; + case CMD_GET_SCHEDULES: + offset = resp_ldf_get_schedules(tvb, offset, ft); + break; + case CMD_RESTORE_SESSION: + offset = resp_restore_session(tvb, offset, ft); + break; + case CMD_CNVT_GET_VALUES: + offset = resp_cnvt_get_values(tvb, offset, ft); + break; + case CMD_CNVT_GET_UNITS: + offset = resp_cnvt_get_units(tvb, offset, ft); + break; + case CMD_CNVT_RESTORE_SESSION: + offset = resp_restore_session(tvb, offset, ft); + break; + case CMD_CNVT_GET_NODE_SIGNALS: + offset = resp_ldf_get_node_signals(tvb, offset, ft); + break; + case CMD_MSGRESP_ADD: + offset = resp_addresp(tvb, offset, ft); + break; + case CMD_MSGRESP_GET: + offset = cmd_addresp(tvb, offset, pinfo, ft); + break; + case CMD_MSGRESP_GET_HANDLES: + offset = resp_resphan(tvb, offset, ft); + break; + case CMD_PGM_DESC: + offset = resp_desc(tvb, offset, ft); + break; + case CMD_PGM_LIST: + offset = resp_list(tvb, offset, ft); + break; + case CMD_PGM_START: + case CMD_PGM_START2: + offset = resp_start(tvb, offset, ft); + break; + case CMD_PGM_STATUS: + case CMD_PGM_OPTIONS: + offset = resp_status(tvb, offset, ft); + break; + case CMD_PGM_FILES: + offset = resp_files(tvb, offset, ft); + break; + case CMD_SCHED_TX: + offset = resp_sched(tvb, offset, ft); + break; + case CMD_USDT_GET_STMIN_FC: + offset = cmd_usdt_stmin_fc(tvb, offset, ft); + break; + case CMD_USDT_GET_BSMAX_FC: + offset = cmd_usdt_bsmax_fc(tvb, offset, ft); + break; + case CMD_USDT_GET_STMIN_OVERRIDE: + offset = cmd_usdt_get_stmin_override(tvb, offset, ft); + break; + case CMD_IOPWR_GETINP: + case CMD_IOPWR_GETLATCH: + case CMD_IOPWR_CLRLATCH: + case CMD_IOPWR_GETPOWER: + offset = cmd_bits_in(tvb, offset, ft); + break; + case CMD_IOPWR_GETOUT: + offset = cmd_bits_out(tvb, offset, ft); + break; + case CMD_UTIL_GET_INIT_STRATEGY: + offset = cmd_init_strat(tvb, offset, ft); + break; + case CMD_CARD_IOCTL: + offset = cmd_ioctl_resp(tvb, pinfo, offset, ft, pkt_info->ioctl_command); + break; + default: + proto_tree_add_item(ft, hf_gryphon_data, tvb, offset, msglen, ENC_NA); + offset += msglen; + } + } + + return offset; +} + +/* +* 20180221 +* This function exists because Gryphon Protocol MISC packets contain within them Gryphon Protocol packets. +* So, this function will decode a packet and return the offset. +*/ +static int +dissect_gryphon_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_msgresp_add) +{ + proto_tree *gryphon_tree; + proto_item *ti, *type_item; + proto_tree *header_tree, *body_tree; + int msgend, msglen, msgpad; + int offset = 0; + guint32 src, dest, i, frmtyp, flags; + + if (!is_msgresp_add) { + col_set_str(pinfo->cinfo, COL_PROTOCOL, "Gryphon"); + col_clear(pinfo->cinfo, COL_INFO); + + ti = proto_tree_add_item(tree, proto_gryphon, tvb, 0, -1, ENC_NA); + gryphon_tree = proto_item_add_subtree(ti, ett_gryphon); + } + else { + gryphon_tree = tree; + } + + header_tree = proto_tree_add_subtree(gryphon_tree, tvb, offset, MSG_HDR_SZ, ett_gryphon_header, NULL, "Header"); + + /* src */ + proto_tree_add_item_ret_uint(header_tree, hf_gryphon_src, tvb, offset, 1, ENC_BIG_ENDIAN, &src); + /* 20180306 20171012 */ + /* srcchan */ + if (is_special_client(src)) { + proto_tree_add_item(header_tree, hf_gryphon_srcchanclient, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + } + else { + proto_tree_add_item(header_tree, hf_gryphon_srcchan, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + } + + /* dest */ + proto_tree_add_item_ret_uint(header_tree, hf_gryphon_dest, tvb, offset + 2, 1, ENC_BIG_ENDIAN, &dest); + /* 20180306 20171012 */ + /* destchan */ + if (is_special_client(dest)) { + proto_tree_add_item(header_tree, hf_gryphon_destchanclient, tvb, offset + 3, 1, ENC_BIG_ENDIAN); + } + else { + proto_tree_add_item(header_tree, hf_gryphon_destchan, tvb, offset + 3, 1, ENC_BIG_ENDIAN); + } + + proto_tree_add_item_ret_uint(header_tree, hf_gryphon_data_length, tvb, offset + 4, 2, ENC_BIG_ENDIAN, &msglen); + flags = tvb_get_guint8(tvb, offset + 6); + frmtyp = flags & ~RESPONSE_FLAGS; + type_item = proto_tree_add_uint(header_tree, hf_gryphon_type, tvb, offset + 6, 1, frmtyp); + /* + * Indicate what kind of message this is. + */ + if (!is_msgresp_add) + col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(frmtyp, frame_type, "- Invalid -")); + + if (is_msgresp_add) { + static int * const wait_flags[] = { + &hf_gryphon_wait_resp, + &hf_gryphon_wait_prev_resp, + NULL + }; + + proto_tree_add_bitmask(header_tree, tvb, offset + 6, hf_gryphon_wait_flags, ett_gryphon_flags, wait_flags, ENC_NA); + } + proto_tree_add_item(header_tree, hf_gryphon_reserved, tvb, offset + 7, 1, ENC_NA); + offset += MSG_HDR_SZ; + + msgpad = 3 - (msglen + 3) % 4; + msgend = offset + msglen + msgpad; + + body_tree = proto_tree_add_subtree(gryphon_tree, tvb, offset, msglen, ett_gryphon_body, NULL, "Body"); + + switch (frmtyp) { + case GY_FT_CMD: + offset = decode_command(tvb, pinfo, msglen, offset, dest, body_tree); + break; + case GY_FT_RESP: + offset = decode_response(tvb, pinfo, offset, src, body_tree); + break; + case GY_FT_DATA: + offset = decode_data(tvb, offset, body_tree); + break; + case GY_FT_EVENT: + offset = decode_event(tvb, offset, body_tree); + break; + case GY_FT_MISC: + offset = decode_misc(tvb, offset, pinfo, body_tree); + break; + case GY_FT_TEXT: + offset = decode_text(tvb, offset, msglen, body_tree); + break; + case GY_FT_SIG: + break; + default: + expert_add_info(pinfo, type_item, &ei_gryphon_type); + proto_tree_add_item(body_tree, hf_gryphon_data, tvb, offset, msglen, ENC_NA); + break; + } + + /*debug*/ + /*i = msgend - offset;*/ + /*proto_tree_add_debug_text(gryphon_tree, "debug offset=%d msgend=%d i=%d",offset,msgend,i);*/ + + if (offset < msgend) { + i = msgend - offset; + /* + * worked when msglen=4, offset=8, msgend=12, get i=4 + * did not work when msglen=5, offset=8, msgend=16, i is 8 + */ + proto_tree_add_item(gryphon_tree, hf_gryphon_padding, tvb, offset, i, ENC_NA); + offset += i; + } + return offset; +} + +static guint +get_gryphon_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) +{ + guint16 plen; + int padded_len; + + /* + * Get the length of the Gryphon packet, and then get the length as + * padded to a 4-byte boundary. + */ + plen = tvb_get_ntohs(tvb, offset + 4); + padded_len = plen + 3 - (plen + 3) % 4; + + /* + * That length doesn't include the fixed-length part of the header; + * add that in. + */ + return padded_len + GRYPHON_FRAME_HEADER_LEN; +} + +static int +dissect_gryphon_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + dissect_gryphon_message(tvb, pinfo, tree, FALSE); + return tvb_reported_length(tvb); +} + +static int +dissect_gryphon(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + tcp_dissect_pdus(tvb, pinfo, tree, gryphon_desegment, GRYPHON_FRAME_HEADER_LEN, + get_gryphon_pdu_len, dissect_gryphon_pdu, data); + return tvb_reported_length(tvb); +} + +void +proto_register_gryphon(void) +{ + static hf_register_info hf[] = { + { &hf_gryphon_src, + { "Source", "gryphon.src", FT_UINT8, BASE_HEX, VALS(src_dest), 0x0, + NULL, HFILL }}, + { &hf_gryphon_srcchan, + { "Source channel", "gryphon.srcchan", FT_UINT8, + BASE_DEC | BASE_SPECIAL_VALS, VALS(channel_or_broadcast), 0x0, + NULL, HFILL }}, + { &hf_gryphon_srcchanclient, + { "Source client id", "gryphon.srcchanclient", FT_UINT8, + BASE_DEC | BASE_SPECIAL_VALS, VALS(channel_or_broadcast), 0x0, + NULL, HFILL }}, + { &hf_gryphon_dest, + { "Destination", "gryphon.dest", FT_UINT8, BASE_HEX, VALS(src_dest), 0x0, + NULL, HFILL }}, + { &hf_gryphon_destchan, + { "Destination channel", "gryphon.destchan", FT_UINT8, + BASE_DEC | BASE_SPECIAL_VALS, VALS(channel_or_broadcast), 0x0, + NULL, HFILL }}, + { &hf_gryphon_destchanclient, + { "Destination client id", "gryphon.destchanclient", FT_UINT8, + BASE_DEC | BASE_SPECIAL_VALS, VALS(channel_or_broadcast), 0x0, + NULL, HFILL }}, + { &hf_gryphon_type, + { "Frame type", "gryphon.type", FT_UINT8, BASE_DEC, VALS(frame_type), 0x0, + NULL, HFILL }}, + { &hf_gryphon_cmd, + { "Command", "gryphon.cmd", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cmd_context, + { "Context", "gryphon.cmd.context", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cmd_ioctl_context, + { "IOCTL Response", "gryphon.cmd.ioctl_response", FT_UINT32, BASE_DEC, VALS(ioctls), 0x0, + NULL, HFILL }}, + { &hf_gryphon_data, + { "Data", "gryphon.data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_padding, + { "Padding", "gryphon.padding", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ignored, + { "Ignored", "gryphon.ignored", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_length, + { "Data length (bytes)", "gryphon.data_length", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_reserved, + { "Reserved", "gryphon.reserved", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_wait_flags, + { "Flags", "gryphon.wait_flags", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_wait_resp, + { "Wait for response", "gryphon.wait_resp", FT_BOOLEAN, 8, TFS(&tfs_wait_response), DONT_WAIT_FOR_RESP, + NULL, HFILL }}, + { &hf_gryphon_wait_prev_resp, + { "Wait for previous response", "gryphon.wait_prev_resp", FT_BOOLEAN, 8, TFS(&tfs_wait_response), WAIT_FOR_PREV_RESP, + NULL, HFILL }}, + { &hf_gryphon_status, + { "Status", "gryphon.status", FT_UINT32, BASE_HEX, VALS(responses_vs), 0x0, + NULL, HFILL }}, + { &hf_gryphon_response_in, + { "Response In", "gryphon.response_in", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0, + "The response to this Gryphon request is in this frame", HFILL }}, + { &hf_gryphon_response_to, + { "Request In", "gryphon.response_to", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0, + "This is a response to the PANA request in this frame", HFILL }}, + { &hf_gryphon_response_time, + { "Response Time", "gryphon.response_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + "The time between the request and the response", HFILL }}, + { &hf_gryphon_data_header_length, + { "Header length (bytes)", "gryphon.data.header_length", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_header_length_bits, + { "Header length (bits)", "gryphon.data.header_length", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_data_length, + { "Data length (bytes)", "gryphon.data.data_length", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_extra_data_length, + { "Extra data length (bytes)", "gryphon.data.extra_length", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_mode, + { "Mode", "gryphon.data.mode", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_mode_transmitted, + { "Transmitted message", "gryphon.data.mode.transmitted", FT_BOOLEAN, 8, TFS(&true_false), 0x80, + NULL, HFILL }}, + { &hf_gryphon_data_mode_receive, + { "Received message", "gryphon.data.mode.receive", FT_BOOLEAN, 8, TFS(&true_false), 0x40, + NULL, HFILL }}, + { &hf_gryphon_data_mode_local, + { "Local message", "gryphon.data.mode.local", FT_BOOLEAN, 8, TFS(&true_false), 0x20, + NULL, HFILL }}, + { &hf_gryphon_data_mode_remote, + { "Remote message (LIN)", "gryphon.data.mode.remote", FT_BOOLEAN, 8, TFS(&true_false), 0x10, + NULL, HFILL }}, + /* 20171012 added additional mode bits */ + { &hf_gryphon_data_mode_oneshot, + { "One-shot slave table message (LIN)", "gryphon.data.mode.oneshot", FT_BOOLEAN, 8, TFS(&true_false), 0x08, + NULL, HFILL }}, + { &hf_gryphon_data_mode_combined, + { "Channel number is in context", "gryphon.data.mode.combined", FT_BOOLEAN, 8, TFS(&true_false), 0x04, + NULL, HFILL }}, + { &hf_gryphon_data_mode_nomux, + { "Do not multiplex message", "gryphon.data.mode.nomux", FT_BOOLEAN, 8, TFS(&true_false), 0x02, + NULL, HFILL }}, + { &hf_gryphon_data_mode_internal, + { "Internal message", "gryphon.data.mode.internal", FT_BOOLEAN, 8, TFS(&true_false), 0x01, + NULL, HFILL }}, + { &hf_gryphon_data_priority, + { "Priority", "gryphon.data.priority", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_error_status, + { "Error status", "gryphon.data.error_status", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_time, + { "Timestamp", "gryphon.data.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_context, + { "Context", "gryphon.data.context", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_header_data, + { "Header", "gryphon.data.header_data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_data, + { "Data", "gryphon.data.data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_extra_data, + { "Extra data", "gryphon.data.extra_data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_data_padding, + { "Padding", "gryphon.data.padding", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_event_id, + { "Event ID", "gryphon.event.id", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_event_name, + { "Event name", "gryphon.event.name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_event_context, + { "Event context", "gryphon.event.context", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_event_time, + { "Timestamp", "gryphon.event.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_event_data, + { "Data", "gryphon.event.data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_event_padding, + { "Padding", "gryphon.event.padding", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_misc_text, + { "Text", "gryphon.misc.text", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_misc_padding, + { "Padding", "gryphon.misc.padding", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_eventnum, + { "Event numbers", "gryphon.eventnum", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_resp_time, + { "Date/Time", "gryphon.resp_time", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_setfilt, + { "Pass/Block flag", "gryphon.setfilt.flag", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_setfilt_length, + { "Length of Pattern & Mask", "gryphon.setfilt.length", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_setfilt_discard_data, + { "Discarded data", "gryphon.setfilt.discard_data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_setfilt_padding, + { "Padding", "gryphon.setfilt.padding", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ioctl, + { "IOCTL", "gryphon.ioctl", FT_UINT32, BASE_HEX, VALS(ioctls), 0x0, + NULL, HFILL }}, + { &hf_gryphon_ioctl_nbytes, + { "Number of bytes to follow (bytes)", "gryphon.ioctl_nbytes", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ioctl_data, + { "Data", "gryphon.ioctl.data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_addfilt_pass, + { "Conforming messages", "gryphon.addfilt.pass", FT_BOOLEAN, 8, TFS(&tfs_passed_blocked), FILTER_PASS_FLAG, + NULL, HFILL }}, + { &hf_gryphon_addfilt_active, + { "Filter", "gryphon.addfilt.active", FT_BOOLEAN, 8, TFS(&active_inactive), FILTER_ACTIVE_FLAG, + NULL, HFILL }}, + { &hf_gryphon_addfilt_blocks, + { "Number of filter blocks", "gryphon.addfilt.blocks", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_addfilt_handle, + { "Filter handle", "gryphon.addfilt.handle", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_modfilt, + { "Filter handle", "gryphon.modfilt", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_modfilt_action, + { "Action", "gryphon.modfilt.action", FT_UINT8, BASE_DEC, VALS(filtacts), 0x0, + NULL, HFILL }}, + { &hf_gryphon_filthan, + { "Number of filter handles", "gryphon.filthan", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filthan_id, + { "Filter handle ID", "gryphon.filthan.id", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filthan_padding, + { "Padding", "gryphon.filthan.padding", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_dfiltmode, + { "Filter mode", "gryphon.dfiltmode", FT_UINT8, BASE_DEC, VALS(dmodes), 0x0, + NULL, HFILL }}, + { &hf_gryphon_filtmode, + { "Filter mode", "gryphon.filtmode", FT_UINT8, BASE_DEC, VALS(modes), 0x0, + NULL, HFILL }}, + { &hf_gryphon_register_username, + { "Username", "gryphon.register.username", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_register_password, + { "Password", "gryphon.register.password", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_register_client_id, + { "Client ID", "gryphon.register.client_id", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_register_privileges, + { "Privileges", "gryphon.register.privileges", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_getspeeds_set_ioctl, + { "Set Speed IOCTL", "gryphon.getspeeds.set_ioctl", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_getspeeds_get_ioctl, + { "Get Speed IOCTL", "gryphon.getspeeds.get_ioctl", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_getspeeds_size, + { "Speed data size (bytes)", "gryphon.getspeeds.size", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_getspeeds_preset, + { "Preset speed numbers", "gryphon.getspeeds.preset", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_getspeeds_data, + { "Data for preset", "gryphon.getspeeds.data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cmd_sort, + { "Set sorting", "gryphon.cmd_sort", FT_UINT8, BASE_DEC, VALS(cmd_sort_type), 0x0, + NULL, HFILL }}, + { &hf_gryphon_cmd_optimize, + { "Set optimization", "gryphon.cmd_optimize", FT_UINT8, BASE_DEC, VALS(cmd_optimize_type), 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_device_name, + { "Device name", "gryphon.config.device_name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_device_version, + { "Device version", "gryphon.config.device_version", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_device_serial_number, + { "Device serial number", "gryphon.config.device_serial_number", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_num_channels, + { "Number of channels", "gryphon.config.num_channels", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_name_version_ext, + { "Name & version extension", "gryphon.config.name_version_ext", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_driver_name, + { "Driver name", "gryphon.config.driver_name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_driver_version, + { "Driver version", "gryphon.config.driver_version", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_device_security, + { "Device security string", "gryphon.config.device_security", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_max_data_length, + { "Maximum data length (bytes)", "gryphon.config.max_data_length", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_min_data_length, + { "Minimum data length (bytes)", "gryphon.config.min_data_length", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_hardware_serial_number, + { "Hardware serial number", "gryphon.config.hardware_serial_number", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_protocol_type, + { "Protocol type & subtype", "gryphon.config.protocol_type", FT_UINT16, BASE_HEX, VALS(protocol_types), 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_channel_id, + { "Channel ID", "gryphon.config.channel_id", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_card_slot_number, + { "Card slot number", "gryphon.config.card_slot_number", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_max_extra_data, + { "Maximum extra data (bytes)", "gryphon.config.max_extra_data", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_config_min_extra_data, + { "Minimum extra data (bytes)", "gryphon.config.min_extra_data", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_num_iterations, + { "Number of iterations", "gryphon.sched.num_iterations", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_flags, + { "Flags", "gryphon.sched.flags", FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_flags_scheduler, + { "Scheduler", "gryphon.sched.flags.scheduler", FT_BOOLEAN, 32, TFS(&critical_normal), 0x00000001, + NULL, HFILL }}, + { &hf_gryphon_sched_sleep, + { "Sleep (milliseconds)", "gryphon.sched.sleep", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_transmit_count, + { "Transmit count", "gryphon.sched.transmit_count", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_transmit_period, + { "Transmit period (milliseconds)", "gryphon.sched.transmit_period", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_transmit_flags, + { "Flags", "gryphon.sched.transmit_flags", FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_skip_transmit_period, + { "Last transmit period", "gryphon.sched.skip_transmit_period", FT_BOOLEAN, 16, TFS(&skip_not_skip), 0x0001, + NULL, HFILL }}, + { &hf_gryphon_sched_skip_sleep, + { "Last transmit period", "gryphon.sched.skip_transmit_period", FT_BOOLEAN, 16, TFS(&skip_not_skip), 0x0001, + NULL, HFILL }}, + { &hf_gryphon_sched_channel, + { "Channel", "gryphon.sched.channel", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_channel0, + { "Channel (specified by the destination channel)", "gryphon.sched.channel", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_rep_id, + { "Schedule ID", "gryphon.sched.rep_id", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_sched_rep_message_index, + { "Message index", "gryphon.sched.rep_message_index", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_data_time, + { "Timestamp", "gryphon.blm_data.time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_data_bus_load, + { "Bus load average (%)", "gryphon.blm_data.bus_load", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_data_current_bus_load, + { "Current bus load (%)", "gryphon.blm_data.current_bus_load", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_data_peak_bus_load, + { "Peak bus load (%)", "gryphon.blm_data.peak_bus_load", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_data_historic_peak_bus_load, + { "Historic peak bus load (%)", "gryphon.blm_data.historic_peak_bus_load", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_stat_receive_frame_count, + { "Receive frame count", "gryphon.blm_stat.receive_frame_count", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_stat_transmit_frame_count, + { "Transmit frame count", "gryphon.blm_stat.transmit_frame_count", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_stat_receive_dropped_frame_count, + { "Receive dropped frame count", "gryphon.blm_stat.receive_dropped_frame_count", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_stat_transmit_dropped_frame_count, + { "Transmit dropped frame count", "gryphon.blm_stat.transmit_dropped_frame_count", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_stat_receive_error_count, + { "Receive error count", "gryphon.blm_stat.receive_error_count", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_stat_transmit_error_count, + { "Transmit error count", "gryphon.blm_stat.transmit_error_count", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_addresp_flags, + { "Flags", "gryphon.addresp.flags", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + /* 20171017 fixed display of filter flags */ + { &hf_gryphon_addresp_flags_active, + { "Filter active flag", "gryphon.addresp.flags.active", FT_BOOLEAN, 8, TFS(&active_inactive), FILTER_ACTIVE_FLAG, + NULL, HFILL }}, + { &hf_gryphon_addresp_blocks, + { "Number of filter blocks", "gryphon.addresp.blocks", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_number, + { "Number of LDF names", "gryphon.ldf.number", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_nodenumber, + { "Number of nodes", "gryphon.ldf.nodenumber", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_list, + { "LDF block index", "gryphon.ldf.list", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_remaining, + { "Remaining LDF names", "gryphon.ldf.remaining", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_name, + { "File Name", "gryphon.ldf.name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_info_pv, + { "Protocol version", "gryphon.ldf.pv", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_info_lv, + { "Language version", "gryphon.ldf.lv", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_ui, + { "Unique identifier", "gryphon.ldf.ui", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_nodename, + { "Node Name", "gryphon.lin.nodename", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_data_length, + { "Data length (bytes)", "gryphon.lin.data_length", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_slave_table_enable, + { "Slave table entry", "gryphon.lin.slave_table_enable", FT_UINT8, BASE_DEC, VALS(lin_slave_table_enable), 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_slave_table_cs, + { "Slave table checksum", "gryphon.lin.slave_table_cs", FT_UINT8, BASE_DEC, VALS(lin_slave_table_cs), 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_slave_table_data, + { "Data", "gryphon.lin.slave_table_data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_slave_table_datacs, + { "Checksum", "gryphon.lin.slave_table_datacs", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_masterevent, + { "Starting frame id", "gryphon.lin.masterevent", FT_UINT8, BASE_DEC, VALS(lin_ioctl_masterevent), 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_numdata, + { "Number of data bytes", "gryphon.lin.numdata", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_lin_numextra, + { "Number of extra bytes", "gryphon.lin.numextra", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_description, + { "Description", "gryphon.ldf.description", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_size, + { "Size of LDF to be uploaded", "gryphon.ldf.size", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_exists, + { "LDF name existence check", "gryphon.ldf.exists", FT_UINT8, BASE_DEC, VALS(ldf_exists), 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_blockn, + { "Block number", "gryphon.ldf.blockn", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_file, + { "Upload text block", "gryphon.ldf.file", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_desc_pad, + { "Padding (TODO: need to fix response data length)", "gryphon.ldf.desc_pad", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_restore_session, + { "Session id", "gryphon.ldf.restore_session", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_schedule_name, + { "Schedule name", "gryphon.ldf.schedule_name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_schedule_msg_dbytes, + { "Data length (bytes)", "gryphon.ldf.schedule_msg_dbytes", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_schedule_flags, + { "Flags", "gryphon.ldf.schedule_flags", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_schedule_event, + { "Event driven", "gryphon.ldf.schedule_event_ev", FT_BOOLEAN, 8, TFS(&true_false), 0x80, + NULL, HFILL }}, + { &hf_gryphon_ldf_schedule_sporadic, + { "Sporadic", "gryphon.ldf.schedule_event_sp", FT_BOOLEAN, 8, TFS(&true_false), 0x40, + NULL, HFILL }}, + { &hf_gryphon_ldf_ioctl_setflags, + { "Starting frame id", "gryphon.ldf.ioctl_setflags", FT_UINT8, BASE_DEC, VALS(lin_ldf_ioctl_setflags), 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_ioctl_setflags_flags, + { "Id", "gryphon.ldf.ioctl_setflags_flags", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_numb_ids, + { "Number of ids", "gryphon.ldf.numb_ids", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_bitrate, + { "Bitrate", "gryphon.ldf.bitrate", FT_FLOAT, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_sched_size_place, + { "Placeholder for schedule size (bytes)", "gryphon.ldf.schedsize", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_sched_numb_place, + { "Placeholder for number of schedules", "gryphon.ldf.numbsched", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_sched_size, + { "Schedule size (bytes)", "gryphon.ldf.schedsize", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_num_node_names, + { "Number of node names", "gryphon.ldf.num_node_names", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_num_frames, + { "Number of frames", "gryphon.ldf.num_frames", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_get_frame, + { "Frame", "gryphon.ldf.get_frame", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_get_frame_num, + { "Number of data bytes in slave response", "gryphon.ldf.get_frame_num", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_get_frame_pub, + { "Publisher", "gryphon.ldf.get_frame_pub", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_get_frame_num_signals, + { "Number of signals", "gryphon.ldf.get_frame_num_signals", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_num_signal_names, + { "Number of signal names", "gryphon.ldf.num_signal_names", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_num_schedules, + { "Number of schedules", "gryphon.ldf.num_schedules", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_num_encodings, + { "Number of encodings", "gryphon.ldf.num_encodings", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_encoding_value, + { "Encoding value", "gryphon.ldf.encoding_value", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_encoding_min, + { "Encoding min value", "gryphon.ldf.encoding_min", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_encoding_max, + { "Encoding max value", "gryphon.ldf.encoding_max", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_master_node_name, + { "Master node name", "gryphon.ldf.master", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_slave_node_name, + { "Slave node name", "gryphon.ldf.slave", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_node_name, + { "Node name", "gryphon.ldf.node_name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_signal_name, + { "Signal name", "gryphon.ldf.signal_name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_signal_encoding_name, + { "Signal encoding name", "gryphon.ldf.signal_encoding_name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_signal_encoding_type, + { "Signal encoding type", "gryphon.ldf.signal_encoding_type", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_signal_encoding_logical, + { "Signal encoding string", "gryphon.ldf.signal_encoding_logical", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_signal_offset, + { "Offset (bits)", "gryphon.ldf.signal_offset", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_ldf_signal_length, + { "Length (bits)", "gryphon.ldf.signal_length", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + /* cnvt */ + { &hf_gryphon_cnvt_valuef, + { "Float value", "gryphon.cnvt.valuef", FT_FLOAT, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cnvt_valuei, + { "Int value", "gryphon.cnvt.valuei", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cnvt_values, + { "String value", "gryphon.cnvt.values", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cnvt_units, + { "String units", "gryphon.cnvt.units", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cnvt_flags_getvalues, + { "Flags", "gryphon.cnvt.flags.getvalues", FT_UINT8, BASE_DEC, VALS(lin_cnvt_getflags), 0x0, + NULL, HFILL }}, + /* delay driver */ + { &hf_gryphon_dd_stream, + { "Stream number", "gryphon.dd.stream", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_dd_value, + { "Value (bytes)", "gryphon.dd.value", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_dd_time, + { "Time (msec)", "gryphon.dd.time", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_addresp_responses, + { "Number of response blocks", "gryphon.addresp.responses", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_addresp_old_handle, + { "Old handle", "gryphon.addresp.old_handle", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_addresp_action, + { "Action", "gryphon.addresp.action", FT_UINT8, BASE_DEC, VALS(action_vals), 0x07, + NULL, HFILL }}, + { &hf_gryphon_addresp_action_period, + { "Period", "gryphon.addresp.action_period", FT_BOOLEAN, 8, TFS(&frames_01seconds), FR_PERIOD_MSGS, + NULL, HFILL }}, + { &hf_gryphon_addresp_action_deact_on_event, + { "Deact on event", "gryphon.addresp.action.deact_on_event", FT_UINT8, BASE_DEC, VALS(deact_on_event_vals), FR_DELETE|FR_DEACT_ON_EVENT, + NULL, HFILL }}, + { &hf_gryphon_addresp_action_deact_after_period, + { "Deact on Period", "gryphon.addresp.action.deact_after_period", FT_UINT8, BASE_DEC, VALS(deact_after_per_vals), FR_DELETE|FR_DEACT_AFTER_PER, + NULL, HFILL }}, + { &hf_gryphon_addresp_action_period_type, + { "Period", "gryphon.addresp.action_period_type", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_addresp_handle, + { "Response handle", "gryphon.addresp.handle", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_modresp_handle, + { "Response handle", "gryphon.modresp.handle", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_modresp_action, + { "Action response", "gryphon.modresp.action", FT_UINT8, BASE_DEC, VALS(filtacts), 0x0, + NULL, HFILL }}, + { &hf_gryphon_num_resphan, + { "Number of response handles", "gryphon.num_resphan", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_handle, + { "Handle", "gryphon.handle", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_transmit_sched_id, + { "Transmit schedule ID", "gryphon.transmit_sched_id", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_desc_program_size, + { "Program size", "gryphon.desc.program_size", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_desc_program_name, + { "Program name", "gryphon.desc.program_name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_desc_program_description, + { "Program description", "gryphon.desc.program_description", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_desc_flags, + { "Flags", "gryphon.desc.flags", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_desc_flags_program, + { "Period", "gryphon.desc.flags.program", FT_BOOLEAN, 8, TFS(&present_not_present), 0x01, + NULL, HFILL }}, + { &hf_gryphon_desc_handle, + { "Handle", "gryphon.desc.handle", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_upload_block_number, + { "Block number", "gryphon.upload.block_number", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_upload_handle, + { "Handle", "gryphon.upload.handle", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_upload_data, + { "Data", "gryphon.upload.data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_delete, + { "Program name", "gryphon.delete", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_list_block_number, + { "Block number", "gryphon.list.block_number", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_list_num_programs, + { "Number of programs in this response", "gryphon.list.num_programs", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_list_num_remain_programs, + { "Number of remaining programs", "gryphon.list.num_remain_programs", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_list_name, + { "Name", "gryphon.list.name", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_list_description, + { "Description", "gryphon.list.description", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_start_arguments, + { "Arguments", "gryphon.start.arguments", FT_STRINGZ, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_start_channel, + { "Channel (Client) number", "gryphon.start.channel", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_status_num_running_copies, + { "Number of running copies", "gryphon.status.num_running_copies", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_options_handle, + { "Handle", "gryphon.options.handle", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_files, + { "Directory", "gryphon.files", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_usdt_flags_register, + { "USDT", "gryphon.usdt.flags_register", FT_UINT8, BASE_DEC, VALS(register_unregister), 0x01, + NULL, HFILL }}, + { &hf_gryphon_usdt_action_flags, + { "Action Flags", "gryphon.usdt.action_flags", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + /* 20171012 added non legacy USDT */ + { &hf_gryphon_usdt_action_flags_non_legacy, + { "Action Flags", "gryphon.usdt.action_flags.non_legacy", FT_BOOLEAN, 8, TFS(®ister_unregister_action_flags), 0x01, + NULL, HFILL }}, + + { &hf_gryphon_usdt_action_flags_register, + { "Register", "gryphon.usdt.action_flags.register", FT_UINT8, BASE_DEC, VALS(register_unregister), 0x01, + NULL, HFILL }}, + { &hf_gryphon_usdt_action_flags_action, + { "Action", "gryphon.usdt.action_flags.action", FT_UINT8, BASE_DEC, VALS(usdt_action_vals), 0x06, + NULL, HFILL }}, + { &hf_gryphon_usdt_transmit_options_flags, + { "Transmit options", "gryphon.usdt.transmit_options_flags", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + /* 20171012 USDT tx options */ + /* bit 0*/ + { &hf_gryphon_usdt_transmit_options_flags_echo, + { "Echo long", "gryphon.usdt.transmit_options_flags.echo_long", FT_UINT8, BASE_DEC, VALS(xmit_opt_echo_long), 0x01, NULL, HFILL }}, + /* bits 1 & 2 */ + { &hf_gryphon_usdt_transmit_options_action, + { "Transmit Action", "gryphon.usdt.transmit_options_flags.action", FT_UINT8, BASE_DEC, VALS(xmit_opt_vals), 0x06, + NULL, HFILL }}, + /* bit 3 */ + { &hf_gryphon_usdt_transmit_options_done_event, + { "Done event", "gryphon.usdt.transmit_options_flags.done_event", FT_UINT8, BASE_DEC, VALS(xmit_opt_done), 0x08, NULL, HFILL }}, + /* bit 4 */ + { &hf_gryphon_usdt_transmit_options_echo_short, + { "Echo short", "gryphon.usdt.transmit_options_flags.echo_log", FT_UINT8, BASE_DEC, VALS(xmit_opt_echo_short), 0x10, NULL, HFILL }}, + /* bit 5 */ + { &hf_gryphon_usdt_transmit_options_rx_nth_fc, + { "Nth flowcontrol event", "gryphon.usdt.transmit_options_flags.nth_fc_event", FT_UINT8, BASE_DEC, VALS(xmit_opt_nth_fc_event), 0x20, NULL, HFILL }}, + + /* bit 5 */ + { &hf_gryphon_usdt_transmit_options_send_done, + { "Send a USDT_DONE event when the last frame of a multi-frame USDT message is transmitted", + "gryphon.usdt.transmit_options_flags.send_done", FT_BOOLEAN, 8, TFS(&yes_no), 0x08, NULL, HFILL }}, + + /* 20171012 USDT rx options */ + { &hf_gryphon_usdt_receive_options_flags, + { "Receive options", "gryphon.usdt.receive_options_flags", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + /* bits 0 & 1 */ + { &hf_gryphon_usdt_receive_options_action, /* legacy */ + { "Receive Action", "gryphon.usdt.receive_options_flags.action", FT_UINT8, BASE_DEC, VALS(recv_opt_vals), 0x03, NULL, HFILL }}, + /* bit 2 */ + { &hf_gryphon_usdt_receive_options_firstframe_event, + { "First frame event", "gryphon.usdt.receive_options_flags.firstframe_event", FT_UINT8, BASE_DEC, VALS(recv_opt_firstframe_event), 0x04, NULL, HFILL }}, + /* bit 3 */ + { &hf_gryphon_usdt_receive_options_lastframe_event, + { "Last frame event", "gryphon.usdt.receive_options_flags.lastframe_event", FT_UINT8, BASE_DEC, VALS(recv_opt_lastframe_event), 0x08, NULL, HFILL }}, + /* bit 5 */ + { &hf_gryphon_usdt_receive_options_tx_nth_fc, + { "Nth flowcontrol event", "gryphon.usdt.receive_options_flags.nth_fc_event", FT_UINT8, BASE_DEC, VALS(recv_opt_nth_fc_event), 0x20, NULL, HFILL }}, + + /* J1939 options */ + { &hf_gryphon_usdt_length_options_flags, + { "Length options", "gryphon.usdt.length_options_flags", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + /* bit 6 */ + { &hf_gryphon_usdt_length_control_j1939, + { "Length control bit", "gryphon.usdt.length_options_flags.j1939", FT_UINT8, BASE_DEC, VALS(recv_opt_j1939), 0x40, NULL, HFILL }}, + + /* 20171013 */ + { &hf_gryphon_usdt_stmin_fc, + { "STMIN flow control time (milliseconds)", "gryphon.usdt.set_stmin_fc", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_gryphon_usdt_set_stmin_mul, + { "STMIN multiplier", "gryphon.usdt.set_stmin_mul", FT_FLOAT, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_usdt_bsmax_fc, + { "Block size max for flow control", "gryphon.usdt.set_bsmax_fc", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_gryphon_usdt_stmin_override, + { "STMIN override time (milliseconds)", "gryphon.usdt.set_stmin_override", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + { &hf_gryphon_usdt_stmin_override_active, + { "STMIN override active", "gryphon.usdt.stmin_active", FT_BOOLEAN, 8, TFS(&active_inactive), FILTER_ACTIVE_FLAG, + NULL, HFILL }}, + { &hf_gryphon_usdt_stmin_override_activate, + { "STMIN override activate", "gryphon.usdt.stmin_active", FT_BOOLEAN, 8, TFS(&active_inactive), FILTER_ACTIVE_FLAG, + NULL, HFILL }}, + + { &hf_gryphon_usdt_receive_options_firstframe, + { "Send a USDT_FIRSTFRAME event when the first frame of a multi-frame USDT message is received", + "gryphon.usdt.receive_options_flags.firstframe", FT_BOOLEAN, 8, TFS(&yes_no), 0x04, NULL, HFILL }}, + { &hf_gryphon_usdt_receive_options_lastframe, + { "Send a USDT_LASTFRAME event when the first frame of a multi-frame USDT message is received", + "gryphon.usdt.receive_options_flags.lastframe", FT_BOOLEAN, 8, TFS(&yes_no), 0x08, NULL, HFILL }}, + { &hf_gryphon_usdt_ext_address, + { "Using extended addressing for", "gryphon.usdt.ext_address", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_usdt_ext_address_id, + { "ID", "gryphon.usdt.ext_address.id", FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_usdt_block_size, + { "Number of IDs in the block", "gryphon.usdt.block_size", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_bits_in_input1, + { "Input 1", "gryphon.bits_in.input1", FT_BOOLEAN, 8, TFS(&set_not_set), 0x01, + NULL, HFILL }}, + { &hf_gryphon_bits_in_input2, + { "Input 2", "gryphon.bits_in.input2", FT_BOOLEAN, 8, TFS(&set_not_set), 0x02, + NULL, HFILL }}, + { &hf_gryphon_bits_in_input3, + { "Input 3", "gryphon.bits_in.input3", FT_BOOLEAN, 8, TFS(&set_not_set), 0x04, + NULL, HFILL }}, + { &hf_gryphon_bits_in_pushbutton, + { "Pushbutton", "gryphon.bits_in.pushbutton", FT_BOOLEAN, 8, TFS(&set_not_set), 0x08, + NULL, HFILL }}, + { &hf_gryphon_bits_out_output1, + { "Input 1", "gryphon.bits_out.output1", FT_BOOLEAN, 8, TFS(&set_not_set), 0x01, + NULL, HFILL }}, + { &hf_gryphon_bits_out_output2, + { "Input 2", "gryphon.bits_out.output2", FT_BOOLEAN, 8, TFS(&set_not_set), 0x02, + NULL, HFILL }}, + { &hf_gryphon_init_strat_reset_limit, + { "Reset Limit", "gryphon.init_strat.reset_limit", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_init_strat_delay, + { "Delay", "gryphon.init_strat.strat_delay", FT_FLOAT, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_speed_baud_rate_index, + { "Baud rate index", "gryphon.speed.baud_rate_index", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_filter_start, + { "Filter field starts at byte", "gryphon.filter_block.filter_start", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_filter_length, + { "Filter field length", "gryphon.filter_block.filter_length", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_filter_type, + { "Filtering on", "gryphon.filter_block.filter_type", FT_UINT8, BASE_DEC, VALS(filter_data_types), 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_filter_operator, + { "Type of comparison", "gryphon.filter_block.filter_operator", FT_UINT8, BASE_DEC, VALS(operators), 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_filter_value1, + { "Value", "gryphon.filter_block.filter_value", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_filter_value2, + { "Value", "gryphon.filter_block.filter_value", FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_filter_value4, + { "Value", "gryphon.filter_block.filter_value", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_filter_value_bytes, + { "Value", "gryphon.filter_block.filter_value_bytes", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_mode, + { "Mode", "gryphon.blm_mode", FT_UINT32, BASE_DEC, VALS(blm_mode_vals), 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_mode_avg_period, + { "Averaging period", "gryphon.blm_mode.avg_period", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_blm_mode_avg_frames, + { "Averaging period (frames)", "gryphon.blm_mode.avg_frames", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_command, + { "Command", "gryphon.command", FT_UINT32, BASE_HEX|BASE_EXT_STRING, &cmd_vals_ext, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cmd_mode, + { "Mode", "gryphon.command.mode", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_option, + { "Option", "gryphon.option", FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_option_data, + { "Option data", "gryphon.option_data", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_cmd_file, + { "File", "gryphon.command.file", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_bit_in_digital_data, + { "Digital values set", "gryphon.bit_in_digital_data", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_bit_out_digital_data, + { "Digital values set", "gryphon.bit_out_digital_data", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_pattern, + { "Pattern", "gryphon.filter_block.pattern", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_filter_block_mask, + { "Mask", "gryphon.filter_block.mask", FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + /* 20171012 USDT */ + { &hf_gryphon_usdt_nids, + { "Number of IDs in block", "gryphon.nids", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, + + { &hf_gryphon_usdt_request, + { "USDT request IDs", "gryphon.usdt_request", FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_usdt_request_ext, + { "USDT request extended address", "gryphon.usdt_request_ext", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_usdt_response, + { "USDT response IDs", "gryphon.usdt_response", FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_usdt_response_ext, + { "USDT response extended address", "gryphon.usdt_response_ext", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_uudt_response, + { "UUDT response IDs", "gryphon.uudt_response", FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_uudt_response_ext, + { "UUDT response extended address", "gryphon.usdt_response_ext", FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_more_filenames, + { "More filenames to return", "gryphon.more_filenames", FT_BOOLEAN, 8, TFS(&yes_no), 0x0, + NULL, HFILL }}, + { &hf_gryphon_filenames, + { "File and directory names", "gryphon.filenames", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_program_channel_number, + { "Program channel number", "gryphon.program_channel_number", FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_gryphon_valid_header_length, + { "Valid Header length", "gryphon.valid_header_length", FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + }; + + static gint *ett[] = { + &ett_gryphon, + &ett_gryphon_header, + &ett_gryphon_body, + &ett_gryphon_command_data, + &ett_gryphon_response_data, + &ett_gryphon_data_header, + &ett_gryphon_flags, + &ett_gryphon_data_body, + &ett_gryphon_cmd_filter_block, + &ett_gryphon_cmd_events_data, + &ett_gryphon_cmd_config_device, + &ett_gryphon_cmd_sched_data, + &ett_gryphon_cmd_sched_cmd, + &ett_gryphon_cmd_response_block, + &ett_gryphon_pgm_list, + &ett_gryphon_pgm_status, + &ett_gryphon_pgm_options, + &ett_gryphon_valid_headers, + &ett_gryphon_usdt_data, + &ett_gryphon_usdt_action_flags, + &ett_gryphon_usdt_tx_options_flags, + &ett_gryphon_usdt_rx_options_flags, + &ett_gryphon_usdt_len_options_flags, + &ett_gryphon_usdt_data_block, + &ett_gryphon_lin_emulate_node, + &ett_gryphon_ldf_block, + &ett_gryphon_ldf_schedule_name, + &ett_gryphon_lin_schedule_msg, + &ett_gryphon_cnvt_getflags, + &ett_gryphon_digital_data, + &ett_gryphon_blm_mode + }; + + static ei_register_info ei[] = { + { &ei_gryphon_type,{ "gryphon.type.invalid", PI_PROTOCOL, PI_WARN, "Invalid frame type", EXPFILL } }, + }; + + module_t *gryphon_module; + expert_module_t* expert_gryphon; + + proto_gryphon = proto_register_protocol("DG Gryphon Protocol", "Gryphon", "gryphon"); + proto_register_field_array(proto_gryphon, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_gryphon = expert_register_protocol(proto_gryphon); + expert_register_field_array(expert_gryphon, ei, array_length(ei)); + gryphon_handle = register_dissector("gryphon", dissect_gryphon, proto_gryphon); + + gryphon_module = prefs_register_protocol(proto_gryphon, NULL); + prefs_register_bool_preference(gryphon_module, "desegment", + "Desegment all Gryphon messages spanning multiple TCP segments", + "Whether the Gryphon dissector should desegment all messages spanning multiple TCP segments", + &gryphon_desegment); + +} + +void +proto_reg_handoff_gryphon(void) +{ + dissector_add_uint_with_preference("tcp.port", GRYPHON_TCP_PORT, gryphon_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/gryphon/packet-gryphon.h b/plugins/epan/gryphon/packet-gryphon.h new file mode 100644 index 00000000..477f897c --- /dev/null +++ b/plugins/epan/gryphon/packet-gryphon.h @@ -0,0 +1,592 @@ +/* packet-gryphon.h + * + * Updated routines for Gryphon protocol packet dissection + * By Mark C. + * Copyright (C) 2018 DG Technologies, Inc. (Dearborn Group, Inc.) USA + * + * Definitions for Gryphon packet disassembly structures and routines + * By Steve Limkemann + * Copyright 1998 Steve Limkemann + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#define MSG_HDR_SZ 8 +#define CMD_HDR_SZ 4 + +/* source/destinations: */ + +#define SD_CARD 0x01 /* (vehicle) network interface */ +#define SD_SERVER 0x02 +#define SD_CLIENT 0x03 +#define SD_KNOWN 0x10 /* Client ID >= are well known */ +#define SD_SCHED 0x10 /* scheduler */ +#define SD_SCRIPT 0x20 /* script processor */ +#define SD_PGM 0x21 /* Program loader */ +#define SD_USDT 0x22 /* USDT (Unacknowledged Segmented Data Transfer) */ +#define SD_BLM 0x23 /* Bus Load Monitoring */ +#define SD_LIN 0x24 /* LIN extensions */ +#define SD_FLIGHT 0x25 /* Flight Recorder */ +#define SD_LOGGER 0x25 /* data logger */ +#define SD_RESP 0x26 /* Message Response */ +#define SD_IOPWR 0x27 /* VNG / Compact Gryphon I/O & power */ +#define SD_UTIL 0x28 /* Miscellaneous utility commands */ +#define SD_CNVT 0x29 /* signal conversion commands */ +#define CH_BROADCAST 0xFF /* broadcast message destination channel */ + + + +/* frame types: */ +#define GY_FT_CMD 0x01 /* command to initiate some action */ +#define GY_FT_RESP 0x02 /* response to a command */ +#define GY_FT_DATA 0x03 /* (vehicle) network data */ +#define GY_FT_EVENT 0x04 /* notification of an event */ +#define GY_FT_MISC 0x05 /* misc data */ +#define GY_FT_TEXT 0x06 /* null-terminated ASCII strings */ +#define GY_FT_SIG 0x07 /* (vehicle) network signals */ + + + +/* generic (all SD type) commands: values 0x00 to 0x3f */ + +#define CMD_INIT 0x01 /* initialize target */ +#define CMD_GET_STAT 0x02 /* request status */ +#define CMD_GET_CONFIG 0x03 /* request configuration info */ +#define CMD_EVENT_ENABLE 0x04 /* Enable event type */ +#define CMD_EVENT_DISABLE 0x05 /* Disable event type */ +#define CMD_GET_TIME 0x06 /* Get current value of timestamp */ +#define CMD_GET_RXDROP 0x07 /* Get count of Rx msgs dropped */ +#define CMD_RESET_RXDROP 0x08 /* Set count of Rx msgs dropped to zero */ +#define CMD_BCAST_ON 0x09 /* broadcasts on */ +#define CMD_BCAST_OFF 0x0a /* broadcasts off */ +#define CMD_SET_TIME 0x0b /* set time */ + +/* SD-type specific commands: should start at 0x40, global uniqueness */ +/* is prefered, but not mandatory. */ + +/* SD_CARD command types: */ + +#define CMD_CARD_SET_SPEED (SD_CARD * 256 + 0x40) /* set peripheral speed */ +#define CMD_CARD_GET_SPEED (SD_CARD * 256 + 0x41) /* get peripheral speed */ +#define CMD_CARD_SET_FILTER (SD_CARD * 256 + 0x42) /* set filter to pass or block all */ +#define CMD_CARD_GET_FILTER (SD_CARD * 256 + 0x43) /* get a pass/block filter */ +#define CMD_CARD_TX (SD_CARD * 256 + 0x44) /* transmit message */ +#define CMD_CARD_TX_LOOP_ON (SD_CARD * 256 + 0x45) /* set transmit loopback on */ +#define CMD_CARD_TX_LOOP_OFF (SD_CARD * 256 + 0x46) /* set transmit loopback off */ +#define CMD_CARD_IOCTL (SD_CARD * 256 + 0x47) /* device driver ioctl pass-through */ +#define CMD_CARD_ADD_FILTER (SD_CARD * 256 + 0x48) /* add a pass/block filter */ +#define CMD_CARD_MODIFY_FILTER (SD_CARD * 256 + 0x49) /* modify a pass/block filter */ +#define CMD_CARD_GET_FILTER_HANDLES (SD_CARD * 256 + 0x4A)/* get a list of filters */ +#define CMD_CARD_SET_DEFAULT_FILTER (SD_CARD * 256 + 0x4B)/* set the default action */ +#define CMD_CARD_GET_DEFAULT_FILTER (SD_CARD * 256 + 0x4C)/* get the defautl action */ +#define CMD_CARD_SET_FILTER_MODE (SD_CARD * 256 + 0x4D) /* set the client data mode */ +#define CMD_CARD_GET_FILTER_MODE (SD_CARD * 256 + 0x4E) /* get the client data mode */ +#define CMD_CARD_GET_EVNAMES (SD_CARD * 256 + 0x4f) /* get event names */ +#define CMD_CARD_GET_SPEEDS (SD_CARD * 256 + 0x50) /* get speed definitions */ + +/* SD_SERVER command types: */ + +#define CMD_SERVER_REG (SD_SERVER * 256 + 0x50) /* register connection */ +#define CMD_SERVER_SET_SORT (SD_SERVER * 256 + 0x51) /* set sorting behavior */ +#define CMD_SERVER_SET_OPT (SD_SERVER * 256 + 0x52) /* set type of optimization */ + +/* SD_CLIENT command types: */ + +#define CMD_CLIENT_GET_ID (SD_CLIENT * 256 + 0x60) /* get the ID (channel field) of this client? */ +#define CMD_CLIENT_SET_ID (SD_CLIENT * 256 + 0x61) /* set the ID (channel field) of this client? */ +#define CMD_CLIENT_SHUTDOWN (SD_CLIENT * 256 + 0x62) /* tell client to die ? */ + +/* Bus load monitor (SD_BLM) commands: */ + +#define CMD_BLM_SET_MODE (SD_BLM * 256 + 0xA0) +#define CMD_BLM_GET_MODE (SD_BLM * 256 + 0xA1) +#define CMD_BLM_GET_DATA (SD_BLM * 256 + 0xA2) +#define CMD_BLM_GET_STATS (SD_BLM * 256 + 0xA3) + +/* SD_LIN command types: */ +#define CMD_LDF_DESC (SD_LIN * 256 + 0xB8) /* */ +#define CMD_LDF_UPLOAD (SD_LIN * 256 + 0xB9) /* */ +#define CMD_LDF_LIST (SD_LIN * 256 + 0xBA) /* */ +#define CMD_LDF_DELETE (SD_LIN * 256 + 0xBB) /* */ +#define CMD_LDF_PARSE (SD_LIN * 256 + 0xBC) /* */ +#define CMD_GET_LDF_INFO (SD_LIN * 256 + 0xBD) /* */ +#define CMD_GET_NODE_NAMES (SD_LIN * 256 + 0xBE) /* */ +#define CMD_EMULATE_NODES (SD_LIN * 256 + 0xBF) /* */ +#define CMD_GET_FRAMES (SD_LIN * 256 + 0xB0) /* */ +#define CMD_GET_FRAME_INFO (SD_LIN * 256 + 0xC1) /* */ +#define CMD_GET_SIGNAL_INFO (SD_LIN * 256 + 0xC2) /* */ +#define CMD_GET_SIGNAL_DETAIL (SD_LIN * 256 + 0xC3) /* */ +#define CMD_GET_ENCODING_INFO (SD_LIN * 256 + 0xC4) /* */ +#define CMD_GET_SCHEDULES (SD_LIN * 256 + 0xC5) /* */ +#define CMD_START_SCHEDULE (SD_LIN * 256 + 0xC6) /* */ +#define CMD_STOP_SCHEDULE (SD_LIN * 256 + 0xC7) /* */ +#define CMD_STORE_DATA (SD_LIN * 256 + 0xC8) /* */ +#define CMD_SEND_ID (SD_LIN * 256 + 0xC9) /* */ +#define CMD_SEND_ID_DATA (SD_LIN * 256 + 0xCA) /* */ +#define CMD_SAVE_SESSION (SD_LIN * 256 + 0xCB) /* */ +#define CMD_RESTORE_SESSION (SD_LIN * 256 + 0xCC) /* */ +#define CMD_GET_NODE_SIGNALS (SD_LIN * 256 + 0xCD) /* */ + +/* signal conversion (SD_CNVT) commands */ + +#define CMD_CNVT_GET_VALUES (SD_CNVT * 256 + 0x78) /* LIN Signal Conversion */ +#define CMD_CNVT_GET_UNITS (SD_CNVT * 256 + 0x79) /* LIN Signal Conversion */ +#define CMD_CNVT_SET_VALUES (SD_CNVT * 256 + 0x7A) /* LIN Signal Conversion */ +#define CMD_CNVT_DESTROY_SESSION (SD_CNVT * 256 + 0x7B) /* LIN Signal Conversion */ +#define CMD_CNVT_SAVE_SESSION (SD_CNVT * 256 + 0xCB) /* LIN Signal Conversion */ +#define CMD_CNVT_RESTORE_SESSION (SD_CNVT * 256 + 0xCC) /* LIN Signal Conversion */ +#define CMD_CNVT_GET_NODE_SIGNALS (SD_CNVT * 256 + 0xCD) /* LIN Signal Conversion */ + +/* Flight recorder (SD_FLIGHT) commands */ + +#define CMD_FLIGHT_GET_CONFIG (SD_FLIGHT * 256 + 0x50) /* get flight recorder channel info */ +#define CMD_FLIGHT_START_MON (SD_FLIGHT * 256 + 0x51) /* start flight recorder monitoring */ +#define CMD_FLIGHT_STOP_MON (SD_FLIGHT * 256 + 0x52) /* stop flight recorder monitoring */ + +/* Message responder (SD_RESP) commands: */ +#define CMD_MSGRESP_ADD (SD_RESP * 256 + 0xB0) +#define CMD_MSGRESP_GET (SD_RESP * 256 + 0xB1) +#define CMD_MSGRESP_MODIFY (SD_RESP * 256 + 0xB2) +#define CMD_MSGRESP_GET_HANDLES (SD_RESP * 256 + 0xB3) + +/* Program loader (SD_PGM) commands: */ + +#define CMD_PGM_DESC (SD_PGM * 256 + 0x90) /* Describe a program to be uploaded */ +#define CMD_PGM_UPLOAD (SD_PGM * 256 + 0x91) /* Upload a program to the Gryphon */ +#define CMD_PGM_DELETE (SD_PGM * 256 + 0x92) /* Delete an uploaded program */ +#define CMD_PGM_LIST (SD_PGM * 256 + 0x93) /* Get a list of uploaded programs */ +#define CMD_PGM_START (SD_PGM * 256 + 0x94) /* Start an uploaded program */ +#define CMD_PGM_START2 (SD_CLIENT * 256 + 0x94) /* Start an uploaded program */ +#define CMD_PGM_STOP (SD_PGM * 256 + 0x95) /* Stop an uploaded program */ +#define CMD_PGM_STATUS (SD_PGM * 256 + 0x96) /* Get the status of an uploaded program */ +#define CMD_PGM_OPTIONS (SD_PGM * 256 + 0x97) /* Set the upload options */ +#define CMD_PGM_FILES (SD_PGM * 256 + 0x98) /* Get a list of files & directories */ + +/* Scheduler (SD_SCHED) target commands: */ + +#define CMD_SCHED_TX (SD_SCHED * 256 + 0x70) /* schedule transmission list */ +#define CMD_SCHED_KILL_TX (SD_SCHED * 256 + 0x71) /* stop and destroy job */ +#define CMD_SCHED_MSG_REPLACE (SD_SCHED * 256 + 0x72) /* replace a scheduled message */ + +/* USDT (SD_USDT) target commands: */ + +#define CMD_USDT_IOCTL (SD_USDT * 256 + 0x47) /* Register/Unregister with USDT */ +#define CMD_USDT_REGISTER (SD_USDT * 256 + 0xB0) /* Register/Unregister with USDT */ +#define CMD_USDT_SET_FUNCTIONAL (SD_USDT * 256 + 0xB1) /* Set to use extended addressing*/ +#define CMD_USDT_SET_STMIN_MULT (SD_USDT * 256 + 0xB2) /* */ +#define CMD_USDT_SET_STMIN_FC (SD_USDT * 256 + 0xB3) /* */ +#define CMD_USDT_GET_STMIN_FC (SD_USDT * 256 + 0xB4) /* */ +#define CMD_USDT_SET_BSMAX_FC (SD_USDT * 256 + 0xB5) /* */ +#define CMD_USDT_GET_BSMAX_FC (SD_USDT * 256 + 0xB6) /* */ +#define CMD_USDT_REGISTER_NON_LEGACY (SD_USDT * 256 + 0xB7) /* Register/Unregister with USDT */ +#define CMD_USDT_SET_STMIN_OVERRIDE (SD_USDT * 256 + 0xB8) /* */ +#define CMD_USDT_GET_STMIN_OVERRIDE (SD_USDT * 256 + 0xB9) /* */ +#define CMD_USDT_ACTIVATE_STMIN_OVERRIDE (SD_USDT * 256 + 0xBA) /* */ + +/* I/O Power (SD_IOPWR) target commands: */ + +#define CMD_IOPWR_GETINP (SD_IOPWR * 256 + 0x40) /* Read current digital inputs */ +#define CMD_IOPWR_GETLATCH (SD_IOPWR * 256 + 0x41) /* Read latched digital inputs */ +#define CMD_IOPWR_CLRLATCH (SD_IOPWR * 256 + 0x42) /* Read & clear latched inputs */ +#define CMD_IOPWR_GETOUT (SD_IOPWR * 256 + 0x43) /* Read digital outputs */ +#define CMD_IOPWR_SETOUT (SD_IOPWR * 256 + 0x44) /* Write digital outputs */ +#define CMD_IOPWR_SETBIT (SD_IOPWR * 256 + 0x45) /* Set indicated output bit(s) */ +#define CMD_IOPWR_CLRBIT (SD_IOPWR * 256 + 0x46) /* Clear indicated output bit(s)*/ +#define CMD_IOPWR_GETPOWER (SD_IOPWR * 256 + 0x47) /* Read inputs at power on time */ + +/* Miscellaneous (SD_UTIL) target commands: */ + +#define CMD_UTIL_SET_INIT_STRATEGY (SD_UTIL * 256 + 0x90) /* set the initialization strategy */ +#define CMD_UTIL_GET_INIT_STRATEGY (SD_UTIL * 256 + 0x91) /* get the initialization strategy */ + +/* response frame (FT_RESP) response field definitions: */ + +#define RESP_OK 0x00 /* no error */ +#define RESP_UNKNOWN_ERR 0x01 /* unknown error */ +#define RESP_UNKNOWN_CMD 0x02 /* unrecognised command */ +#define RESP_UNSUPPORTED 0x03 /* unsupported command */ +#define RESP_INVAL_CHAN 0x04 /* invalid channel specified */ +#define RESP_INVAL_DST 0x05 /* invalid destination */ +#define RESP_INVAL_PARAM 0x06 /* invalid parameters */ +#define RESP_INVAL_MSG 0x07 /* invalid message */ +#define RESP_INVAL_LEN 0x08 /* invalid length field */ +#define RESP_TX_FAIL 0x09 /* transmit failed */ +#define RESP_RX_FAIL 0x0a /* receive failed */ +#define RESP_AUTH_FAIL 0x0b +#define RESP_MEM_ALLOC_ERR 0x0c /* memory allocation error */ +#define RESP_TIMEOUT 0x0d /* command timed out */ +#define RESP_UNAVAILABLE 0x0e +#define RESP_BUF_FULL 0x0f /* buffer full */ +#define RESP_NO_SUCH_JOB 0x10 + +/* Flight recorder (SD_FLIGHT) target definitions */ + +#define FR_RESP_AFTER_EVENT 0 +#define FR_RESP_AFTER_PERIOD 1 +#define FR_IGNORE_DURING_PER 2 +#define FR_DEACT_AFTER_PER 0x80 +#define FR_DEACT_ON_EVENT 0x40 +#define FR_DELETE 0x20 +#define FR_PERIOD_MSGS 0x10 + +/* Filter data types */ + +#define FILTER_DATA_TYPE_HEADER_FRAME 0x00 +#define FILTER_DATA_TYPE_HEADER 0x01 +#define FILTER_DATA_TYPE_DATA 0x02 +#define FILTER_DATA_TYPE_EXTRA_DATA 0x03 +#define FILTER_EVENT_TYPE_HEADER 0x04 +#define FILTER_EVENT_TYPE_DATA 0x05 + +/* filter flags */ + +#define FILTER_PASS_FLAG 0x01 +#define FILTER_ACTIVE_FLAG 0x02 + +/* Filter and Frame Responder Condition operators */ + +#define BIT_FIELD_CHECK 0 +#define SVALUE_GT 1 +#define SVALUE_GE 2 +#define SVALUE_LT 3 +#define SVALUE_LE 4 +#define VALUE_EQ 5 +#define VALUE_NE 6 +#define UVALUE_GT 7 +#define UVALUE_GE 8 +#define UVALUE_LT 9 +#define UVALUE_LE 10 +#define DIG_LOW_TO_HIGH 11 +#define DIG_HIGH_TO_LOW 12 +#define DIG_TRANSITION 13 + +/* Modes available via CMD_CARD_SET_FILTERING_MODE */ +#define FILTER_OFF_PASS_ALL 3 +#define FILTER_OFF_BLOCK_ALL 4 +#define FILTER_ON 5 + +/* Modes available via CMD_CARD_SET_DEFAULT_FILTER */ +#define DEFAULT_FILTER_BLOCK 0 +#define DEFAULT_FILTER_PASS 1 + +/* Actions available via CMD_CARD_MODIFY_FILTER */ +#define DELETE_FILTER 0 +#define ACTIVATE_FILTER 1 +#define DEACTIVATE_FILTER 2 + +/* Flags to modify how FT_CMD (command) messages are handled */ +/* These values are ORed with FT_CMD and stored in the Frame Header's */ +/* Frame Type field for each response. */ +#define DONT_WAIT_FOR_RESP 0x80 +#define WAIT_FOR_PREV_RESP 0x40 +#define RESPONSE_FLAGS (DONT_WAIT_FOR_RESP | WAIT_FOR_PREV_RESP) + + +/* Program loader options */ +#define PGM_CONV 1 /* Type of data conversion to perform */ +#define PGM_TYPE 2 /* Type of file */ +#define PGM_BIN 11 /* Binary, no conversion */ +#define PGM_ASCII 12 /* ASCII, convert CR LF to LF */ +#define PGM_PGM 21 /* Executable */ +#define PGM_DATA 22 /* Data */ + + + + +/* IOCTL definitions - comments indicate data size */ + +#define GINIT 0x11100001 +#define GLOOPON 0x11100002 +#define GLOOPOFF 0x11100003 +#define GGETHWTYPE 0x11100004 +#define GGETREG 0x11100005 +#define GSETREG 0x11100006 +#define GGETRXCOUNT 0x11100007 +#define GSETRXCOUNT 0x11100008 +#define GGETTXCOUNT 0x11100009 +#define GSETTXCOUNT 0x1110000a +#define GGETRXDROP 0x1110000b +#define GSETRXDROP 0x1110000c +#define GGETTXDROP 0x1110000d +#define GSETTXDROP 0x1110000e +#define GGETRXBAD 0x1110000f +#define GGETTXBAD 0x11100011 +#define GGETCOUNTS 0x11100013 +#define GGETBLMON 0x11100014 +#define GSETBLMON 0x11100015 +#define GGETERRLEV 0x11100016 +#define GSETERRLEV 0x11100017 +#define GGETBITRATE 0x11100018 +#define GGETRAM 0x11100019 +#define GSETRAM 0x1110001a + +#define GCANGETBTRS 0x11200001 +#define GCANSETBTRS 0x11200002 +#define GCANGETBC 0x11200003 +#define GCANSETBC 0x11200004 +#define GCANGETMODE 0x11200005 +#define GCANSETMODE 0x11200006 +#define GCANGETTRANS 0x11200009 +#define GCANSETTRANS 0x1120000a +#define GCANSENDERR 0x1120000b +#define GCANRGETOBJ 0x11210001 +#define GCANRSETSTDID 0x11210002 +#define GCANRSETEXTID 0x11210003 +#define GCANRSETDATA 0x11210004 +#define GCANRENABLE 0x11210005 +#define GCANRDISABLE 0x11210006 +#define GCANRGETMASKS 0x11210007 +#define GCANRSETMASKS 0x11210008 +#define GCANSWGETMODE 0x11220001 +#define GCANSWSETMODE 0x11220002 + +#define GDLCGETFOURX 0x11400001 +#define GDLCSETFOURX 0x11400002 +#define GDLCGETLOAD 0x11400003 +#define GDLCSETLOAD 0x11400004 +#define GDLCSENDBREAK 0x11400005 +#define GDLCABORTTX 0x11400006 +#define GDLCGETHDRMODE 0x11400007 +#define GDLCSETHDRMODE 0x11400008 + +#define GHONSLEEP 0x11600001 +#define GHONSILENCE 0x11600002 + +#define GKWPSETPTIMES 0x11700011 +#define GKWPSETWTIMES 0x11700010 +#define GKWPDOWAKEUP 0x11700008 +#define GKWPGETBITTIME 0x11700101 +#define GKWPSETBITTIME 0x11700102 +#define GKWPSETNODEADDR 0x11700104 +#define GKWPGETNODETYPE 0x11700105 +#define GKWPSETNODETYPE 0x11700106 +#define GKWPSETWAKETYPE 0x11700108 +#define GKWPSETTARGADDR 0x1170010a +#define GKWPSETKEYBYTES 0x1170010c +#define GKWPSETSTARTREQ 0x1170010e +#define GKWPSETSTARTRESP 0x11700110 +#define GKWPSETPROTOCOL 0x11700112 +#define GKWPGETLASTKEYBYTES 0x11700201 +#define GKWPSETLASTKEYBYTES 0x11700202 + +#define GSCPGETBBR 0x11300001 +#define GSCPSETBBR 0x11300002 +#define GSCPGETID 0x11300003 +#define GSCPSETID 0x11300004 +#define GSCPADDFUNCID 0x11300005 +#define GSCPCLRFUNCID 0x11300006 + +#define GUBPGETBITRATE 0x11800001 +#define GUBPSETBITRATE 0x11800002 +#define GUBPGETINTERBYTE 0x11800003 +#define GUBPSETINTERBYTE 0x11800004 +#define GUBPGETNACKMODE 0x11800005 +#define GUBPSETNACKMODE 0x11800006 +#define GUBPGETRETRYDELAY 0x11800007 +#define GUBPSETRETRYDELAY 0x11800008 + +#define GRESETHC08 0x11800009 +#define GTESTHC08COP 0x1180000A + +#define GSJAGETLISTEN 0x11250001 +#define GSJASETLISTEN 0x11250002 +#define GSJAGETSELFTEST 0x11250003 +#define GSJASETSELFTEST 0x11250004 +#define GSJAGETXMITONCE 0x11250005 +#define GSJASETXMITONCE 0x11250006 +#define GSJAGETTRIGSTATE 0x11250007 +#define GSJASETTRIGCTRL 0x11250008 +#define GSJAGETTRIGCTRL 0x11250009 +#define GSJAGETOUTSTATE 0x1125000A +#define GSJASETOUTSTATE 0x1125000B +#define GSJAGETFILTER 0x1125000C +#define GSJASETFILTER 0x1125000D +#define GSJAGETMASK 0x1125000E +#define GSJASETMASK 0x1125000F +#define GSJAGETINTTERM 0x11250010 +#define GSJASETINTTERM 0x11250011 +#define GSJAGETFTTRANS 0x11250012 +#define GSJASETFTTRANS 0x11250013 +#define GSJAGETFTERROR 0x11250014 + +/* LIN driver IOCTLs */ +#define GLINGETBITRATE 0x11C00001 +#define GLINSETBITRATE 0x11C00002 +#define GLINGETBRKSPACE 0x11C00003 +#define GLINSETBRKSPACE 0x11C00004 +#define GLINGETBRKMARK 0x11C00005 +#define GLINSETBRKMARK 0x11C00006 +#define GLINGETIDDELAY 0x11C00007 +#define GLINSETIDDELAY 0x11C00008 +#define GLINGETRESPDELAY 0x11C00009 +#define GLINSETRESPDELAY 0x11C0000A +#define GLINGETINTERBYTE 0x11C0000B +#define GLINSETINTERBYTE 0x11C0000C +#define GLINGETWAKEUPDELAY 0x11C0000D +#define GLINSETWAKEUPDELAY 0x11C0000E +#define GLINGETWAKEUPTIMEOUT 0x11C0000F +#define GLINSETWAKEUPTIMEOUT 0x11C00010 +#define GLINGETWUTIMOUT3BR 0x11C00011 +#define GLINSETWUTIMOUT3BR 0x11C00012 +#define GLINSENDWAKEUP 0x11C00013 +#define GLINGETMODE 0x11C00014 +#define GLINSETMODE 0x11C00015 +#define GLINGETSLEW 0x11C00016 +#define GLINSETSLEW 0x11C00017 +#define GLINADDSCHED 0x11C00018 +#define GLINGETSCHED 0x11C00019 +#define GLINGETSCHEDSIZE 0x11C0001A +#define GLINDELSCHED 0x11C0001B +#define GLINACTSCHED 0x11C0001C +#define GLINDEACTSCHED 0x11C0001D +#define GLINGETACTSCHED 0x11C0001E +#define GLINGETNUMSCHEDS 0x11C0001F +#define GLINGETSCHEDNAMES 0x11C00020 +#define GLINSETFLAGS 0x11C00021 +#define GLINGETAUTOCHECKSUM 0x11C00022 +#define GLINSETAUTOCHECKSUM 0x11C00023 +#define GLINGETAUTOPARITY 0x11C00024 +#define GLINSETAUTOPARITY 0x11C00025 +#define GLINGETSLAVETABLEENABLE 0x11C00026 +#define GLINSETSLAVETABLEENABLE 0x11C00027 +#define GLINGETFLAGS 0x11C00028 +#define GLINGETWAKEUPMODE 0x11C00029 +#define GLINSETWAKEUPMODE 0x11C0002A +#define GLINGETMASTEREVENTENABLE 0x11C0002B /* 1 */ +#define GLINSETMASTEREVENTENABLE 0x11C0002C /* 1 */ +#define GLINGETNSLAVETABLE 0x11C0002D /* 1 get number of slave table entries */ +#define GLINGETSLAVETABLEPIDS 0x11C0002E /* 1 + n get list of slave table PIDs */ +#define GLINGETSLAVETABLE 0x11C0002F /* var., 4 + n */ +#define GLINSETSLAVETABLE 0x11C00030 /* var., 4 + n */ +#define GLINCLEARSLAVETABLE 0x11C00031 /* 1 */ +#define GLINCLEARALLSLAVETABLE 0x11C00032 /* 0 */ +#define GLINGETONESHOT 0x11C00033 /* var., 4 + n */ +#define GLINSETONESHOT 0x11C00034 /* var., 4 + n */ +#define GLINCLEARONESHOT 0x11C00035 /* 0 */ + +/* delay driver (real-time scheduler) IOCTLs */ +#define GDLYGETHIVALUE 0x11D50001 /* 4 */ +#define GDLYSETHIVALUE 0x11D50002 /* 4 set the high water value */ + /* 2 bytes - stream number */ + /* 2 bytes - high water value */ + +#define GDLYGETLOVALUE 0x11D50003 /* 4 */ +#define GDLYSETLOVALUE 0x11D50004 /* 4 set the low water value */ + /* 2 bytes - stream number */ + /* 2 bytes - low water value */ + +#define GDLYGETHITIME 0x11D50005 /* 4 */ +#define GDLYSETHITIME 0x11D50006 /* 4 set the high water time */ + /* 2 bytes - stream number */ + /* 2 bytes - high water time (ms) */ + +#define GDLYGETLOTIME 0x11D50007 /* 4 */ +#define GDLYSETLOTIME 0x11D50008 /* 4 set the low water time */ + /* 2 bytes - stream number */ + /* 2 bytes - low water time (ms) */ + +#define GDLYGETLOREPORT 0x11D50009 /* 4 get the low water report flag */ + /* 2 bytes - stream number */ + /* 2 bytes - 1: report when low */ + /* 0: do not report when low*/ + +#define GDLYFLUSHSTREAM 0x11D5000A /* 2 flush the delay buffer */ + /* 2 bytes - stream number */ + +#define GDLYINITSTREAM 0x11D5000B /* 2 set default hi & lo water marks*/ + /* 2 bytes - stream number */ + +#define GDLYPARTIALFLUSHSTREAM 0x11D5000C /* 4 flush the delay buffer */ + /* 2 bytes - stream number */ + /* 2 bytes - data to retain in ms */ + + +#define GINPGETINP 0x11500001 +#define GINPGETLATCH 0x11500002 +#define GINPCLRLATCH 0x11500003 +#define GOUTGET 0x11510001 +#define GOUTSET 0x11510002 +#define GOUTSETBIT 0x11510003 +#define GOUTCLEARBIT 0x11510004 +#define GPWRGETWHICH 0x11520001 +#define GPWROFF 0x11520002 +#define GPWROFFRESET 0x11520003 +#define GPWRRESET 0x11520004 + + +/* Hardware / driver TYPE and SUBTYPE definitions */ + +#define GDUMMY 0x01 /* Dummy device driver TYPE */ +#define GDGDMARKONE 0x01 /* Dummy device driver SUBTYPE */ + +#define GCAN 0x02 /* CAN TYPE */ +#define G82527 0x01 /* 82527 SUBTYPE */ +#define GSJA1000 0x02 /* SJA1000 SUBTYPE */ +#define G82527SW 0x03 /* 82527 single wire subtype */ +#define G82527ISO11992 0x04 /* 82527 ISO11992 subtype */ +#define G82527_SINGLECHAN 0x05 /* 82527 single channel */ +#define G82527SW_SINGLECHAN 0x06 /* 82527 single wire single channel */ +#define G82527ISO11992_SINGLECHAN 0x07 /* 82527 ISO11992 single channel */ +#define GSJA1000FT 0x10 /* SJA1000 Fault Tolerant subtype */ +#define GSJA1000C 0x11 /* SJA1000 Compact subtype */ +#define GSJA1000FT_FO 0x12 /* SJA1000 single chsnnel Fault Tolerant subtype */ +#define GSJA1000_BEACON_CANFD 0x1a /* SJA1000 BEACON CAN-FD subtype */ +#define GSJA1000_BEACON_SW 0x1b /* SJA1000 BEACON CAN single wire subtype */ +#define GSJA1000_BEACON_FT 0x1c /* SJA1000 BEACON CAN Fault Tolerant subtype */ + +#define GJ1850 0x03 /* 1850 TYPE */ +#define GHBCCPAIR 0x01 /* HBCC SUBTYPE */ +#define GDLC 0x02 /* GM DLC SUBTYPE */ +#define GCHRYSLER 0x03 /* Chrysler SUBTYPE */ +#define GDEHC12 0x04 /* DE HC12 KWP/BDLC SUBTYPE */ + +#define GKWP2000 0x04 /* Keyword protocol 2000 TYPE */ +#define GDEHC12KWP 0x01 /* DE HC12 KWP/BDLC card SUBTYPE */ + +#define GHONDA 0x05 /* Honda UART TYPE */ +#define GDGHC08 0x01 /* DG HC08 SUBTYPE */ + +#define GFORDUBP 0x06 /* FORD UBP TYPE */ +#define GDGUBP08 0x01 /* DG HC08 SUBTYPE */ + +#define GSCI 0x09 /* Chrysler SCI TYPE */ +#define G16550SCI 0x01 /* 16550 type UART based card SUBTYPE */ + +#define GCCD 0x0a /* Chrysler C2D TYPE */ +#define G16550CDP68HC68 0x01 /* 16550 / CDP68HC68S1 card SUBTYPE */ + +#define GLIN 0x0b /* LIN TYPE */ +#define GDGLIN08 0x01 /* DG HC08 SUBTYPE */ +#define GDGLIN_BEACON 0x03 /* DG BEACON LIN SUBTYPE */ + +typedef struct { + guint32 cmd; + guint32 cmd_context; //typically just guint8, but let's room for expansion/improvement + guint32 ioctl_command; //should be more generic, but IOCTL is currently the only user + guint32 req_frame_num; + guint32 rsp_frame_num; + nstime_t req_time; +} gryphon_pkt_info_t; + +/* List contains request data */ +typedef struct { + wmem_list_t *request_frame_data; +} gryphon_conversation; + + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/irda/CMakeLists.txt b/plugins/epan/irda/CMakeLists.txt new file mode 100644 index 00000000..31bfe897 --- /dev/null +++ b/plugins/epan/irda/CMakeLists.txt @@ -0,0 +1,66 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(irda 0 0 6 0) + +set(DISSECTOR_SRC + packet-ircomm.c + packet-irda.c + packet-sir.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_wireshark_plugin_library(irda epan) + +target_link_libraries(irda epan) + +install_plugin(irda epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + irda + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/irda/irda-appl.h b/plugins/epan/irda/irda-appl.h new file mode 100644 index 00000000..5a839405 --- /dev/null +++ b/plugins/epan/irda/irda-appl.h @@ -0,0 +1,87 @@ +/* irda-appl.h + * Interface for IrDA application dissectors + * By Jan Kiszka + * Copyright 2003 Jan Kiszka + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#ifndef __IRDA_APPL_H__ +#define __IRDA_APPL_H__ + +/* + * Prototypes, defines, and typedefs needed for implementing IrDA application + * layer dissectors. + * There should be no need to modify this part. + */ + +/* LM-IAS Attribute types */ +#define IAS_MISSING 0 +#define IAS_INTEGER 1 +#define IAS_OCT_SEQ 2 +#define IAS_STRING 3 + +/* Maximum number of handled list entries of an IAP result */ +#define MAX_IAP_ENTRIES 32 + + +typedef enum { + CONNECT_PDU, + DISCONNECT_PDU, + DATA_PDU +} pdu_type_t; + +typedef gboolean (*ias_value_dissector_t)(tvbuff_t* tvb, guint offset, packet_info* pinfo, proto_tree* tree, + guint list_index, guint8 attr_type, guint8 circuit_id); + +typedef const struct ias_attr_dissector { + const char* attr_name; + ias_value_dissector_t value_dissector; +} ias_attr_dissector_t; + +typedef const struct ias_class_dissector { + const char* class_name; + ias_attr_dissector_t* pattr_dissector; +} ias_class_dissector_t; + + +extern gboolean check_iap_octet_result(tvbuff_t* tvb, proto_tree* tree, guint offset, + const char* attr_name, guint8 attr_type); +extern guint8 check_iap_lsap_result(tvbuff_t* tvb, proto_tree* tree, guint offset, + const char* attr_name, guint8 attr_type); + +extern void add_lmp_conversation(packet_info* pinfo, guint8 dlsap, gboolean ttp, dissector_handle_t dissector, guint8 circuit_id); + +extern unsigned dissect_param_tuple(tvbuff_t* tvb, proto_tree* tree, guint offset); + +/* + * Protocol exports. + * Modify the lines below to add new protocols. + */ + +/* IrCOMM/IrLPT protocol */ +extern void proto_register_ircomm(void); +extern ias_attr_dissector_t ircomm_attr_dissector[]; +extern ias_attr_dissector_t irlpt_attr_dissector[]; + +/* Serial Infrared (SIR) */ +extern void proto_register_irsir(void); + + +/* + * Protocol hooks + */ + +/* IAS class dissectors */ +#define CLASS_DISSECTORS \ + { "Device", device_attr_dissector }, \ + { "IrDA:IrCOMM", ircomm_attr_dissector }, \ + { "IrLPT", irlpt_attr_dissector }, \ + { NULL, NULL } + +#endif /* __IRDA_APPL_H__ */ diff --git a/plugins/epan/irda/packet-ircomm.c b/plugins/epan/irda/packet-ircomm.c new file mode 100644 index 00000000..0f46c33d --- /dev/null +++ b/plugins/epan/irda/packet-ircomm.c @@ -0,0 +1,428 @@ +/* packet-ircomm.c + * Routines for IrCOMM dissection + * Copyright 2003 Jan Kiszka + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +/* + * See + * + * http://www.irdajp.info/specifications.php + * + * or + * + * https://web.archive.org/web/20040405053146/http://www.irda.org/standards/specifications.asp + * + * for various IrDA specifications. + */ + +#include "irda-appl.h" + + +/* Parameters common to all service types */ +#define IRCOMM_SERVICE_TYPE 0x00 +#define IRCOMM_PORT_TYPE 0x01 /* Only used in LM-IAS */ +#define IRCOMM_PORT_NAME 0x02 /* Only used in LM-IAS */ + +/* Parameters for both 3 wire and 9 wire */ +#define IRCOMM_DATA_RATE 0x10 +#define IRCOMM_DATA_FORMAT 0x11 +#define IRCOMM_FLOW_CONTROL 0x12 +#define IRCOMM_XON_XOFF 0x13 +#define IRCOMM_ENQ_ACK 0x14 +#define IRCOMM_LINE_STATUS 0x15 +#define IRCOMM_BREAK 0x16 + +/* Parameters for 9 wire */ +#define IRCOMM_DTE 0x20 +#define IRCOMM_DCE 0x21 +#define IRCOMM_POLL 0x22 + +/* Service type (details) */ +#define IRCOMM_3_WIRE_RAW 0x01 +#define IRCOMM_3_WIRE 0x02 +#define IRCOMM_9_WIRE 0x04 +#define IRCOMM_CENTRONICS 0x08 + +/* Port type (details) */ +#define IRCOMM_SERIAL 0x01 +#define IRCOMM_PARALLEL 0x02 + +/* Data format (details) */ +#define IRCOMM_WSIZE_5 0x00 +#define IRCOMM_WSIZE_6 0x01 +#define IRCOMM_WSIZE_7 0x02 +#define IRCOMM_WSIZE_8 0x03 + +#define IRCOMM_1_STOP_BIT 0x00 +#define IRCOMM_2_STOP_BIT 0x04 /* 1.5 if char len 5 */ + +#define IRCOMM_PARITY_DISABLE 0x00 +#define IRCOMM_PARITY_ENABLE 0x08 + +#define IRCOMM_PARITY_ODD 0x00 +#define IRCOMM_PARITY_EVEN 0x10 +#define IRCOMM_PARITY_MARK 0x20 +#define IRCOMM_PARITY_SPACE 0x30 + +/* Flow control */ +#define IRCOMM_XON_XOFF_IN 0x01 +#define IRCOMM_XON_XOFF_OUT 0x02 +#define IRCOMM_RTS_CTS_IN 0x04 +#define IRCOMM_RTS_CTS_OUT 0x08 +#define IRCOMM_DSR_DTR_IN 0x10 +#define IRCOMM_DSR_DTR_OUT 0x20 +#define IRCOMM_ENQ_ACK_IN 0x40 +#define IRCOMM_ENQ_ACK_OUT 0x80 + +/* Line status */ +#define IRCOMM_OVERRUN_ERROR 0x02 +#define IRCOMM_PARITY_ERROR 0x04 +#define IRCOMM_FRAMING_ERROR 0x08 + +/* DTE (Data terminal equipment) line settings */ +#define IRCOMM_DELTA_DTR 0x01 +#define IRCOMM_DELTA_RTS 0x02 +#define IRCOMM_DTR 0x04 +#define IRCOMM_RTS 0x08 + +/* DCE (Data communications equipment) line settings */ +#define IRCOMM_DELTA_CTS 0x01 /* Clear to send has changed */ +#define IRCOMM_DELTA_DSR 0x02 /* Data set ready has changed */ +#define IRCOMM_DELTA_RI 0x04 /* Ring indicator has changed */ +#define IRCOMM_DELTA_CD 0x08 /* Carrier detect has changed */ +#define IRCOMM_CTS 0x10 /* Clear to send is high */ +#define IRCOMM_DSR 0x20 /* Data set ready is high */ +#define IRCOMM_RI 0x40 /* Ring indicator is high */ +#define IRCOMM_CD 0x80 /* Carrier detect is high */ +#define IRCOMM_DCE_DELTA_ANY 0x0f + +void proto_reg_handoff_ircomm(void); + +/* Initialize the subtree pointers */ +static gint ett_ircomm = -1; +static gint ett_ircomm_ctrl = -1; + +#define MAX_PARAMETERS 32 +static gint ett_param[MAX_IAP_ENTRIES * MAX_PARAMETERS]; + +static dissector_handle_t ircomm_raw_handle; +static dissector_handle_t ircomm_cooked_handle; + +static int proto_ircomm = -1; +static int hf_ircomm_param = -1; +/* static int hf_param_pi = -1; */ +/* static int hf_param_pl = -1; */ +/* static int hf_param_pv = -1; */ +static int hf_control = -1; +static int hf_control_len = -1; + +static gboolean dissect_ircomm_parameters(tvbuff_t* tvb, guint offset, packet_info* pinfo, + proto_tree* tree, guint list_index, guint8 attr_type, guint8 circuit_id); +static gboolean dissect_ircomm_ttp_lsap(tvbuff_t* tvb, guint offset, packet_info* pinfo, + proto_tree* tree, guint list_index, guint8 attr_type, guint8 circuit_id); +static gboolean dissect_ircomm_lmp_lsap(tvbuff_t* tvb, guint offset, packet_info* pinfo, + proto_tree* tree, guint list_index, guint8 attr_type, guint8 circuit_id); + +ias_attr_dissector_t ircomm_attr_dissector[] = { +/* IrDA:IrCOMM attribute dissectors */ + { "Parameters", dissect_ircomm_parameters }, + { "IrDA:TinyTP:LsapSel", dissect_ircomm_ttp_lsap }, + { NULL, NULL } +}; + +ias_attr_dissector_t irlpt_attr_dissector[] = { +/* IrLPT attribute dissectors */ + { "IrDA:IrLMP:LsapSel", dissect_ircomm_lmp_lsap }, + { "IrDA:IrLMP:LSAPSel", dissect_ircomm_lmp_lsap }, /* according to IrCOMM V1.0, p25 */ + { NULL, NULL } +}; + + +/* + * Dissect the cooked IrCOMM protocol + */ +static int dissect_cooked_ircomm(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) +{ + proto_item *ti; + proto_tree *ircomm_tree, *ctrl_tree; + guint offset = 0; + guint clen; + gint len = tvb_reported_length(tvb); + + if (len == 0) + return len; + + /* Make entries in Protocol column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrCOMM"); + + clen = tvb_get_guint8(tvb, offset); + len -= 1 + clen; + + if (len > 0) + col_add_fstr(pinfo->cinfo, COL_INFO, "Clen=%d, UserData: %d byte%s", clen, len, (len > 1)? "s": ""); + else + col_add_fstr(pinfo->cinfo, COL_INFO, "Clen=%d", clen); + + /* create display subtree for the protocol */ + ti = proto_tree_add_item(tree, proto_ircomm, tvb, 0, -1, ENC_NA); + ircomm_tree = proto_item_add_subtree(ti, ett_ircomm); + + ti = proto_tree_add_item(ircomm_tree, hf_control, tvb, 0, clen + 1, ENC_NA); + ctrl_tree = proto_item_add_subtree(ti, ett_ircomm_ctrl); + proto_tree_add_item(ctrl_tree, hf_control_len, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + call_data_dissector(tvb_new_subset_length(tvb, offset, clen), pinfo, ctrl_tree); + offset += clen; + + call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, ircomm_tree); + + return len; +} + + +/* + * Dissect the raw IrCOMM/IrLPT protocol + */ +static int dissect_raw_ircomm(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) +{ + guint len = tvb_reported_length(tvb); + proto_item* ti; + proto_tree* ircomm_tree; + + if (len == 0) + return 0; + + /* Make entries in Protocol column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrCOMM"); + + col_add_fstr(pinfo->cinfo, COL_INFO, "User Data: %d byte%s", len, (len > 1)? "s": ""); + + /* create display subtree for the protocol */ + ti = proto_tree_add_item(tree, proto_ircomm, tvb, 0, -1, ENC_NA); + ircomm_tree = proto_item_add_subtree(ti, ett_ircomm); + + call_data_dissector(tvb, pinfo, ircomm_tree); + + return len; +} + + +/* + * Dissect IrCOMM IAS "Parameters" attribute + */ +static gboolean dissect_ircomm_parameters(tvbuff_t* tvb, guint offset, packet_info* pinfo _U_, + proto_tree* tree, guint list_index, guint8 attr_type, guint8 circuit_id _U_) +{ + guint len; + guint n = 0; + proto_item* ti; + proto_tree* p_tree; + char buf[256]; + guint8 pv; + + + if (!check_iap_octet_result(tvb, tree, offset, "Parameters", attr_type)) + return TRUE; + + if (tree) + { + len = tvb_get_ntohs(tvb, offset) + offset + 2; + offset += 2; + + while (offset < len) + { + guint8 p_len = tvb_get_guint8(tvb, offset + 1); + + + ti = proto_tree_add_item(tree, hf_ircomm_param, tvb, offset, p_len + 2, ENC_NA); + p_tree = proto_item_add_subtree(ti, ett_param[list_index * MAX_PARAMETERS + n]); + + buf[0] = 0; + + switch (tvb_get_guint8(tvb, offset)) + { + case IRCOMM_SERVICE_TYPE: + proto_item_append_text(ti, ": Service Type ("); + + pv = tvb_get_guint8(tvb, offset+2); + if (pv & IRCOMM_3_WIRE_RAW) + (void) g_strlcat(buf, ", 3-Wire raw", 256); + if (pv & IRCOMM_3_WIRE) + (void) g_strlcat(buf, ", 3-Wire", 256); + if (pv & IRCOMM_9_WIRE) + (void) g_strlcat(buf, ", 9-Wire", 256); + if (pv & IRCOMM_CENTRONICS) + (void) g_strlcat(buf, ", Centronics", 256); + + (void) g_strlcat(buf, ")", 256); + + if (strlen(buf) > 2) + proto_item_append_text(ti, "%s", buf+2); + else + proto_item_append_text(ti, "unknown)"); + + break; + + case IRCOMM_PORT_TYPE: + proto_item_append_text(ti, ": Port Type ("); + + pv = tvb_get_guint8(tvb, offset+2); + if (pv & IRCOMM_SERIAL) + (void) g_strlcat(buf, ", serial", 256); + if (pv & IRCOMM_PARALLEL) + (void) g_strlcat(buf, ", parallel", 256); + + (void) g_strlcat(buf, ")", 256); + + if (strlen(buf) > 2) + proto_item_append_text(ti, "%s", buf+2); + else + proto_item_append_text(ti, "unknown)"); + + break; + + case IRCOMM_PORT_NAME: + /* XXX - the IrCOMM V1.0 spec says this "Normally + human readable text, but not required". */ + proto_item_append_text(ti, ": Port Name (\"%s\")", + tvb_format_text(pinfo->pool, tvb, offset+2, p_len)); + + break; + + default: + proto_item_append_text(ti, ": unknown"); + } + + offset = dissect_param_tuple(tvb, p_tree, offset); + n++; + } + + } + + return TRUE; +} + + +/* + * Dissect IrCOMM IAS "IrDA:TinyTP:LsapSel" attribute + */ +static gboolean dissect_ircomm_ttp_lsap(tvbuff_t* tvb, guint offset, packet_info* pinfo, + proto_tree* tree, guint list_index _U_, guint8 attr_type, guint8 circuit_id) +{ + guint8 dlsap; + + + if ((dlsap = check_iap_lsap_result(tvb, tree, offset, "IrDA:TinyTP:LsapSel", attr_type)) == 0) + return FALSE; + + add_lmp_conversation(pinfo, dlsap, TRUE, ircomm_cooked_handle, circuit_id); + + return FALSE; +} + + +/* + * Dissect IrCOMM/IrLPT IAS "IrDA:IrLMP:LsapSel" attribute + */ +static gboolean dissect_ircomm_lmp_lsap(tvbuff_t* tvb, guint offset, packet_info* pinfo, + proto_tree* tree, guint list_index _U_, guint8 attr_type, guint8 circuit_id) +{ + guint8 dlsap; + + + if ((dlsap = check_iap_lsap_result(tvb, tree, offset, "IrDA:IrLMP:LsapSel", attr_type)) == 0) + return FALSE; + + add_lmp_conversation(pinfo, dlsap, FALSE, ircomm_raw_handle, circuit_id); + + return FALSE; +} + + +/* + * Register the IrCOMM protocol + */ +void proto_register_ircomm(void) +{ + guint i; + + /* Setup list of header fields */ + static hf_register_info hf_ircomm[] = { + { &hf_ircomm_param, + { "IrCOMM Parameter", "ircomm.parameter", + FT_NONE, BASE_NONE, NULL, 0, + NULL, HFILL }}, +#if 0 + { &hf_param_pi, + { "Parameter Identifier", "ircomm.pi", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_param_pl, + { "Parameter Length", "ircomm.pl", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_param_pv, + { "Parameter Value", "ircomm.pv", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL }}, +#endif + { &hf_control, + { "Control Channel", "ircomm.control", + FT_NONE, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_control_len, + { "Clen", "ircomm.control.len", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL }} + }; + + /* Setup protocol subtree arrays */ + static gint* ett[] = { + &ett_ircomm, + &ett_ircomm_ctrl + }; + + gint* ett_p[MAX_IAP_ENTRIES * MAX_PARAMETERS]; + + + /* Register protocol names and descriptions */ + proto_ircomm = proto_register_protocol("IrCOMM Protocol", "IrCOMM", "ircomm"); + ircomm_raw_handle = register_dissector("ircomm_raw", dissect_raw_ircomm, proto_ircomm); + ircomm_cooked_handle = register_dissector("ircomm_cooked", dissect_cooked_ircomm, proto_ircomm); + + /* Required function calls to register the header fields */ + proto_register_field_array(proto_ircomm, hf_ircomm, array_length(hf_ircomm)); + + /* Register subtrees */ + proto_register_subtree_array(ett, array_length(ett)); + for (i = 0; i < MAX_IAP_ENTRIES * MAX_PARAMETERS; i++) + { + ett_param[i] = -1; + ett_p[i] = &ett_param[i]; + } + proto_register_subtree_array(ett_p, MAX_IAP_ENTRIES * MAX_PARAMETERS); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/irda/packet-irda.c b/plugins/epan/irda/packet-irda.c new file mode 100644 index 00000000..d3c2c835 --- /dev/null +++ b/plugins/epan/irda/packet-irda.c @@ -0,0 +1,2327 @@ +/* packet-irda.c + * Routines for IrDA dissection + * By Shaun Jackman + * Copyright 2000 Shaun Jackman + * + * Extended by Jan Kiszka + * Copyright 2003 Jan Kiszka + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "irda-appl.h" + +/* + * This plugin dissects infrared data transmissions as defined by the IrDA + * specification (www.irda.org). See + * + * http://www.irdajp.info/specifications.php + * + * or + * + * https://web.archive.org/web/20040405053146/http://www.irda.org/standards/specifications.asp + * + * for various IrDA specifications. + * + * The plugin operates both offline with libpcap files and online on supported + * platforms. Live dissection is currently available for Linux-IrDA + * (irda.sourceforge.net) and for Windows if the Linux-IrDA port IrCOMM2k + * (www.ircomm2k.de) is installed. + */ + +/* + * LAP + */ + +/* Frame types and templates */ +#define INVALID 0xff + +/* + * XXX - the IrDA spec gives XID as 0x2c; HDLC (and other HDLC-derived + * protocolc) use 0xAC. + */ +#define IRDA_XID_CMD 0x2c /* Exchange Station Identification */ + +#define CMD_FRAME 0x01 +#define RSP_FRAME 0x00 + +/* Discovery Flags */ +#define S_MASK 0x03 +#define CONFLICT 0x04 + +/* Negotiation Parameters */ +#define PI_BAUD_RATE 0x01 +#define PI_MAX_TURN_TIME 0x82 +#define PI_DATA_SIZE 0x83 +#define PI_WINDOW_SIZE 0x84 +#define PI_ADD_BOFS 0x85 +#define PI_MIN_TURN_TIME 0x86 +#define PI_LINK_DISC 0x08 + + +/* + * LMP + */ + +/* IrLMP frame opcodes */ +#define CONNECT_CMD 0x01 +#define CONNECT_CNF 0x81 +#define DISCONNECT 0x02 +#define ACCESSMODE_CMD 0x03 +#define ACCESSMODE_CNF 0x83 + +#define CONTROL_BIT 0x80 +#define RESERVED_BIT 0x80 + +/* LSAP-SEL's */ +#define LSAP_MASK 0x7f +#define LSAP_IAS 0x00 +#define LSAP_ANY 0xff +#define LSAP_MAX 0x6f /* 0x70-0x7f are reserved */ +#define LSAP_CONNLESS 0x70 /* Connectionless LSAP, mostly used for Ultra */ + + +/* + * IAP + */ + +/* IrIAP Op-codes */ +#define GET_INFO_BASE 0x01 +#define GET_OBJECTS 0x02 +#define GET_VALUE 0x03 +#define GET_VALUE_BY_CLASS 0x04 +#define GET_OBJECT_INFO 0x05 +#define GET_ATTRIB_NAMES 0x06 + +#define IAP_LST 0x80 +#define IAP_ACK 0x40 +#define IAP_OP 0x3F + +#define IAS_SUCCESS 0 +#define IAS_CLASS_UNKNOWN 1 +#define IAS_ATTRIB_UNKNOWN 2 +#define IAS_ATTR_TOO_LONG 3 +#define IAS_DISCONNECT 10 +#define IAS_UNSUPPORTED 0xFF + + +/* + * TTP + */ + +#define TTP_PARAMETERS 0x80 +#define TTP_MORE 0x80 + +void proto_reg_handoff_irda(void); +void proto_register_irda(void); + +/* Initialize the protocol and registered fields */ +static int proto_irlap = -1; +static int hf_lap_a = -1; +static int hf_lap_a_cr = -1; +static int hf_lap_a_address = -1; +static int hf_lap_c = -1; +static int hf_lap_c_nr = -1; +static int hf_lap_c_ns = -1; +static int hf_lap_c_p = -1; +static int hf_lap_c_f = -1; +static int hf_lap_c_s = -1; +static int hf_lap_c_u_cmd = -1; +static int hf_lap_c_u_rsp = -1; +static int hf_lap_c_i = -1; +static int hf_lap_c_s_u = -1; +static int hf_lap_i = -1; +static int hf_snrm_saddr = -1; +static int hf_snrm_daddr = -1; +static int hf_snrm_ca = -1; +static int hf_ua_saddr = -1; +static int hf_ua_daddr = -1; +static int hf_negotiation_param = -1; +static int hf_param_pi = -1; +static int hf_param_pl = -1; +static int hf_param_pv = -1; +static int hf_xid_ident = -1; +static int hf_xid_saddr = -1; +static int hf_xid_daddr = -1; +static int hf_xid_flags = -1; +static int hf_xid_s = -1; +static int hf_xid_conflict = -1; +static int hf_xid_slotnr = -1; +static int hf_xid_version = -1; + +static int proto_irlmp = -1; +static int hf_lmp_xid_hints = -1; +static int hf_lmp_xid_charset = -1; +static int hf_lmp_xid_name = -1; +static int hf_lmp_xid_name_no_encoding = -1; +static int hf_lmp_dst = -1; +static int hf_lmp_dst_control = -1; +static int hf_lmp_dst_lsap = -1; +static int hf_lmp_src = -1; +static int hf_lmp_src_r = -1; +static int hf_lmp_src_lsap = -1; +static int hf_lmp_opcode = -1; +static int hf_lmp_rsvd = -1; +static int hf_lmp_reason = -1; +static int hf_lmp_mode = -1; +static int hf_lmp_status = -1; + +static int proto_iap = -1; +static int hf_iap_ctl = -1; +static int hf_iap_ctl_lst = -1; +static int hf_iap_ctl_ack = -1; +static int hf_iap_ctl_opcode = -1; +static int hf_iap_class_name = -1; +static int hf_iap_attr_name = -1; +static int hf_iap_return = -1; +static int hf_iap_list_len = -1; +static int hf_iap_list_entry = -1; +static int hf_iap_obj_id = -1; +static int hf_iap_attr_type = -1; +static int hf_iap_int = -1; +static int hf_iap_seq_len = -1; +static int hf_iap_oct_seq = -1; +static int hf_iap_char_set = -1; +static int hf_iap_string = -1; +static int hf_iap_invaloctet = -1; +static int hf_iap_invallsap = -1; + +static int proto_ttp = -1; +static int hf_ttp_p = -1; +static int hf_ttp_icredit = -1; +static int hf_ttp_m = -1; +static int hf_ttp_dcredit = -1; + +static int proto_log = -1; +static int hf_log_msg = -1; +static int hf_log_missed = -1; + +/* Initialize the subtree pointers */ +static gint ett_irlap = -1; +static gint ett_lap_a = -1; +static gint ett_lap_c = -1; +static gint ett_lap_i = -1; +static gint ett_xid_flags = -1; +static gint ett_log = -1; +static gint ett_irlmp = -1; +static gint ett_lmp_dst = -1; +static gint ett_lmp_src = -1; +static gint ett_iap = -1; +static gint ett_iap_ctl = -1; +static gint ett_ttp = -1; + +#define MAX_PARAMETERS 32 +static gint ett_param[MAX_PARAMETERS]; + +static gint ett_iap_entry[MAX_IAP_ENTRIES]; + +static int irda_address_type = -1; + +static dissector_handle_t irda_handle; + +static const xdlc_cf_items irlap_cf_items = { + &hf_lap_c_nr, + &hf_lap_c_ns, + &hf_lap_c_p, + &hf_lap_c_f, + &hf_lap_c_s, + &hf_lap_c_u_cmd, + &hf_lap_c_u_rsp, + &hf_lap_c_i, + &hf_lap_c_s_u +}; + +/* IAP conversation type */ +typedef struct iap_conversation { + struct iap_conversation* pnext; + guint32 iap_query_frame; + ias_attr_dissector_t* pattr_dissector; +} iap_conversation_t; + +/* IrLMP conversation type */ +typedef struct lmp_conversation { + struct lmp_conversation* pnext; + guint32 iap_result_frame; + gboolean ttp; + dissector_handle_t dissector; +} lmp_conversation_t; + +static const true_false_string lap_cr_vals = { + "Command", + "Response" +}; + +static const true_false_string set_notset = { + "Set", + "Not set" +}; + +static const value_string lap_c_ftype_vals[] = { + { XDLC_I, "Information frame" }, + { XDLC_S, "Supervisory frame" }, + { XDLC_U, "Unnumbered frame" }, + { 0, NULL } +}; + +static const value_string lap_c_u_cmd_abbr_vals[] = { + { XDLC_SNRM, "SNRM" }, + { XDLC_DISC, "DISC" }, + { XDLC_UI, "UI" }, + { IRDA_XID_CMD, "XID" }, + { XDLC_TEST, "TEST" }, + { 0, NULL } +}; + +static const value_string lap_c_u_rsp_abbr_vals[] = { + { XDLC_SNRM, "RNRM" }, + { XDLC_UA, "UA" }, + { XDLC_FRMR, "FRMR" }, + { XDLC_DM, "DM" }, + { XDLC_RD, "RD" }, + { XDLC_UI, "UI" }, + { XDLC_XID, "XID" }, + { XDLC_TEST, "TEST" }, + { 0, NULL } +}; + +static const value_string lap_c_u_cmd_vals[] = { + { XDLC_SNRM>>2, "Set Normal Response Mode" }, + { XDLC_DISC>>2, "Disconnect" }, + { XDLC_UI>>2, "Unnumbered Information" }, + { IRDA_XID_CMD>>2, "Exchange Station Identification" }, + { XDLC_TEST>>2, "Test" }, + { 0, NULL } +}; + +static const value_string lap_c_u_rsp_vals[] = { + { XDLC_SNRM>>2, "Request Normal Response Mode" }, + { XDLC_UA>>2, "Unnumbered Acknowledge" }, + { XDLC_FRMR>>2, "Frame Reject" }, + { XDLC_DM>>2, "Disconnect Mode" }, + { XDLC_RD>>2, "Request Disconnect" }, + { XDLC_UI>>2, "Unnumbered Information" }, + { XDLC_XID>>2, "Exchange Station Identification" }, + { XDLC_TEST>>2, "Test" }, + { 0, NULL } +}; + +static const value_string lap_c_s_vals[] = { + { XDLC_RR>>2, "Receiver ready" }, + { XDLC_RNR>>2, "Receiver not ready" }, + { XDLC_REJ>>2, "Reject" }, + { XDLC_SREJ>>2, "Selective reject" }, + { 0, NULL } +}; + +static const value_string xid_slot_numbers[] = { +/* Number of XID slots */ + { 0, "1" }, + { 1, "6" }, + { 2, "8" }, + { 3, "16" }, + { 0, NULL } +}; + +static const value_string lmp_opcode_vals[] = { +/* IrLMP frame opcodes */ + { CONNECT_CMD, "Connect Command" }, + { CONNECT_CNF, "Connect Confirm" }, + { DISCONNECT, "Disconnect" }, + { ACCESSMODE_CMD, "Access Mode Command" }, + { ACCESSMODE_CNF, "Access Mode Confirm" }, + { 0, NULL } +}; + +static const value_string lmp_reason_vals[] = { +/* IrLMP disconnect reasons */ + { 0x01, "User Request" }, + { 0x02, "Unexpected IrLAP Disconnect" }, + { 0x03, "Failed to establish IrLAP connection" }, + { 0x04, "IrLAP Reset" }, + { 0x05, "Link Management Initiated Disconnect" }, + { 0x06, "Data delivered on disconnected LSAP-Connection"}, + { 0x07, "Non Responsive LM-MUX Client" }, + { 0x08, "No available LM-MUX Client" }, + { 0x09, "Connection Half Open" }, + { 0x0A, "Illegal Source Address" }, + { 0xFF, "Unspecified Disconnect Reason" }, + { 0, NULL } +}; + +static const value_string lmp_mode_vals[] = { +/* IrLMP modes */ + { 0x00, "Multiplexed" }, + { 0x01, "Exclusive" }, + { 0, NULL } +}; + +static const value_string lmp_status_vals[] = { +/* IrLMP status */ + { 0x00, "Success" }, + { 0x01, "Failure" }, + { 0xFF, "Unsupported" }, + { 0, NULL } +}; + +#define LMP_CHARSET_ASCII 0 +#define LMP_CHARSET_ISO_8859_1 1 +#define LMP_CHARSET_ISO_8859_2 2 +#define LMP_CHARSET_ISO_8859_3 3 +#define LMP_CHARSET_ISO_8859_4 4 +#define LMP_CHARSET_ISO_8859_5 5 +#define LMP_CHARSET_ISO_8859_6 6 +#define LMP_CHARSET_ISO_8859_7 7 +#define LMP_CHARSET_ISO_8859_8 8 +#define LMP_CHARSET_ISO_8859_9 9 +#define LMP_CHARSET_UNICODE 0xFF /* UCS-2 (byte order?) */ + +static const value_string lmp_charset_vals[] = { +/* IrLMP character set */ + { LMP_CHARSET_ASCII, "ASCII" }, + { LMP_CHARSET_ISO_8859_1, "ISO 8859-1" }, + { LMP_CHARSET_ISO_8859_2, "ISO 8859-2" }, + { LMP_CHARSET_ISO_8859_3, "ISO 8859-3" }, + { LMP_CHARSET_ISO_8859_4, "ISO 8859-4" }, + { LMP_CHARSET_ISO_8859_5, "ISO 8859-5" }, + { LMP_CHARSET_ISO_8859_6, "ISO 8859-6" }, + { LMP_CHARSET_ISO_8859_7, "ISO 8859-7" }, + { LMP_CHARSET_ISO_8859_8, "ISO 8859-8" }, + { LMP_CHARSET_ISO_8859_9, "ISO 8859-9" }, + { LMP_CHARSET_UNICODE, "Unicode" }, + { 0, NULL } +}; + +static const value_string iap_opcode_vals[] = { +/* IrIAP Op-codes */ + { GET_INFO_BASE, "GetInfoBase" }, + { GET_OBJECTS, "GetObjects" }, + { GET_VALUE, "GetValue" }, + { GET_VALUE_BY_CLASS, "GetValueByClass" }, + { GET_OBJECT_INFO, "GetObjectInfo" }, + { GET_ATTRIB_NAMES, "GetAttributeNames" }, + { 0, NULL } +}; + +static const value_string iap_return_vals[] = { +/* IrIAP Return-codes */ + { IAS_SUCCESS, "Success" }, + { IAS_CLASS_UNKNOWN, "Class/Object Unknown" }, + { IAS_ATTRIB_UNKNOWN, "Attribute Unknown" }, + { IAS_ATTR_TOO_LONG, "Attribute List Too Long" }, + { IAS_DISCONNECT, "Disconnect (Linux-IrDA only)" }, + { IAS_UNSUPPORTED, "Unsupported Optional Operation" }, + { 0, NULL } +}; + +static const value_string iap_attr_type_vals[] = { +/* LM-IAS Attribute types */ + { IAS_MISSING, "Missing" }, + { IAS_INTEGER, "Integer" }, + { IAS_OCT_SEQ, "Octet Sequence" }, + { IAS_STRING, "String" }, + { 0, NULL } +}; + +static ias_attr_dissector_t device_attr_dissector[] = { +/* Device attribute dissectors */ +/* { "IrLMPSupport", xxx }, not implemented yet... */ + { NULL, NULL } +}; + +/* IAS class dissectors */ +static ias_class_dissector_t class_dissector[] = { CLASS_DISSECTORS }; + + +/* + * Dissect parameter tuple + */ +guint dissect_param_tuple(tvbuff_t* tvb, proto_tree* tree, guint offset) +{ + guint8 len = tvb_get_guint8(tvb, offset + 1); + + if (tree) + proto_tree_add_item(tree, hf_param_pi, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + if (tree) + proto_tree_add_item(tree, hf_param_pl, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + if (len > 0) + { + if (tree) + proto_tree_add_item(tree, hf_param_pv, tvb, offset, len, ENC_NA); + offset += len; + } + + return offset; +} + + +/* + * Dissect TTP + */ +static guint dissect_ttp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, gboolean data) +{ + guint offset = 0; + guint8 head; + char buf[128]; + + if (tvb_reported_length(tvb) == 0) + return 0; + + /* Make entries in Protocol column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "TTP"); + + head = tvb_get_guint8(tvb, offset); + + snprintf(buf, 128, ", Credit=%d", head & ~TTP_PARAMETERS); + col_append_str(pinfo->cinfo, COL_INFO, buf); + + if (root) + { + /* create display subtree for the protocol */ + proto_item* ti = proto_tree_add_item(root, proto_ttp, tvb, 0, -1, ENC_NA); + proto_tree* tree = proto_item_add_subtree(ti, ett_ttp); + + if (data) + { + proto_tree_add_item(tree, hf_ttp_m, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ttp_dcredit, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + } + else + { + proto_tree_add_item(tree, hf_ttp_p, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_ttp_icredit, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + } + proto_item_set_len(tree, offset); + } + else + offset++; + + return offset; +} + + +/* + * Dissect IAP request + */ +static void dissect_iap_request(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, guint8 circuit_id) +{ + guint offset = 0; + guint8 op; + guint8 clen = 0; + guint8 alen = 0; + guint8 src; + address srcaddr; + address destaddr; + conversation_t* conv; + iap_conversation_t* iap_conv; + + if (tvb_reported_length(tvb) == 0) + return; + + /* Make entries in Protocol column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAP"); + + op = tvb_get_guint8(tvb, offset) & IAP_OP; + + switch (op) + { + case GET_VALUE_BY_CLASS: + clen = MIN(tvb_get_guint8(tvb, offset + 1), 60); + alen = MIN(tvb_get_guint8(tvb, offset + 1 + 1 + clen), 60); + + /* create conversation entry */ + src = circuit_id ^ CMD_FRAME; + set_address(&srcaddr, irda_address_type, 1, &src); + + set_address(&destaddr, irda_address_type, 1, &circuit_id); + + conv = find_conversation(pinfo->num, &srcaddr, &destaddr, CONVERSATION_NONE, pinfo->srcport, pinfo->destport, 0); + if (conv) + { + iap_conv = (iap_conversation_t*)conversation_get_proto_data(conv, proto_iap); + while (1) + { + if (iap_conv->iap_query_frame == pinfo->num) + { + iap_conv = NULL; + break; + } + if (iap_conv->pnext == NULL) + { + iap_conv->pnext = wmem_new(wmem_file_scope(), iap_conversation_t); + iap_conv = iap_conv->pnext; + break; + } + iap_conv = iap_conv->pnext; + } + } + else + { + conv = conversation_new(pinfo->num, &srcaddr, &destaddr, CONVERSATION_NONE, pinfo->srcport, pinfo->destport, 0); + iap_conv = wmem_new(wmem_file_scope(), iap_conversation_t); + conversation_add_proto_data(conv, proto_iap, (void*)iap_conv); + } + if (iap_conv) + { + iap_conv->pnext = NULL; + iap_conv->iap_query_frame = pinfo->num; + iap_conv->pattr_dissector = NULL; + } + + char *class_name = (char *) tvb_get_string_enc(pinfo->pool, tvb, offset + 1 + 1, clen, ENC_ASCII|ENC_NA); + char *attr_name = (char *) tvb_get_string_enc(pinfo->pool, tvb, offset + 1 + 1 + clen + 1, alen, ENC_ASCII|ENC_NA); + + col_add_fstr(pinfo->cinfo, COL_INFO, "GetValueByClass: \"%s\" \"%s\"", + format_text(pinfo->pool, (guchar *) class_name, strlen(class_name)), + format_text(pinfo->pool, (guchar *) attr_name, strlen(attr_name))); + + /* Dissect IAP query if it is new */ + if (iap_conv) + { + int i, j; + + /* Find the attribute dissector */ + for (i = 0; class_dissector[i].class_name != NULL; i++) + if (strcmp(class_name, class_dissector[i].class_name) == 0) + { + for (j = 0; class_dissector[i].pattr_dissector[j].attr_name != NULL; j++) + if (strcmp(attr_name, class_dissector[i].pattr_dissector[j].attr_name) == 0) + { + iap_conv->pattr_dissector = &class_dissector[i].pattr_dissector[j]; + break; + } + break; + } + } + } + + if (root) + { + /* create display subtree for the protocol */ + proto_item* ti = proto_tree_add_item(root, proto_iap, tvb, 0, -1, ENC_NA); + proto_tree* tree = proto_item_add_subtree(ti, ett_iap); + + proto_tree* ctl_tree; + + + ti = proto_tree_add_item(tree, hf_iap_ctl, tvb, offset, 1, ENC_BIG_ENDIAN); + ctl_tree = proto_item_add_subtree(ti, ett_iap_ctl); + proto_tree_add_item(ctl_tree, hf_iap_ctl_lst, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ctl_tree, hf_iap_ctl_ack, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ctl_tree, hf_iap_ctl_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + switch (op) + { + case GET_VALUE_BY_CLASS: + proto_tree_add_item(tree, hf_iap_class_name, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN); + offset += 1 + clen; + + proto_tree_add_item(tree, hf_iap_attr_name, tvb, offset, 1, ENC_ASCII|ENC_BIG_ENDIAN); + offset += 1 + alen; + break; + } + } + else + { + offset++; + switch (op) + { + case GET_VALUE_BY_CLASS: + offset += 1 + clen + 1 + alen; + break; + } + } + + /* If any bytes remain, send it to the generic data dissector */ + tvb = tvb_new_subset_remaining(tvb, offset); + call_data_dissector(tvb, pinfo, root); +} + + +/* + * Dissect IAP result + */ +static void dissect_iap_result(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, guint8 circuit_id) +{ + guint offset = 0; + guint len = tvb_reported_length(tvb); + guint n = 0; + guint list_len; + guint8 op; + guint8 retcode; + guint8 type; + guint16 attr_len; + char buf[300]; + guint8 src; + address srcaddr; + address destaddr; + conversation_t* conv; + iap_conversation_t* cur_iap_conv; + iap_conversation_t* iap_conv = NULL; + guint32 num; + + + if (len == 0) + return; + + /* Make entries in Protocol column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IAP"); + + op = tvb_get_guint8(tvb, offset) & IAP_OP; + retcode = tvb_get_guint8(tvb, offset + 1); + + src = circuit_id ^ CMD_FRAME; + set_address(&srcaddr, irda_address_type, 1, &src); + + set_address(&destaddr, irda_address_type, 1, &circuit_id); + + /* Find result value dissector */ + conv = find_conversation(pinfo->num, &srcaddr, &destaddr, CONVERSATION_NONE, pinfo->srcport, pinfo->destport, 0); + if (conv) + { + num = pinfo->num; + + iap_conv = (iap_conversation_t*)conversation_get_proto_data(conv, proto_iap); + while (iap_conv && (iap_conv->iap_query_frame >= num)) + iap_conv = iap_conv->pnext; + + if (iap_conv) + { + cur_iap_conv = iap_conv->pnext; + while (cur_iap_conv) + { + if ((cur_iap_conv->iap_query_frame < num) && + (cur_iap_conv->iap_query_frame > iap_conv->iap_query_frame)) + { + iap_conv = cur_iap_conv; + } + + cur_iap_conv = cur_iap_conv->pnext; + } + } + } + + col_set_str(pinfo->cinfo, COL_INFO, "Result: "); + col_append_str(pinfo->cinfo, COL_INFO, val_to_str(retcode, iap_return_vals, "0x%02X")); + + switch (op) + { + case GET_VALUE_BY_CLASS: + if (retcode == 0) + { + switch (tvb_get_guint8(tvb, offset + 6)) + { + case IAS_MISSING: + col_append_str(pinfo->cinfo, COL_INFO, ", Missing"); + break; + + case IAS_INTEGER: + col_append_fstr(pinfo->cinfo, COL_INFO, ", Integer: %d", tvb_get_ntohl(tvb, offset + 7)); + break; + + case IAS_OCT_SEQ: + snprintf(buf, 300, ", %d Octets", tvb_get_ntohs(tvb, offset + 7)); + break; + + case IAS_STRING: + n = tvb_get_guint8(tvb, offset + 8); + col_append_fstr(pinfo->cinfo, COL_INFO, ", \"%s\"", tvb_get_string_enc(pinfo->pool, tvb, offset + 9, n, ENC_ASCII)); + break; + default: + break; + } + if (tvb_get_ntohs(tvb, offset + 2) > 1) + col_append_str(pinfo->cinfo, COL_INFO, ", ..."); + } + break; + } + + if (root) + { + /* create display subtree for the protocol */ + proto_item* ti = proto_tree_add_item(root, proto_iap, tvb, 0, -1, ENC_NA); + proto_tree* tree = proto_item_add_subtree(ti, ett_iap); + + proto_tree* ctl_tree; + proto_tree* entry_tree; + + + ti = proto_tree_add_item(tree, hf_iap_ctl, tvb, offset, 1, ENC_BIG_ENDIAN); + ctl_tree = proto_item_add_subtree(ti, ett_iap_ctl); + proto_tree_add_item(ctl_tree, hf_iap_ctl_lst, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ctl_tree, hf_iap_ctl_ack, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ctl_tree, hf_iap_ctl_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item(tree, hf_iap_return, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + switch (op) + { + case GET_VALUE_BY_CLASS: + if (retcode == 0) + { + list_len = tvb_get_ntohs(tvb, offset); + + proto_tree_add_item(tree, hf_iap_list_len, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + while ((offset < len) && (n < list_len)) + { + type = tvb_get_guint8(tvb, offset + 2); + switch (type) + { + case IAS_INTEGER: + attr_len = 4; + break; + + case IAS_OCT_SEQ: + attr_len = tvb_get_ntohs(tvb, offset + 2 + 1) + 2; + break; + + case IAS_STRING: + attr_len = tvb_get_guint8(tvb, offset + 2 + 1 + 1) + 2; + break; + + default: + attr_len = 0; + } + + ti = proto_tree_add_item(tree, hf_iap_list_entry, tvb, offset, 2 + 1 + attr_len, ENC_NA); + proto_item_append_text(ti, "%d", n + 1); + entry_tree = proto_item_add_subtree(ti, ett_iap_entry[n]); + + proto_tree_add_item(entry_tree, hf_iap_obj_id, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(entry_tree, hf_iap_attr_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + switch (type) + { + case IAS_INTEGER: + if (!iap_conv || !iap_conv->pattr_dissector || + !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree, + n, type, circuit_id)) + proto_tree_add_item(entry_tree, hf_iap_int, tvb, offset, 4, ENC_BIG_ENDIAN); + break; + + case IAS_OCT_SEQ: + proto_tree_add_item(entry_tree, hf_iap_seq_len, tvb, offset, 2, ENC_BIG_ENDIAN); + if (!iap_conv || !iap_conv->pattr_dissector || + !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree, + n, type, circuit_id)) + proto_tree_add_item(entry_tree, hf_iap_oct_seq, tvb, offset + 2, + attr_len - 2, ENC_NA); + break; + + case IAS_STRING: + proto_tree_add_item(entry_tree, hf_iap_char_set, tvb, offset, 1, ENC_BIG_ENDIAN); + if (!iap_conv || !iap_conv->pattr_dissector || + !iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, entry_tree, + n, type, circuit_id)) + proto_tree_add_item(entry_tree, hf_iap_string, tvb, offset + 1, 1, ENC_ASCII|ENC_BIG_ENDIAN); + break; + } + offset += attr_len; + + n++; + } + } + break; + } + } + else + { + offset += 2; + switch (op) + { + case GET_VALUE_BY_CLASS: + if (retcode == 0) + { + offset += 2; + + while (offset < len) + { + offset += 2; + type = tvb_get_guint8(tvb, offset); + offset++; + + switch (type) + { + case IAS_INTEGER: + attr_len = 4; + if (iap_conv && iap_conv->pattr_dissector) + iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0, + n, type, circuit_id); + break; + + case IAS_OCT_SEQ: + attr_len = tvb_get_ntohs(tvb, offset) + 2; + if (iap_conv && iap_conv->pattr_dissector) + iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0, + n, type, circuit_id); + break; + + case IAS_STRING: + attr_len = tvb_get_guint8(tvb, offset + 1) + 2; + if (iap_conv && iap_conv->pattr_dissector) + iap_conv->pattr_dissector->value_dissector(tvb, offset, pinfo, 0, + n, type, circuit_id); + break; + + default: + attr_len = 0; + } + offset += attr_len; + + n++; + } + } + break; + } + } + + /* If any bytes remain, send it to the generic data dissector */ + tvb = tvb_new_subset_remaining(tvb, offset); + call_data_dissector(tvb, pinfo, root); +} + + +/* + * Check if IAP result is octet sequence + */ +gboolean check_iap_octet_result(tvbuff_t* tvb, proto_tree* tree, guint offset, + const char* attr_name, guint8 attr_type) +{ + if (attr_type != IAS_OCT_SEQ) + { + if (tree) + { + proto_item* ti = proto_tree_add_item(tree, hf_iap_invaloctet, tvb, offset, 0, ENC_NA); + proto_item_append_text(ti, "%s", attr_name); + proto_item_append_text(ti, "\" attribute must be octet sequence!"); + } + + return FALSE; + } + else + return TRUE; +} + + +/* + * Check if IAP result is correct LsapSel + */ +guint8 check_iap_lsap_result(tvbuff_t* tvb, proto_tree* tree, guint offset, + const char* attr_name, guint8 attr_type) +{ + guint32 lsap; + + + if ((attr_type != IAS_INTEGER) || ((lsap = tvb_get_ntohl(tvb, offset)) < 0x01) || + (lsap > 0x6F)) + { + if (tree) + { + proto_item* ti = proto_tree_add_item(tree, hf_iap_invallsap, tvb, offset, 0, ENC_NA); + proto_item_append_text(ti, "%s", attr_name); + proto_item_append_text(ti, "\" attribute must be integer value between 0x01 and 0x6F!"); + } + + return 0; + } + else + return lsap; +} + + +/* + * Dissect IrDA application protocol + */ +static void dissect_appl_proto(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, pdu_type_t pdu_type, guint8 circuit_id) +{ + guint offset = 0; + guint8 src; + address srcaddr; + address destaddr; + conversation_t* conv; + lmp_conversation_t* cur_lmp_conv; + lmp_conversation_t* lmp_conv = NULL; + guint32 num; + + + src = circuit_id ^ CMD_FRAME; + set_address(&srcaddr, irda_address_type, 1, &src); + + set_address(&destaddr, irda_address_type, 1, &circuit_id); + + /* Find result value dissector */ + conv = find_conversation(pinfo->num, &srcaddr, &destaddr, CONVERSATION_NONE, pinfo->srcport, pinfo->destport, 0); + if (conv) + { + num = pinfo->num; + + lmp_conv = (lmp_conversation_t*)conversation_get_proto_data(conv, proto_irlmp); + while (lmp_conv && (lmp_conv->iap_result_frame >= num)) + lmp_conv = lmp_conv->pnext; + + if (lmp_conv) + { + cur_lmp_conv = lmp_conv->pnext; + while (cur_lmp_conv) + { + if ((cur_lmp_conv->iap_result_frame < num) && + (cur_lmp_conv->iap_result_frame > lmp_conv->iap_result_frame)) + { + lmp_conv = cur_lmp_conv; + } + + cur_lmp_conv = cur_lmp_conv->pnext; + } + } + } + + if (lmp_conv) + { +/*ws_message("%x:%d->%x:%d = %p\n", src, pinfo->srcport, circuit_id, pinfo->destport, lmp_conv); */ +/*ws_message("->%d: %d %d %p\n", pinfo->num, lmp_conv->iap_result_frame, lmp_conv->ttp, lmp_conv->proto_dissector); */ + if ((lmp_conv->ttp) && (pdu_type != DISCONNECT_PDU)) + { + offset += dissect_ttp(tvb, pinfo, root, (pdu_type == DATA_PDU)); + + tvb = tvb_new_subset_remaining(tvb, offset); + } + + call_dissector_with_data(lmp_conv->dissector, tvb, pinfo, root, GUINT_TO_POINTER(pdu_type)); + } + else + call_data_dissector(tvb, pinfo, root); +} + + +/* + * Dissect LMP + */ +static void dissect_irlmp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, guint8 circuit_id) +{ + guint offset = 0; + guint8 dlsap; + guint8 slsap; + guint8 cbit; + guint8 opcode = 0; + + + /* Make entries in Protocol column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrLMP"); + + dlsap = tvb_get_guint8(tvb, offset); + cbit = dlsap & CONTROL_BIT; + dlsap &= ~CONTROL_BIT; + + slsap = tvb_get_guint8(tvb, offset+1) & ~CONTROL_BIT; + + /* save Lsaps in pinfo */ + pinfo->srcport = slsap; + pinfo->destport = dlsap; + + if (cbit != 0) + { + opcode = tvb_get_guint8(tvb, offset+2); + + col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d, ", slsap, dlsap); + col_append_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, lmp_opcode_vals, "0x%02X")); + if ((opcode == ACCESSMODE_CMD) || (opcode == ACCESSMODE_CNF)) + { + col_append_str(pinfo->cinfo, COL_INFO, " ("); + col_append_str(pinfo->cinfo, COL_INFO, + val_to_str(tvb_get_guint8(tvb, offset+4), lmp_mode_vals, "0x%02X")); + col_append_str(pinfo->cinfo, COL_INFO, ")"); + } + } + else + col_add_fstr(pinfo->cinfo, COL_INFO, "%d > %d, Len=%d", slsap, dlsap, + tvb_reported_length(tvb) - 2); + + if (root) + { + /* create display subtree for the protocol */ + proto_item* ti = proto_tree_add_item(root, proto_irlmp, tvb, 0, -1, ENC_NA); + proto_tree* tree = proto_item_add_subtree(ti, ett_irlmp); + + proto_tree* dst_tree; + proto_tree* src_tree; + + + ti = proto_tree_add_item(tree, hf_lmp_dst, tvb, offset, 1, ENC_BIG_ENDIAN); + dst_tree = proto_item_add_subtree(ti, ett_lmp_dst); + proto_tree_add_item(dst_tree, hf_lmp_dst_control, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dst_tree, hf_lmp_dst_lsap, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + ti = proto_tree_add_item(tree, hf_lmp_src, tvb, offset, 1, ENC_BIG_ENDIAN); + src_tree = proto_item_add_subtree(ti, ett_lmp_src); + proto_tree_add_item(src_tree, hf_lmp_src_r, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(src_tree, hf_lmp_src_lsap, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + if (cbit != 0) + { + proto_tree_add_item(tree, hf_lmp_opcode, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + switch (opcode) + { + case CONNECT_CMD: + case CONNECT_CNF: + if (offset < tvb_reported_length(tvb)) + { + proto_tree_add_item(tree, hf_lmp_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + } + break; + + case DISCONNECT: + proto_tree_add_item(tree, hf_lmp_reason, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + break; + + case ACCESSMODE_CMD: + proto_tree_add_item(tree, hf_lmp_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item(tree, hf_lmp_mode, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + break; + + case ACCESSMODE_CNF: + proto_tree_add_item( tree, hf_lmp_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item(tree, hf_lmp_mode, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + break; + } + } + + tvb = tvb_new_subset_remaining(tvb, offset); + proto_item_set_len(tree, offset); + } + else + { + offset += 2; + if (cbit != 0) + { + offset += 1; + + switch (opcode) + { + case CONNECT_CMD: + case CONNECT_CNF: + if (offset < tvb_reported_length(tvb)) + offset++; + break; + + case DISCONNECT: + offset++; + break; + + case ACCESSMODE_CMD: + case ACCESSMODE_CNF: + offset += 2; + break; + } + } + + tvb = tvb_new_subset_remaining(tvb, offset); + } + + if (cbit == 0) + { + if (dlsap == LSAP_IAS) + dissect_iap_request(tvb, pinfo, root, circuit_id); + else if (slsap == LSAP_IAS) + dissect_iap_result(tvb, pinfo, root, circuit_id); + else + dissect_appl_proto(tvb, pinfo, root, DATA_PDU, circuit_id); + } + else + { + if ((dlsap == LSAP_IAS) || (slsap == LSAP_IAS)) + call_data_dissector(tvb, pinfo, root); + else + switch (opcode) + { + case CONNECT_CMD: + case CONNECT_CNF: + dissect_appl_proto(tvb, pinfo, root, CONNECT_PDU, circuit_id); + break; + + case DISCONNECT: + dissect_appl_proto(tvb, pinfo, root, DISCONNECT_PDU, circuit_id); + break; + + default: + call_data_dissector(tvb, pinfo, root); + } + } +} + + +/* + * Add LMP conversation + */ +void add_lmp_conversation(packet_info* pinfo, guint8 dlsap, gboolean ttp, dissector_handle_t dissector, guint8 circuit_id) +{ + guint8 dest; + address srcaddr; + address destaddr; + conversation_t* conv; + lmp_conversation_t* lmp_conv = NULL; + + +/*ws_message("%d: add_lmp_conversation(%p, %d, %d, %p) = ", pinfo->num, pinfo, dlsap, ttp, proto_dissector); */ + set_address(&srcaddr, irda_address_type, 1, &circuit_id); + dest = circuit_id ^ CMD_FRAME; + set_address(&destaddr, irda_address_type, 1, &dest); + + conv = find_conversation(pinfo->num, &destaddr, &srcaddr, CONVERSATION_NONE, dlsap, 0, NO_PORT_B); + if (conv) + { + lmp_conv = (lmp_conversation_t*)conversation_get_proto_data(conv, proto_irlmp); + while (1) + { + /* Does entry already exist? */ + if (lmp_conv->iap_result_frame == pinfo->num) + return; + + if (lmp_conv->pnext == NULL) + { + lmp_conv->pnext = wmem_new(wmem_file_scope(), lmp_conversation_t); + lmp_conv = lmp_conv->pnext; + break; + } + lmp_conv = lmp_conv->pnext; + } + } + else + { + conv = conversation_new(pinfo->num, &destaddr, &srcaddr, CONVERSATION_NONE, dlsap, 0, NO_PORT2); + lmp_conv = wmem_new(wmem_file_scope(), lmp_conversation_t); + conversation_add_proto_data(conv, proto_irlmp, (void*)lmp_conv); + } + + lmp_conv->pnext = NULL; + lmp_conv->iap_result_frame = pinfo->num; + lmp_conv->ttp = ttp; + lmp_conv->dissector = dissector; + +/*ws_message("%p\n", lmp_conv); */ +} + + +/* + * Dissect Negotiation Parameters + */ +static guint dissect_negotiation(tvbuff_t* tvb, proto_tree* tree, guint offset) +{ + guint n = 0; + proto_item* ti; + proto_tree* p_tree; + char buf[256]; + guint8 pv; + + while (tvb_reported_length_remaining(tvb, offset) > 0) + { + guint8 p_len = tvb_get_guint8(tvb, offset + 1); + + if (tree) + { + ti = proto_tree_add_item(tree, hf_negotiation_param, tvb, offset, p_len + 2, ENC_NA); + p_tree = proto_item_add_subtree(ti, ett_param[n]); + + pv = tvb_get_guint8(tvb, offset+2); + buf[0] = 0; + + switch (tvb_get_guint8(tvb, offset)) + { + case PI_BAUD_RATE: + proto_item_append_text(ti, ": Baud Rate ("); + + if (pv & 0x01) + (void) g_strlcat(buf, ", 2400", 256); + if (pv & 0x02) + (void) g_strlcat(buf, ", 9600", 256); + if (pv & 0x04) + (void) g_strlcat(buf, ", 19200", 256); + if (pv & 0x08) + (void) g_strlcat(buf, ", 38400", 256); + if (pv & 0x10) + (void) g_strlcat(buf, ", 57600", 256); + if (pv & 0x20) + (void) g_strlcat(buf, ", 115200", 256); + if (pv & 0x40) + (void) g_strlcat(buf, ", 576000", 256); + if (pv & 0x80) + (void) g_strlcat(buf, ", 1152000", 256); + if ((p_len > 1) && (tvb_get_guint8(tvb, offset+3) & 0x01)) + (void) g_strlcat(buf, ", 4000000", 256); + + (void) g_strlcat(buf, " bps)", 256); + + proto_item_append_text(ti, "%s", buf+2); + + break; + + case PI_MAX_TURN_TIME: + proto_item_append_text(ti, ": Maximum Turn Time ("); + + if (pv & 0x01) + (void) g_strlcat(buf, ", 500", 256); + if (pv & 0x02) + (void) g_strlcat(buf, ", 250", 256); + if (pv & 0x04) + (void) g_strlcat(buf, ", 100", 256); + if (pv & 0x08) + (void) g_strlcat(buf, ", 50", 256); + + (void) g_strlcat(buf, " ms)", 256); + + proto_item_append_text(ti, "%s", buf+2); + + break; + + case PI_DATA_SIZE: + proto_item_append_text(ti, ": Data Size ("); + + if (pv & 0x01) + (void) g_strlcat(buf, ", 64", 256); + if (pv & 0x02) + (void) g_strlcat(buf, ", 128", 256); + if (pv & 0x04) + (void) g_strlcat(buf, ", 256", 256); + if (pv & 0x08) + (void) g_strlcat(buf, ", 512", 256); + if (pv & 0x10) + (void) g_strlcat(buf, ", 1024", 256); + if (pv & 0x20) + (void) g_strlcat(buf, ", 2048", 256); + + (void) g_strlcat(buf, " bytes)", 256); + + proto_item_append_text(ti, "%s", buf+2); + + break; + + case PI_WINDOW_SIZE: + proto_item_append_text(ti, ": Window Size ("); + + if (pv & 0x01) + (void) g_strlcat(buf, ", 1", 256); + if (pv & 0x02) + (void) g_strlcat(buf, ", 2", 256); + if (pv & 0x04) + (void) g_strlcat(buf, ", 3", 256); + if (pv & 0x08) + (void) g_strlcat(buf, ", 4", 256); + if (pv & 0x10) + (void) g_strlcat(buf, ", 5", 256); + if (pv & 0x20) + (void) g_strlcat(buf, ", 6", 256); + if (pv & 0x40) + (void) g_strlcat(buf, ", 7", 256); + + (void) g_strlcat(buf, " frame window)", 256); + + proto_item_append_text(ti, "%s", buf+2); + + break; + + case PI_ADD_BOFS: + proto_item_append_text(ti, ": Additional BOFs ("); + + if (pv & 0x01) + (void) g_strlcat(buf, ", 48", 256); + if (pv & 0x02) + (void) g_strlcat(buf, ", 24", 256); + if (pv & 0x04) + (void) g_strlcat(buf, ", 12", 256); + if (pv & 0x08) + (void) g_strlcat(buf, ", 5", 256); + if (pv & 0x10) + (void) g_strlcat(buf, ", 3", 256); + if (pv & 0x20) + (void) g_strlcat(buf, ", 2", 256); + if (pv & 0x40) + (void) g_strlcat(buf, ", 1", 256); + if (pv & 0x80) + (void) g_strlcat(buf, ", 0", 256); + + (void) g_strlcat(buf, " additional BOFs at 115200)", 256); + + proto_item_append_text(ti, "%s", buf+2); + + break; + + case PI_MIN_TURN_TIME: + proto_item_append_text(ti, ": Minimum Turn Time ("); + + if (pv & 0x01) + (void) g_strlcat(buf, ", 10", 256); + if (pv & 0x02) + (void) g_strlcat(buf, ", 5", 256); + if (pv & 0x04) + (void) g_strlcat(buf, ", 1", 256); + if (pv & 0x08) + (void) g_strlcat(buf, ", 0.5", 256); + if (pv & 0x10) + (void) g_strlcat(buf, ", 0.1", 256); + if (pv & 0x20) + (void) g_strlcat(buf, ", 0.05", 256); + if (pv & 0x40) + (void) g_strlcat(buf, ", 0.01", 256); + if (pv & 0x80) + (void) g_strlcat(buf, ", 0", 256); + + (void) g_strlcat(buf, " ms)", 256); + + proto_item_append_text(ti, "%s", buf+2); + + break; + + case PI_LINK_DISC: + proto_item_append_text(ti, ": Link Disconnect/Threshold Time ("); + + if (pv & 0x01) + (void) g_strlcat(buf, ", 3/0", 256); + if (pv & 0x02) + (void) g_strlcat(buf, ", 8/3", 256); + if (pv & 0x04) + (void) g_strlcat(buf, ", 12/3", 256); + if (pv & 0x08) + (void) g_strlcat(buf, ", 16/3", 256); + if (pv & 0x10) + (void) g_strlcat(buf, ", 20/3", 256); + if (pv & 0x20) + (void) g_strlcat(buf, ", 25/3", 256); + if (pv & 0x40) + (void) g_strlcat(buf, ", 30/3", 256); + if (pv & 0x80) + (void) g_strlcat(buf, ", 40/3", 256); + + (void) g_strlcat(buf, " s)", 256); + + proto_item_append_text(ti, "%s", buf+2); + + break; + + default: + proto_item_append_text(ti, ": unknown"); + } + } else + p_tree = NULL; + + offset = dissect_param_tuple(tvb, p_tree, offset); + n++; + } + + return offset; +} + + +/* + * Dissect XID packet + */ +static void dissect_xid(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, proto_tree* lap_tree, gboolean is_command) +{ + int offset = 0; + proto_item* ti = NULL; + proto_tree* i_tree = NULL; + proto_tree* flags_tree; + guint32 saddr, daddr; + guint8 s; + proto_tree* lmp_tree = NULL; + + if (lap_tree) + { + ti = proto_tree_add_item(lap_tree, hf_lap_i, tvb, offset, -1, ENC_NA); + i_tree = proto_item_add_subtree(ti, ett_lap_i); + + proto_tree_add_item(i_tree, hf_xid_ident, tvb, offset, 1, ENC_BIG_ENDIAN); + } + offset++; + + saddr = tvb_get_letohl(tvb, offset); + col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr); + if (lap_tree) + proto_tree_add_uint(i_tree, hf_xid_saddr, tvb, offset, 4, saddr); + offset += 4; + + daddr = tvb_get_letohl(tvb, offset); + col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr); + if (lap_tree) + proto_tree_add_uint(i_tree, hf_xid_daddr, tvb, offset, 4, daddr); + offset += 4; + + if (lap_tree) + { + ti = proto_tree_add_item(i_tree, hf_xid_flags, tvb, offset, 1, ENC_BIG_ENDIAN); + flags_tree = proto_item_add_subtree(ti, ett_xid_flags); + proto_tree_add_item(flags_tree, hf_xid_s, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(flags_tree, hf_xid_conflict, tvb, offset, 1, ENC_BIG_ENDIAN); + } + offset++; + + if (is_command) + { + s = tvb_get_guint8(tvb, offset); + if (s == 0xFF) + col_append_str(pinfo->cinfo, COL_INFO, ", s=final"); + else + col_append_fstr(pinfo->cinfo, COL_INFO, ", s=%u", s); + if (lap_tree) + { + ti = proto_tree_add_uint(i_tree, hf_xid_slotnr, tvb, offset, 1, s); + if (s == 0xFF) + proto_item_append_text(ti, " (final)"); + } + } + offset++; + + if (lap_tree) + proto_tree_add_item(i_tree, hf_xid_version, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + if (lap_tree) + { + proto_item_set_end(lap_tree, tvb, offset); + proto_item_set_end(i_tree, tvb, offset); + } + + if (tvb_reported_length_remaining(tvb, offset) > 0) + { + guint hints_len; + guint8 hint1 = 0; + guint8 hint2 = 0; + + if (root) + { + ti = proto_tree_add_item(root, proto_irlmp, tvb, offset, -1, ENC_NA); + lmp_tree = proto_item_add_subtree(ti, ett_irlmp); + } + + for (hints_len = 0;;) + { + guint8 hint = tvb_get_guint8(tvb, offset + hints_len++); + + if (hints_len == 1) + hint1 = hint; + else if (hints_len == 2) + hint2 = hint; + + if ((hint & 0x80) == 0) + break; + } + + if (root) + { + ti = proto_tree_add_item(lmp_tree, hf_lmp_xid_hints, tvb, offset, hints_len, ENC_NA); + if ((hint1 | hint2) != 0) + { + char service_hints[256]; + + service_hints[0] = 0; + + if (hint1 & 0x01) + (void) g_strlcat(service_hints, ", PnP Compatible", 256); + if (hint1 & 0x02) + (void) g_strlcat(service_hints, ", PDA/Palmtop", 256); + if (hint1 & 0x04) + (void) g_strlcat(service_hints, ", Computer", 256); + if (hint1 & 0x08) + (void) g_strlcat(service_hints, ", Printer", 256); + if (hint1 & 0x10) + (void) g_strlcat(service_hints, ", Modem", 256); + if (hint1 & 0x20) + (void) g_strlcat(service_hints, ", Fax", 256); + if (hint1 & 0x40) + (void) g_strlcat(service_hints, ", LAN Access", 256); + if (hint2 & 0x01) + (void) g_strlcat(service_hints, ", Telephony", 256); + if (hint2 & 0x02) + (void) g_strlcat(service_hints, ", File Server", 256); + if (hint2 & 0x04) + (void) g_strlcat(service_hints, ", IrCOMM", 256); + if (hint2 & 0x20) + (void) g_strlcat(service_hints, ", OBEX", 256); + + (void) g_strlcat(service_hints, ")", 256); + service_hints[0] = ' '; + service_hints[1] = '('; + + proto_item_append_text(ti, "%s", service_hints); + } + } + offset += hints_len; + + if (tvb_reported_length_remaining(tvb, offset) > 0) + { + guint8 cset; + gint name_len; + gchar *name; + gboolean have_encoding; + guint encoding; + + cset = tvb_get_guint8(tvb, offset); + if (root) + proto_tree_add_uint(lmp_tree, hf_lmp_xid_charset, tvb, offset, 1, cset); + offset++; + name_len = tvb_reported_length_remaining(tvb, offset); + if (name_len > 0) + { + switch (cset) { + + case LMP_CHARSET_ASCII: + encoding = ENC_ASCII|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_1: + encoding = ENC_ISO_8859_1|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_2: + encoding = ENC_ISO_8859_2|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_3: + encoding = ENC_ISO_8859_3|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_4: + encoding = ENC_ISO_8859_4|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_5: + encoding = ENC_ISO_8859_5|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_6: + encoding = ENC_ISO_8859_6|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_7: + encoding = ENC_ISO_8859_7|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_8: + encoding = ENC_ISO_8859_8|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_ISO_8859_9: + encoding = ENC_ISO_8859_9|ENC_NA; + have_encoding = TRUE; + break; + + case LMP_CHARSET_UNICODE: + /* Presumably big-endian; assume just UCS-2 for now */ + encoding = ENC_UCS_2|ENC_BIG_ENDIAN; + have_encoding = TRUE; + break; + + default: + encoding = 0; + have_encoding = FALSE; + break; + } + + if (have_encoding) + { + name = (gchar *) tvb_get_string_enc(pinfo->pool, tvb, offset, name_len, encoding); + col_append_fstr(pinfo->cinfo, COL_INFO, ", \"%s\"", format_text(pinfo->pool, (guchar *) name, strlen(name))); + if (root) + proto_tree_add_item(lmp_tree, hf_lmp_xid_name, tvb, offset, + -1, encoding); + } + else + { + if (root) + proto_tree_add_item(lmp_tree, hf_lmp_xid_name_no_encoding, tvb, offset, + -1, ENC_NA); + } + } + } + } +} + + +/* + * Dissect Log Messages + */ +static void dissect_log(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root) +{ + /* Make entries in Protocol column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "Log"); + + /* missed messages? */ + if (pinfo->pseudo_header->irda.pkttype == IRDA_MISSED_MSG) + { + col_set_str(pinfo->cinfo, COL_INFO, "WARNING: Missed one or more messages while capturing!"); + } + else + { + guint length; + char *buf; + + length = tvb_captured_length(tvb); + buf = (char *) tvb_get_string_enc(pinfo->pool, tvb, 0, length, ENC_ASCII|ENC_NA); + if (length > 0 && buf[length-1] == '\n') + buf[length-1] = 0; + else if (length > 1 && buf[length-2] == '\n') + buf[length-2] = 0; + + col_add_str(pinfo->cinfo, COL_INFO, format_text(pinfo->pool, (guchar *) buf, strlen(buf))); + } + + if (root) + { + proto_item* ti = proto_tree_add_item(root, proto_log, tvb, 0, -1, ENC_NA); + proto_tree* tree = proto_item_add_subtree(ti, ett_log); + + if (pinfo->pseudo_header->irda.pkttype == IRDA_MISSED_MSG) + proto_tree_add_item(tree, hf_log_missed, tvb, 0, 0, ENC_NA); + else + proto_tree_add_item(tree, hf_log_msg, tvb, 0, -1, ENC_ASCII|ENC_NA); + } +} + + +/* + * Dissect IrLAP + */ +static void dissect_irlap(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root) +{ + int offset = 0; + guint8 circuit_id, c; + gboolean is_response; + char addr[9]; + proto_item* ti = NULL; + proto_tree* tree = NULL; + proto_tree* i_tree = NULL; + guint32 saddr, daddr; + guint8 ca; + + /* Make entries in Protocol column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IrLAP"); + + /* Clear Info column */ + col_clear(pinfo->cinfo, COL_INFO); + + /* set direction column */ + switch (pinfo->pseudo_header->irda.pkttype) + { + case IRDA_OUTGOING: + col_set_str(pinfo->cinfo, COL_IF_DIR, "Out"); + break; + + case IRDA_INCOMING: + col_set_str(pinfo->cinfo, COL_IF_DIR, "In"); + break; + } + + /* decode values used for demuxing */ + circuit_id = tvb_get_guint8(tvb, 0); + + /* initially set address columns to connection address */ + snprintf(addr, sizeof(addr)-1, "0x%02X", circuit_id >> 1); + col_add_str(pinfo->cinfo, COL_DEF_SRC, addr); + col_add_str(pinfo->cinfo, COL_DEF_DST, addr); + + if (root) + { + proto_tree* a_tree; + proto_item* addr_item; + + /* create display subtree for the protocol */ + ti = proto_tree_add_item(root, proto_irlap, tvb, 0, -1, ENC_NA); + tree = proto_item_add_subtree(ti, ett_irlap); + + /* create subtree for the address field */ + ti = proto_tree_add_item(tree, hf_lap_a, tvb, offset, 1, ENC_BIG_ENDIAN); + a_tree = proto_item_add_subtree(ti, ett_lap_a); + proto_tree_add_item(a_tree, hf_lap_a_cr, tvb, offset, 1, ENC_BIG_ENDIAN); + addr_item = proto_tree_add_item(a_tree, hf_lap_a_address, tvb, offset, 1, ENC_BIG_ENDIAN); + switch (circuit_id & ~CMD_FRAME) + { + case 0: + proto_item_append_text(addr_item, " (NULL Address)"); + break; + case 0xFE: + proto_item_append_text(addr_item, " (Broadcast)"); + break; + } + } + is_response = ((circuit_id & CMD_FRAME) == 0); + offset++; + + /* process the control field */ + c = dissect_xdlc_control(tvb, 1, pinfo, tree, hf_lap_c, + ett_lap_c, &irlap_cf_items, NULL, lap_c_u_cmd_abbr_vals, + lap_c_u_rsp_abbr_vals, is_response, FALSE, FALSE); + offset++; + + if ((c & XDLC_I_MASK) == XDLC_I) { + /* I frame */ + proto_item_set_len(tree, offset); + tvb = tvb_new_subset_remaining(tvb, offset); + dissect_irlmp(tvb, pinfo, root, circuit_id); + return; + } + + if ((c & XDLC_S_U_MASK) == XDLC_U) { + /* U frame */ + switch (c & XDLC_U_MODIFIER_MASK) + { + case XDLC_SNRM: + if (root) + { + ti = proto_tree_add_item(tree, hf_lap_i, tvb, offset, -1, ENC_NA); + i_tree = proto_item_add_subtree(ti, ett_lap_i); + } + + saddr = tvb_get_letohl(tvb, offset); + if (!is_response) + { + col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr); + } + if (root) + proto_tree_add_uint(i_tree, hf_snrm_saddr, tvb, offset, 4, saddr); + offset += 4; + + daddr = tvb_get_letohl(tvb, offset); + if (!is_response) + { + col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr); + } + if (root) + proto_tree_add_uint(i_tree, hf_snrm_daddr, tvb, offset, 4, daddr); + offset += 4; + + ca = tvb_get_guint8(tvb, offset); + if (!is_response) + { + col_append_fstr(pinfo->cinfo, COL_INFO, ", ca=0x%02X", + ca >> 1); + } + if (root) + proto_tree_add_uint(i_tree, hf_snrm_ca, tvb, offset, 1, ca >> 1); + offset++; + + offset = dissect_negotiation(tvb, i_tree, offset); + if (root) + proto_item_set_end(ti, tvb, offset); + break; + + case IRDA_XID_CMD: + tvb = tvb_new_subset_remaining(tvb, offset); + dissect_xid(tvb, pinfo, root, tree, TRUE); + return; + + case XDLC_UA: + if (tvb_reported_length_remaining(tvb, offset) > 0) + { + if (root) + { + ti = proto_tree_add_item(tree, hf_lap_i, tvb, offset, -1, ENC_NA); + i_tree = proto_item_add_subtree(ti, ett_lap_i); + } + + saddr = tvb_get_letohl(tvb, offset); + col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "0x%08X", saddr); + if (root) + proto_tree_add_uint(i_tree, hf_ua_saddr, tvb, offset, 4, saddr); + offset += 4; + + daddr = tvb_get_letohl(tvb, offset); + col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%08X", daddr); + if (root) + proto_tree_add_uint(i_tree, hf_ua_daddr, tvb, offset, 4, daddr); + offset += 4; + + offset = dissect_negotiation(tvb, i_tree, offset); + if (root) + proto_item_set_end(ti, tvb, offset); + } + break; + + case XDLC_XID: + tvb = tvb_new_subset_remaining(tvb, offset); + dissect_xid(tvb, pinfo, root, tree, FALSE); + return; + } + } + + /* If any bytes remain, send it to the generic data dissector */ + if (tvb_reported_length_remaining(tvb, offset) > 0) + { + tvb = tvb_new_subset_remaining(tvb, offset); + call_data_dissector(tvb, pinfo, root); + } +} + + +/* + * Dissect IrDA protocol + */ +static int dissect_irda(tvbuff_t* tvb, packet_info* pinfo, proto_tree* root, void* data _U_) +{ + /* check if log message */ + if ((pinfo->pseudo_header->irda.pkttype & IRDA_CLASS_MASK) == IRDA_CLASS_LOG) + { + dissect_log(tvb, pinfo, root); + return tvb_captured_length(tvb); + } + + + dissect_irlap(tvb, pinfo, root); + return tvb_captured_length(tvb); +} + +static int irda_addr_to_str(const address* addr, gchar *buf, int buf_len _U_) +{ + const guint8 *addrdata = (const guint8 *)addr->data; + + guint32_to_str_buf(*addrdata, buf, buf_len); + return (int)strlen(buf); +} + +static int irda_addr_str_len(const address* addr _U_) +{ + return 11; /* Leaves required space (10 bytes) for uint_to_str_back() */ +} + +static const char* irda_col_filter_str(const address* addr _U_, gboolean is_src _U_) +{ + return "irlap.a"; +} + +static int irda_addr_len(void) +{ + return 1; +} + +/* + * Register the protocol with Wireshark + * This format is required because a script is used to build the C function + * that calls all the protocol registrations. + */ +void proto_register_irda(void) +{ + guint i; + + /* Setup list of header fields */ + static hf_register_info hf_lap[] = { + { &hf_lap_a, + { "Address Field", "irlap.a", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_lap_a_cr, + { "C/R", "irlap.a.cr", + FT_BOOLEAN, 8, TFS(&lap_cr_vals), CMD_FRAME, + NULL, HFILL }}, + { &hf_lap_a_address, + { "Address", "irlap.a.address", + FT_UINT8, BASE_HEX, NULL, ~CMD_FRAME, + NULL, HFILL }}, + { &hf_lap_c, + { "Control Field", "irlap.c", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_lap_c_nr, + { "N(R)", "irlap.c.n_r", + FT_UINT8, BASE_DEC, NULL, XDLC_N_R_MASK, + NULL, HFILL }}, + { &hf_lap_c_ns, + { "N(S)", "irlap.c.n_s", + FT_UINT8, BASE_DEC, NULL, XDLC_N_S_MASK, + NULL, HFILL }}, + { &hf_lap_c_p, + { "Poll", "irlap.c.p", + FT_BOOLEAN, 8, TFS(&set_notset), XDLC_P_F, + NULL, HFILL }}, + { &hf_lap_c_f, + { "Final", "irlap.c.f", + FT_BOOLEAN, 8, TFS(&set_notset), XDLC_P_F, + NULL, HFILL }}, + { &hf_lap_c_s, + { "Supervisory frame type", "irlap.c.s_ftype", + FT_UINT8, BASE_HEX, VALS(lap_c_s_vals), XDLC_S_FTYPE_MASK, + NULL, HFILL }}, + { &hf_lap_c_u_cmd, + { "Command", "irlap.c.u_modifier_cmd", + FT_UINT8, BASE_HEX, VALS(lap_c_u_cmd_vals), XDLC_U_MODIFIER_MASK, + NULL, HFILL }}, + { &hf_lap_c_u_rsp, + { "Response", "irlap.c.u_modifier_resp", + FT_UINT8, BASE_HEX, VALS(lap_c_u_rsp_vals), XDLC_U_MODIFIER_MASK, + NULL, HFILL }}, + { &hf_lap_c_i, + { "Frame Type", "irlap.c.ftype", + FT_UINT8, BASE_HEX, VALS(lap_c_ftype_vals), XDLC_I_MASK, + NULL, HFILL }}, + { &hf_lap_c_s_u, + { "Frame Type", "irlap.c.ftype", + FT_UINT8, BASE_HEX, VALS(lap_c_ftype_vals), XDLC_S_U_MASK, + NULL, HFILL }}, + { &hf_lap_i, + { "Information Field", "irlap.i", + FT_NONE, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_snrm_saddr, + { "Source Device Address", "irlap.snrm.saddr", + FT_UINT32, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_snrm_daddr, + { "Destination Device Address", "irlap.snrm.daddr", + FT_UINT32, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_snrm_ca, + { "Connection Address", "irlap.snrm.ca", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_negotiation_param, + { "Negotiation Parameter", "irlap.negotiation", + FT_NONE, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_param_pi, + { "Parameter Identifier", "irlap.pi", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_param_pl, + { "Parameter Length", "irlap.pl", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_param_pv, + { "Parameter Value", "irlap.pv", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_ua_saddr, + { "Source Device Address", "irlap.ua.saddr", + FT_UINT32, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_ua_daddr, + { "Destination Device Address", "irlap.ua.daddr", + FT_UINT32, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_xid_ident, + { "Format Identifier", "irlap.xid.fi", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_xid_saddr, + { "Source Device Address", "irlap.xid.saddr", + FT_UINT32, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_xid_daddr, + { "Destination Device Address", "irlap.xid.daddr", + FT_UINT32, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_xid_flags, + { "Discovery Flags", "irlap.xid.flags", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_xid_s, + { "Number of Slots", "irlap.xid.s", + FT_UINT8, BASE_DEC, VALS(xid_slot_numbers), S_MASK, + NULL, HFILL }}, + { &hf_xid_conflict, + { "Conflict", "irlap.xid.conflict", + FT_BOOLEAN, 8, TFS(&set_notset), CONFLICT, + NULL, HFILL }}, + { &hf_xid_slotnr, + { "Slot Number", "irlap.xid.slotnr", + FT_UINT8, BASE_DEC, NULL, 0, + NULL, HFILL }}, + { &hf_xid_version, + { "Version Number", "irlap.xid.version", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }} + }; + + static hf_register_info hf_log[] = { + { &hf_log_msg, + { "Message", "log.msg", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_log_missed, + { "WARNING: Missed one or more messages while capturing!", "log.missed", + FT_NONE, BASE_NONE, NULL, 0, + NULL, HFILL }} + }; + + static hf_register_info hf_lmp[] = { + { &hf_lmp_xid_hints, + { "Service Hints", "irlmp.xid.hints", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_lmp_xid_charset, + { "Character Set", "irlmp.xid.charset", + FT_UINT8, BASE_HEX, VALS(lmp_charset_vals), 0, + NULL, HFILL }}, + { &hf_lmp_xid_name, + { "Device Nickname", "irlmp.xid.name", + FT_STRING, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_lmp_xid_name_no_encoding, + { "Device Nickname (unsupported character set)", "irlmp.xid.name.no_encoding", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_lmp_dst, + { "Destination", "irlmp.dst", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_lmp_dst_control, + { "Control Bit", "irlmp.dst.c", + FT_BOOLEAN, 8, TFS(&set_notset), CONTROL_BIT, + NULL, HFILL }}, + { &hf_lmp_dst_lsap, + { "Destination LSAP", "irlmp.dst.lsap", + FT_UINT8, BASE_DEC, NULL, ~CONTROL_BIT, + NULL, HFILL }}, + { &hf_lmp_src, + { "Source", "irlmp.src", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_lmp_src_r, + { "reserved", "irlmp.src.r", + FT_UINT8, BASE_DEC, NULL, RESERVED_BIT, + NULL, HFILL }}, + { &hf_lmp_src_lsap, + { "Source LSAP", "irlmp.src.lsap", + FT_UINT8, BASE_DEC, NULL, ~RESERVED_BIT, + NULL, HFILL }}, + { &hf_lmp_opcode, + { "Opcode", "irlmp.opcode", + FT_UINT8, BASE_HEX, VALS(lmp_opcode_vals), 0x0, + NULL, HFILL }}, + { &hf_lmp_rsvd, + { "Reserved", "irlmp.rsvd", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_lmp_reason, + { "Reason", "irlmp.reason", + FT_UINT8, BASE_HEX, VALS(lmp_reason_vals), 0x0, + NULL, HFILL }}, + { &hf_lmp_mode, + { "Mode", "irlmp.mode", + FT_UINT8, BASE_HEX, VALS(lmp_mode_vals), 0x0, + NULL, HFILL }}, + { &hf_lmp_status, + { "Status", "irlmp.status", + FT_UINT8, BASE_HEX, VALS(lmp_status_vals), 0x0, + NULL, HFILL }} + }; + + static hf_register_info hf_iap[] = { + { &hf_iap_ctl, + { "Control Field", "iap.ctl", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_iap_ctl_lst, + { "Last Frame", "iap.ctl.lst", + FT_BOOLEAN, 8, TFS(&set_notset), IAP_LST, + NULL, HFILL }}, + { &hf_iap_ctl_ack, + { "Acknowledge", "iap.ctl.ack", + FT_BOOLEAN, 8, TFS(&set_notset), IAP_ACK, + NULL, HFILL }}, + { &hf_iap_ctl_opcode, + { "Opcode", "iap.ctl.opcode", + FT_UINT8, BASE_HEX, VALS(iap_opcode_vals), IAP_OP, + NULL, HFILL }}, + { &hf_iap_class_name, + { "Class Name", "iap.classname", + FT_UINT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_attr_name, + { "Attribute Name", "iap.attrname", + FT_UINT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_return, + { "Return", "iap.return", + FT_UINT8, BASE_HEX, VALS(iap_return_vals), 0x0, + NULL, HFILL }}, + { &hf_iap_list_len, + { "List Length", "iap.listlen", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_list_entry, + { "List Entry", "iap.listentry", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_obj_id, + { "Object Identifier", "iap.objectid", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_attr_type, + { "Type", "iap.attrtype", + FT_UINT8, BASE_DEC, VALS(iap_attr_type_vals), 0x0, + NULL, HFILL }}, + { &hf_iap_int, + { "Value", "iap.int", + FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_seq_len, + { "Sequence Length", "iap.seqlen", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_oct_seq, + { "Sequence", "iap.octseq", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_char_set, + { "Character Set", "iap.charset", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_string, + { "String", "iap.string", + FT_UINT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_iap_invaloctet, + { "Malformed IAP result: \"", "iap.invaloctet", + FT_NONE, BASE_NONE, NULL, 0, + NULL, HFILL }}, + { &hf_iap_invallsap, + { "Malformed IAP result: \"", "iap.invallsap", + FT_NONE, BASE_NONE, NULL, 0, + NULL, HFILL }} + }; + + static hf_register_info hf_ttp[] = { + { &hf_ttp_p, + { "Parameter Bit", "ttp.p", + FT_BOOLEAN, 8, TFS(&set_notset), TTP_PARAMETERS, + NULL, HFILL }}, + { &hf_ttp_icredit, + { "Initial Credit", "ttp.icredit", + FT_UINT8, BASE_DEC, NULL, ~TTP_PARAMETERS, + NULL, HFILL }}, + { &hf_ttp_m, + { "More Bit", "ttp.m", + FT_BOOLEAN, 8, TFS(&set_notset), TTP_MORE, + NULL, HFILL }}, + { &hf_ttp_dcredit, + { "Delta Credit", "ttp.dcredit", + FT_UINT8, BASE_DEC, NULL, ~TTP_MORE, + NULL, HFILL }} + }; + + /* Setup protocol subtree arrays */ + static gint* ett[] = { + &ett_irlap, + &ett_lap_a, + &ett_lap_c, + &ett_lap_i, + &ett_xid_flags, + &ett_log, + &ett_irlmp, + &ett_lmp_dst, + &ett_lmp_src, + &ett_iap, + &ett_iap_ctl, + &ett_ttp + }; + + gint* ett_p[MAX_PARAMETERS]; + gint* ett_iap_e[MAX_IAP_ENTRIES]; + + + /* Register protocol names and descriptions */ + proto_irlap = proto_register_protocol("IrDA Link Access Protocol", "IrLAP", "irlap"); + proto_log = proto_register_protocol("Log Message", "Log", "log"); + proto_irlmp = proto_register_protocol("IrDA Link Management Protocol", "IrLMP", "irlmp"); + proto_iap = proto_register_protocol("Information Access Protocol", "IAP", "iap"); + proto_ttp = proto_register_protocol("Tiny Transport Protocol", "TTP", "ttp"); + + /* Register the dissector */ + irda_handle = register_dissector("irda", dissect_irda, proto_irlap); + + /* Required function calls to register the header fields */ + proto_register_field_array(proto_irlap, hf_lap, array_length(hf_lap)); + proto_register_field_array(proto_log, hf_log, array_length(hf_log)); + proto_register_field_array(proto_irlmp, hf_lmp, array_length(hf_lmp)); + proto_register_field_array(proto_iap, hf_iap, array_length(hf_iap)); + proto_register_field_array(proto_ttp, hf_ttp, array_length(hf_ttp)); + + /* Register subtrees */ + proto_register_subtree_array(ett, array_length(ett)); + for (i = 0; i < MAX_PARAMETERS; i++) + { + ett_param[i] = -1; + ett_p[i] = &ett_param[i]; + } + proto_register_subtree_array(ett_p, MAX_PARAMETERS); + for (i = 0; i < MAX_IAP_ENTRIES; i++) + { + ett_iap_entry[i] = -1; + ett_iap_e[i] = &ett_iap_entry[i]; + } + proto_register_subtree_array(ett_iap_e, MAX_IAP_ENTRIES); + + irda_address_type = address_type_dissector_register("AT_IRDA", "IRDA Address", irda_addr_to_str, irda_addr_str_len, NULL, irda_col_filter_str, irda_addr_len, NULL, NULL); +} + + +/* If this dissector uses sub-dissector registration add a registration routine. + This format is required because a script is used to find these routines and + create the code that calls these routines. +*/ + +void proto_reg_handoff_irda(void) +{ + dissector_add_uint("wtap_encap", WTAP_ENCAP_IRDA, irda_handle); + dissector_add_uint("sll.ltype", LINUX_SLL_P_IRDA_LAP, irda_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/irda/packet-sir.c b/plugins/epan/irda/packet-sir.c new file mode 100644 index 00000000..71b0e837 --- /dev/null +++ b/plugins/epan/irda/packet-sir.c @@ -0,0 +1,236 @@ +/** Decode IrDA Serial Infrared (SIR) wrapped packets. + * @author Shaun Jackman + * @copyright Copyright 2004 Shaun Jackman + * @license GPL + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include +#include + +/** Serial infrared port. */ +#define TCP_PORT_SIR 6417 /* Not IANA registered */ + + +/** Beginning of frame. */ +#define SIR_BOF 0xc0 + +/** End of frame. */ +#define SIR_EOF 0xc1 + +/** Control escape. */ +#define SIR_CE 0x7d + +/** Escapes this character. */ +#define SIR_ESCAPE(x) ((x)^0x20) + +void proto_reg_handoff_irsir(void); +void proto_register_irsir(void); + +/** Protocol handles. */ +static dissector_handle_t irda_handle; +static dissector_handle_t sir_handle; + +/** Protocol fields. */ +static int proto_sir = -1; +static int ett_sir = -1; +static int hf_sir_bof = -1; +/* static int hf_sir_ce = -1; */ +static int hf_sir_eof = -1; +static int hf_sir_fcs = -1; +static int hf_sir_fcs_status = -1; +static int hf_sir_length = -1; +static int hf_sir_preamble = -1; + +static expert_field ei_sir_fcs = EI_INIT; + +/* Copied and renamed from proto.c because global value_strings don't work for plugins */ +static const value_string plugin_proto_checksum_vals[] = { + { PROTO_CHECKSUM_E_BAD, "Bad" }, + { PROTO_CHECKSUM_E_GOOD, "Good" }, + { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" }, + { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" }, + + { 0, NULL } +}; + + +/** Unescapes the data. */ +static tvbuff_t * +unescape_data(tvbuff_t *tvb, packet_info *pinfo) +{ + if (tvb_find_guint8(tvb, 0, -1, SIR_CE) == -1) { + return tvb; + } else { + guint length = tvb_captured_length(tvb); + guint offset; + guint8 *data = (guint8 *)wmem_alloc(pinfo->pool, length); + guint8 *dst = data; + tvbuff_t *next_tvb; + + for (offset = 0; offset < length; ) + { + guint8 c = tvb_get_guint8(tvb, offset++); + if ((c == SIR_CE) && (offset < length)) + c = SIR_ESCAPE(tvb_get_guint8(tvb, offset++)); + *dst++ = c; + } + + next_tvb = tvb_new_child_real_data(tvb, data, (guint) (dst-data), (guint) (dst-data)); + add_new_data_source(pinfo, next_tvb, "Unescaped SIR"); + return next_tvb; + } +} + + +/** Checksums the data. */ +static tvbuff_t * +checksum_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + int len = tvb_reported_length(tvb) - 2; + if (len < 0) + return tvb; + + proto_tree_add_checksum(tree, tvb, len, hf_sir_fcs, hf_sir_fcs_status, &ei_sir_fcs, pinfo, crc16_ccitt_tvb(tvb, len), + ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY); + + return tvb_new_subset_length(tvb, 0, len); +} + + +/** Dissects an SIR packet. */ +static int +dissect_sir(tvbuff_t *tvb, packet_info *pinfo, proto_tree *root, void* data _U_) +{ + gint offset = 0; + gint bof_offset; + gint eof_offset; + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + bof_offset = tvb_find_guint8(tvb, offset, -1, SIR_BOF); + eof_offset = (bof_offset == -1) ? -1 : + tvb_find_guint8(tvb, bof_offset, -1, SIR_EOF); + + if (bof_offset == -1 || eof_offset == -1) { + if (pinfo->can_desegment) { + pinfo->desegment_offset = offset; + pinfo->desegment_len = 1; + } + return tvb_captured_length(tvb); + } else { + guint preamble_len = bof_offset - offset; + gint data_offset = bof_offset + 1; + tvbuff_t* next_tvb = tvb_new_subset_length_caplen(tvb, + data_offset, eof_offset - data_offset, -1); + next_tvb = unescape_data(next_tvb, pinfo); + if (root) { + guint data_len = tvb_reported_length(next_tvb) < 2 ? 0 : + tvb_reported_length(next_tvb) - 2; + proto_tree* ti = proto_tree_add_protocol_format(root, + proto_sir, tvb, offset, eof_offset - offset + 1, + "Serial Infrared, Len: %d", data_len); + proto_tree* tree = proto_item_add_subtree(ti, ett_sir); + if (preamble_len > 0) + proto_tree_add_item(tree, hf_sir_preamble, tvb, + offset, preamble_len, ENC_NA); + proto_tree_add_item(tree, hf_sir_bof, tvb, + bof_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_uint(tree, hf_sir_length, + next_tvb, 0, data_len, data_len); + next_tvb = checksum_data(next_tvb, pinfo, tree); + proto_tree_add_item(tree, hf_sir_eof, tvb, + eof_offset, 1, ENC_BIG_ENDIAN); + } else { + next_tvb = checksum_data(next_tvb, pinfo, NULL); + } + call_dissector(irda_handle, next_tvb, pinfo, root); + } + offset = eof_offset + 1; + } + return tvb_captured_length(tvb); +} + + +/** Registers this dissector with the parent dissector. */ +void +proto_reg_handoff_irsir(void) +{ + dissector_add_uint_with_preference("tcp.port", TCP_PORT_SIR, sir_handle); + + irda_handle = find_dissector("irda"); +} + + +/** Initializes this protocol. */ +void +proto_register_irsir(void) +{ + static gint* ett[] = { &ett_sir }; + + static hf_register_info hf_sir[] = { + { &hf_sir_bof, + { "Beginning of frame", "sir.bof", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, +#if 0 + { &hf_sir_ce, + { "Command escape", "sir.ce", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, +#endif + { &hf_sir_eof, + { "End of frame", "sir.eof", + FT_UINT8, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_sir_fcs, + { "Frame check sequence", "sir.fcs", + FT_UINT16, BASE_HEX, NULL, 0, + NULL, HFILL }}, + { &hf_sir_fcs_status, + { "Frame check sequence Status", "sir.fcs.status", + FT_UINT8, BASE_NONE, VALS(plugin_proto_checksum_vals), 0x0, + NULL, HFILL }}, + { &hf_sir_length, + { "Length", "sir.length", + FT_UINT16, BASE_DEC, NULL, 0, + NULL, HFILL }}, + { &hf_sir_preamble, + { "Preamble", "sir.preamble", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL }} + }; + + static ei_register_info ei[] = { + { &ei_sir_fcs, { "sir.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, + }; + + expert_module_t* expert_sir; + + proto_sir = proto_register_protocol("Serial Infrared", "SIR", "sir"); + sir_handle = register_dissector("sir", dissect_sir, proto_sir); + proto_register_subtree_array(ett, array_length(ett)); + proto_register_field_array( proto_sir, hf_sir, array_length(hf_sir)); + expert_sir = expert_register_protocol(proto_sir); + expert_register_field_array(expert_sir, ei, array_length(ei)); +} + +/* + * 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: + */ diff --git a/plugins/epan/mate/.editorconfig b/plugins/epan/mate/.editorconfig new file mode 100644 index 00000000..2ee8bf0b --- /dev/null +++ b/plugins/epan/mate/.editorconfig @@ -0,0 +1,3 @@ +[mate_grammar.lemon] +indent_style = tab +indent_size = tab diff --git a/plugins/epan/mate/AUTHORS b/plugins/epan/mate/AUTHORS new file mode 100644 index 00000000..e37df0dd --- /dev/null +++ b/plugins/epan/mate/AUTHORS @@ -0,0 +1,3 @@ +Author: +Luis E. Garcia Ontanon + diff --git a/plugins/epan/mate/CMakeLists.txt b/plugins/epan/mate/CMakeLists.txt new file mode 100644 index 00000000..62b6c090 --- /dev/null +++ b/plugins/epan/mate/CMakeLists.txt @@ -0,0 +1,85 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(mate 1 0 1 0) + +set(DISSECTOR_SRC + packet-mate.c +) + +set(DISSECTOR_SUPPORT_SRC + mate_setup.c + mate_runtime.c + mate_util.c +) + +add_lemon_files(LEMON_FILES GENERATED_FILES + mate_grammar.lemon +) +add_lex_files(LEX_FILES GENERATED_FILES + mate_parser.l +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} + ${GENERATED_FILES} +) + +set_source_files_properties( + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +add_wireshark_plugin_library(mate epan) + +target_link_libraries(mate epan) + +install_plugin(mate epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + mate + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} + ${DISSECTOR_HEADERS} +# LEX files commented out due to use of malloc, free etc. +# ${LEX_FILES} + ${LEMON_FILES} +) + +# +# 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: +# diff --git a/plugins/epan/mate/examples/call.mate b/plugins/epan/mate/examples/call.mate new file mode 100644 index 00000000..0dbbb45e --- /dev/null +++ b/plugins/epan/mate/examples/call.mate @@ -0,0 +1,34 @@ +# call.mate + +Action=Settings; DiscardPduData=TRUE; ShowGopTimes=FALSE; ShowPduTree=FALSE; + +Action=PduDef; Name=q931_pdu; Proto=q931; Stop=TRUE; Transport=tcp/ip; addr=ip.addr; call_ref=q931.call_ref; q931_msg=q931.message_type; +Action=PduDef; Name=ras_pdu; Proto=h225.RasMessage; Transport=udp/ip; addr=ip.addr; ras_sn=h225.requestSeqNum; ras_msg=h225.RasMessage; +Action=PduDef; Name=isup_pdu; Proto=isup; Transport=mtp3; m3pc=mtp3.dpc; m3pc=mtp3.opc; cic=isup.cic; isup_msg=isup.message_type; + +Action=PduExtra; For=q931_pdu; guid=h225.guid; calling=q931.calling_party_number.digits; q931_cause=q931.cause_value; +Action=PduExtra; For=isup_pdu; calling=isup.calling; isup_cause=isup.cause_indicator; +Action=PduExtra; For=ras_pdu; guid=h225.guid; + +Action=GopDef; Name=q931_leg; On=q931_pdu; addr; addr; call_ref; +Action=GopStart; For=q931_leg; q931_msg=5; +Action=GopStop; For=q931_leg; q931_msg=90; +Action=GopExtra; For=q931_leg; calling; q931_cause; guid; + +Action=GopDef; Name=isup_leg; On=isup_pdu; ShowPduTree=TRUE; ShowGopTimes=TRUE; m3pc; m3pc; cic; +Action=GopStart; For=isup_leg; isup_msg=1; +Action=GopStop; For=isup_leg; isup_msg=16; +Action=GopExtra; For=isup_leg; calling; isup_cause; + +Action=GopDef; Name=ras_leg; On=ras_pdu; addr; addr; ras_sn; +Action=GopStart; For=ras_leg; ras_msg|0|3|6|9|12|15|18|21|26|30; +Action=GopStop; For=ras_leg; ras_msg|1|2|4|5|7|8|10|11|13|14|16|17|19|20|22|24|27|28|29|31; +Action=GopExtra; For=ras_leg; guid; + +Action=GogDef; Name=call; GogExpiration=0.75; +Action=GogKey; For=call; On=isup_leg; calling; +Action=GogKey; For=call; On=q931_leg; calling; +Action=GogKey; For=call; On=q931_leg; guid; +Action=GogKey; For=call; On=ras_leg; guid; +Action=GogExtra; For=call; isup_cause; +Action=GogExtra; For=call; q931_cause; diff --git a/plugins/epan/mate/examples/mms.mate b/plugins/epan/mate/examples/mms.mate new file mode 100644 index 00000000..7554b119 --- /dev/null +++ b/plugins/epan/mate/examples/mms.mate @@ -0,0 +1,40 @@ +# mms.mate + +# MMSE over HTTP +Action=PduDef; Name=mmse_over_http_pdu; Proto=http; Transport=tcp/ip; Payload=mmse; addr=ip.addr; port=tcp.port; http_rq=http.request; content=http.content_type; +Action=PduExtra; For=mmse_over_http_pdu; resp=http.response.code; method=http.request.method; host=http.host; content=http.content_type; +Action=PduExtra; For=mmse_over_http_pdu; method=http.request.method; host=http.host; +Action=PduExtra; For=mmse_over_http_pdu; trx=mmse.transaction_id; msg_type=mmse.message_type; notify_status=mmse.status; send_status=mmse.response_status; + +Action=Transform; Name=rm_client_from_http_resp1; Mode=Insert; Match=Strict; http_rq; +Action=Transform; Name=rm_client_from_http_resp1; Mode=Insert; Match=Every; addr; .not_rq; + +Action=Transform; Name=rm_client_from_http_resp2; Mode=Replace; Match=Strict; not_rq; ue; + +Action=PduTransform; For=mmse_over_http_pdu; Name=rm_client_from_http_resp1; +Action=PduTransform; For=mmse_over_http_pdu; Name=rm_client_from_http_resp2; + +Action=GopDef; Name=mmse_over_http; On=mmse_over_http_pdu; addr; addr; port; port; +Action=GopStart; For=mmse_over_http; http_rq; +Action=GopStop; For=mmse_over_http; http_rs; + +Action=GopExtra; For=mmse_over_http; host; ue; resp; notify_status; send_status; trx; + +# MMSE over WSP +Action=PduDef; Name=mmse_over_wsp_pdu; Proto=wsp; Payload=mmse; Transport=ip; trx=mmse.transaction_id; msg_type=mmse.message_type; notify_status=mmse.status; send_status=mmse.response_status; + +Action=Transform; Name=mms_start; Match=Loose; .mms_start; + +Action=PduTransform; Name=mms_start; For=mmse_over_wsp_pdu; + +Action=GopDef; Name=mmse_over_wsp; On=mmse_over_wsp_pdu; trx; +Action=GopStart; For=mmse_over_wsp; mms_start; +Action=GopStop; For=mmse_over_wsp; never; + +Action=GopExtra; For=mmse_over_wsp; ue; notify_status; send_status; + +# the MMS GoG +Action=GogDef; Name=mms; GogExpiration=60.0; +Action=GogKey; For=mms; On=mmse_over_http; trx; +Action=GogKey; For=mms; On=mmse_over_wsp; trx; +Action=GogExtra; For=mms; ue; notify_status; send_status; resp; host; trx; diff --git a/plugins/epan/mate/examples/pasv_ftp.mate b/plugins/epan/mate/examples/pasv_ftp.mate new file mode 100644 index 00000000..24ef7ab4 --- /dev/null +++ b/plugins/epan/mate/examples/pasv_ftp.mate @@ -0,0 +1,18 @@ +# pasv_ftp.mate + +Action=PduDef; Name=ftp_pdu; Proto=ftp; Transport=tcp/ip; Stop=TRUE; ftp_addr=ip.addr; ftp_port=tcp.port; ftp_resp=ftp.response.code; ftp_req=ftp.request.command; server_addr=ftp.passive.ip; server_port=ftp.passive.port; + +Action=PduDef; Name=ftp_data_pdu; Proto=ftp-data; Transport=tcp/ip; server_addr=ip.src; server_port=tcp.srcport; + +Action=GopDef; Name=ftp_data; On=ftp_data_pdu; server_addr; server_port; +Action=GopStart; For=ftp_data; server_addr; + +Action=GopDef; Name=ftp_ctl; On=ftp_pdu; ftp_addr; ftp_addr; ftp_port; ftp_port; +Action=GopStart; For=ftp_ctl; ftp_resp=220; +Action=GopStop; For=ftp_ctl; ftp_resp=221; +Action=GopExtra; For=ftp_ctl; server_addr; server_port; + +Action=GogDef; Name=ftp_ses; +Action=GogKey; For=ftp_ses; On=ftp_ctl; ftp_addr; ftp_addr; ftp_port; ftp_port; +Action=GogKey; For=ftp_ses; On=ftp_data; server_addr; server_port; + diff --git a/plugins/epan/mate/examples/tcp.mate b/plugins/epan/mate/examples/tcp.mate new file mode 100644 index 00000000..2abe3e88 --- /dev/null +++ b/plugins/epan/mate/examples/tcp.mate @@ -0,0 +1,7 @@ +# tcp.mate + + Action=PduDef; Name=tcp_pdu; Proto=tcp; Transport=ip; addr=ip.addr; port=tcp.port; tcp_start=tcp.flags.syn; tcp_stop=tcp.flags.fin; tcp_stop=tcp.flags.reset; + Action=GopDef; Name=tcp_session; On=tcp_pdu; addr; addr; port; port; + Action=GopStart; For=tcp_session; tcp_start=1; + Action=GopStop; For=tcp_session; tcp_stop=1; + diff --git a/plugins/epan/mate/examples/web.mate b/plugins/epan/mate/examples/web.mate new file mode 100644 index 00000000..fd00c651 --- /dev/null +++ b/plugins/epan/mate/examples/web.mate @@ -0,0 +1,27 @@ +# web.mate + +Action=PduDef; Name=dns_pdu; Proto=dns; Transport=ip; addr=ip.addr; dns_resp=dns.flags.response; host=dns.qry.name; client_addr=ip.src; dns_id=dns.id; +Action=PduDef; Name=http_pdu; Proto=http; Transport=tcp/ip; addr=ip.addr; port=tcp.port; http_rq=http.request.method; http_rs=http.response; host=http.host; client_addr=ip.src; + +Action=GopDef; Name=dns_req; On=dns_pdu; addr; addr; dns_id; +Action=GopStart; For=dns_req; dns_resp=0; +Action=GopStop; For=dns_req; dns_resp=1; + +Action=GopDef; Name=http_req; On=http_pdu; addr; addr; port; port; +Action=GopStart; For=http_req; http_rq; +Action=GopStop; For=http_req; http_rs; + +Action=Transform; Name=rm_client_from_dns_resp; Mode=Replace; Match=Every; dns_resp=1; client_addr; .dns_resp=1; +Action=PduTransform; For=dns_pdu; Name=rm_client_from_dns_resp; + +Action=Transform; Name=rm_client_from_http_resp; Mode=Replace; Match=Every; http_rs; client_addr; .http_rs=; +Action=PduTransform; For=http_pdu; Name=rm_client_from_http_resp; + +Action=GopExtra; For=http_req; host; client_addr; +Action=GopExtra; For=dns_req; host; client_addr; + +Action=GogDef; Name=http_use; GogExpiration=0.75; +Action=GogKey; For=http_use; On=http_req; host; client_addr; +Action=GogKey; For=http_use; On=dns_req; host;client_addr; + +Action=GogExtra; For=http_use; host; client_addr; diff --git a/plugins/epan/mate/mate.h b/plugins/epan/mate/mate.h new file mode 100644 index 00000000..79f46af8 --- /dev/null +++ b/plugins/epan/mate/mate.h @@ -0,0 +1,373 @@ +/* mate.h + * MATE -- Meta Analysis and Tracing Engine + * + * Copyright 2004, Luis E. Garcia Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#ifndef __MATE_H_ +#define __MATE_H_ + +#define WS_LOG_DOMAIN "MATE" +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "mate_util.h" + +/* defaults */ + +#define DEFAULT_GOG_EXPIRATION 2.0 + +#ifdef _WIN32 +#define DIR_SEP '\\' +#else +#define DIR_SEP '/' +#endif + +#define DEFAULT_MATE_LIB_PATH "matelib" + +#define MATE_ITEM_ID_SIZE 24 + +#define VALUE_TOO ((void*)1) + +#define MateConfigError 65535 + +typedef enum _gop_tree_mode_t { + GOP_NULL_TREE, + GOP_BASIC_TREE, + GOP_FULL_TREE +} gop_tree_mode_t; + +typedef enum _gop_pdu_tree { + GOP_NO_TREE, + GOP_PDU_TREE, + GOP_FRAME_TREE, + GOP_BASIC_PDU_TREE +} gop_pdu_tree_t; + +typedef enum _accept_mode_t { + ACCEPT_MODE, + REJECT_MODE +} accept_mode_t; + + +typedef struct _mate_cfg_pdu { + gchar* name; + guint last_id; /* keeps the last id given to an item of this kind */ + + GHashTable* items; /* all the items of this type */ + GPtrArray* transforms; /* transformations to be applied */ + + int hfid; + + int hfid_proto; + int hfid_pdu_rel_time; + int hfid_pdu_time_in_gop; + + GHashTable* my_hfids; /* for creating register info */ + + gint ett; + gint ett_attr; + + GHashTable* hfids_attr; /* k=hfid v=avp_name */ + + gboolean discard; + gboolean last_extracted; + gboolean drop_unassigned; + + GPtrArray* transport_ranges; /* hfids of candidate transport ranges from which to extract attributes */ + GPtrArray* payload_ranges; /* hfids of candidate payload ranges from which to extract attributes */ + + avpl_match_mode criterium_match_mode; + accept_mode_t criterium_accept_mode; + AVPL* criterium; +} mate_cfg_pdu; + + +typedef struct _mate_cfg_gop { + gchar* name; + guint last_id; /* keeps the last id given to an item of this kind */ + GHashTable* items; /* all the items of this type */ + + GPtrArray* transforms; /* transformations to be applied */ + gchar* on_pdu; + + AVPL* key; /* key candidate avpl */ + AVPL* start; /* start candidate avpl */ + AVPL* stop; /* stop candidate avpl */ + AVPL* extra; /* attributes to be added */ + + float expiration; + float idle_timeout; + float lifetime; + + gboolean drop_unassigned; + gop_pdu_tree_t pdu_tree_mode; + gboolean show_times; + + GHashTable* my_hfids; /* for creating register info */ + int hfid; + int hfid_start_time; + int hfid_stop_time; + int hfid_last_time; + int hfid_gop_pdu; + int hfid_gop_num_pdus; + + gint ett; + gint ett_attr; + gint ett_times; + gint ett_children; + + GHashTable* gop_index; + GHashTable* gog_index; +} mate_cfg_gop; + + +typedef struct _mate_cfg_gog { + gchar* name; + + GHashTable* items; /* all the items of this type */ + guint last_id; /* keeps the last id given to an item of this kind */ + + GPtrArray* transforms; /* transformations to be applied */ + + LoAL* keys; + AVPL* extra; /* attributes to be added */ + + float expiration; + gop_tree_mode_t gop_tree_mode; + gboolean show_times; + + GHashTable* my_hfids; /* for creating register info */ + int hfid; + int hfid_gog_num_of_gops; + int hfid_gog_gop; + int hfid_gog_gopstart; + int hfid_gog_gopstop; + int hfid_start_time; + int hfid_stop_time; + int hfid_last_time; + gint ett; + gint ett_attr; + gint ett_times; + gint ett_children; + gint ett_gog_gop; +} mate_cfg_gog; + +typedef struct _mate_config { + gchar* mate_config_file; /* name of the config file */ + + int hfid_mate; + + GArray *wanted_hfids; /* hfids of protocols and fields MATE needs */ + guint num_fields_wanted; /* number of fields MATE will look at */ + + FILE* dbg_facility; /* where to dump dbgprint output ws_message if null */ + + gchar* mate_lib_path; /* where to look for "Include" files first */ + + GHashTable* pducfgs; /* k=pducfg->name v=pducfg */ + GHashTable* gopcfgs; /* k=gopcfg->name v=gopcfg */ + GHashTable* gogcfgs; /* k=gogcfg->name v=gogcfg */ + GHashTable* transfs; /* k=transform->name v=transform */ + + GPtrArray* pducfglist; /* pducfgs in order of "execution" */ + GHashTable* gops_by_pduname; /* k=pducfg->name v=gopcfg */ + GHashTable* gogs_by_gopname; /* k=gopname v=loal where avpl->name == matchedgop->name */ + + GArray* hfrs; + gint ett_root; + GArray* ett; + + /* defaults */ + struct _mate_cfg_defaults { + struct _pdu_defaults { + avpl_match_mode match_mode; + avpl_replace_mode replace_mode; + gboolean last_extracted; + + gboolean drop_unassigned; + gboolean discard; + } pdu; + + struct _gop_defaults { + float expiration; + float idle_timeout; + float lifetime; + + gop_pdu_tree_t pdu_tree_mode; + gboolean show_times; + gboolean drop_unassigned; + + } gop; + + struct _gog_defaults { + float expiration; + gboolean show_times; + gop_tree_mode_t gop_tree_mode; + } gog; + } defaults; + + /* what to dbgprint */ + int dbg_lvl; + int dbg_pdu_lvl; + int dbg_gop_lvl; + int dbg_gog_lvl; + + GPtrArray* config_stack; + GString* config_error; + +} mate_config; + + +typedef struct _mate_config_frame { + gchar* filename; + guint linenum; +} mate_config_frame; + + +typedef struct _mate_runtime_data { + guint current_items; /* a count of items */ + float now; + guint highest_analyzed_frame; + + GHashTable* frames; /* k=frame.num v=pdus */ + +} mate_runtime_data; + +typedef struct _mate_pdu mate_pdu; +typedef struct _mate_gop mate_gop; +typedef struct _mate_gog mate_gog; + +/* these are used to contain information regarding pdus, gops and gogs */ +struct _mate_pdu { + guint32 id; /* 1:1 -> saving a g_malloc */ + mate_cfg_pdu* cfg; /* the type of this item */ + + AVPL* avpl; + + guint32 frame; /* wich frame I belog to? */ + mate_pdu* next_in_frame; /* points to the next pdu in this frame */ + float rel_time; /* time since start of capture */ + + mate_gop* gop; /* the gop the pdu belongs to (if any) */ + mate_pdu* next; /* next in gop */ + float time_in_gop; /* time since gop start */ + + gboolean first; /* is this the first pdu in this frame? */ + gboolean is_start; /* this is the start pdu for this gop */ + gboolean is_stop; /* this is the stop pdu for this gop */ + gboolean after_release; /* this pdu comes after the stop */ + +}; + + +struct _mate_gop { + guint32 id; + mate_cfg_gop* cfg; + + gchar* gop_key; + AVPL* avpl; /* the attributes of the pdu/gop/gog */ + guint last_n; + + mate_gog* gog; /* the gog of a gop */ + mate_gop* next; /* next in gog; */ + + float expiration; /* when will it expire after release (all gops releases if gog)? */ + float idle_expiration; /* when will it expire if no new pdus are assigned to it */ + float time_to_die; + float time_to_timeout; + + float start_time; /* time of start */ + float release_time; /* when this gop/gog was released */ + float last_time; /* the rel_time at which the last pdu has been added (to gop or gog's gop) */ + + + int num_of_pdus; /* how many gops a gog has? */ + int num_of_after_release_pdus; /* how many pdus have arrived since it's been released */ + mate_pdu* pdus; /* pdus that belong to a gop (NULL in gog) */ + mate_pdu* last_pdu; /* last pdu in pdu's list */ + + gboolean released; /* has this gop been released? */ +}; + + +struct _mate_gog { + guint32 id; + mate_cfg_gog* cfg; + + AVPL* avpl; /* the attributes of the pdu/gop/gog */ + guint last_n; /* the number of attributes the avpl had the last time we checked */ + + gboolean released; /* has this gop been released? */ + + float expiration; /* when will it expire after release (all gops releases if gog)? */ + float idle_expiration; /* when will it expire if no new pdus are assigned to it */ + + /* on gop and gog: */ + float start_time; /* time of start */ + float release_time; /* when this gog was released */ + float last_time; /* the rel_time at which the last pdu has been added */ + + mate_gop* gops; /* gops that belong to a gog (NULL in gop) */ + mate_gop* last_gop; /* last gop in gop's list */ + + int num_of_gops; /* how many gops a gog has? */ + int num_of_counting_gops; /* how many of them count for gog release */ + int num_of_released_gops; /* how many of them have already been released */ + GPtrArray* gog_keys; /* the keys under which this gog is stored in the gogs hash */ +}; + +typedef union _mate_max_size { + mate_pdu pdu; + mate_gop gop; + mate_gog gog; +} mate_max_size; + +/* from mate_runtime.c */ +extern void initialize_mate_runtime(mate_config* mc); +extern mate_pdu* mate_get_pdus(guint32 framenum); +extern void mate_analyze_frame(mate_config *mc, packet_info *pinfo, proto_tree* tree); + +/* from mate_setup.c */ +extern mate_config* mate_make_config(const gchar* filename, int mate_hfid); + +extern mate_cfg_pdu* new_pducfg(mate_config* mc, gchar* name); +extern mate_cfg_gop* new_gopcfg(mate_config* mc, gchar* name); +extern mate_cfg_gog* new_gogcfg(mate_config* mc, gchar* name); + +extern gboolean add_hfid(mate_config* mc, header_field_info* hfi, gchar* as, GHashTable* where); +extern gchar* add_ranges(gchar* range, GPtrArray* range_ptr_arr); + + +/* from mate_parser.l */ +extern gboolean mate_load_config(const gchar* filename, mate_config* mc); + +/* Constructor/Destructor prototypes for Lemon Parser */ +#define YYMALLOCARGTYPE gsize +void *MateParserAlloc(void* (*)(YYMALLOCARGTYPE)); +void MateParserFree(void*, void (*)(void *)); +void MateParser(void*, int, gchar*, mate_config*); + +#endif diff --git a/plugins/epan/mate/mate_grammar.lemon b/plugins/epan/mate/mate_grammar.lemon new file mode 100644 index 00000000..57f291fe --- /dev/null +++ b/plugins/epan/mate/mate_grammar.lemon @@ -0,0 +1,729 @@ +%include { + +/* mate_grammar.lemon + * MATE's configuration language grammar + * + * Copyright 2005, Luis E. Garcia Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * XXX - there's a Lemon bug where this grammar produces a parser that + * fails assertions; to work around it, we disable assert() failures. + */ +#ifndef NDEBUG +#define NDEBUG +#endif +#include "config.h" + +#include + +#include "mate.h" +#include "mate_grammar.h" +#include +#include + +#define DUMMY void* + +typedef struct _extraction { + gchar* as; + header_field_info* hfi; + struct _extraction* next; + struct _extraction* last; +} extraction_t; + +typedef struct _pdu_criteria_t { + AVPL* criterium_avpl; + avpl_match_mode criterium_match_mode; + accept_mode_t criterium_accept_mode; +} pdu_criteria_t; + +typedef struct _gop_options { + gop_tree_mode_t pdu_tree_mode; + gboolean drop_unassigned; + gboolean show_times; + float expiration; + float idle_timeout; + float lifetime; + AVPL* start; + AVPL* stop; + AVPL* extras; +} gop_options_t; + +typedef struct _gog_statements { + float expiration; + gop_tree_mode_t gop_tree_mode; + GPtrArray* transform_list; + AVPL* extras; + LoAL* current_gogkeys; +} gog_statement_t; + +typedef struct _transf_match_t { + avpl_match_mode match_mode; + AVPL* avpl; +} transf_match_t; + +typedef struct _transf_action_t { + avpl_replace_mode replace_mode; + AVPL* avpl; +} transf_action_t; + +static void configuration_error(mate_config* mc, const gchar* fmt, ...) { + static gchar error_buffer[256]; + const gchar* incl; + gint i; + mate_config_frame* current_frame; + va_list list; + + va_start( list, fmt ); + vsnprintf(error_buffer,sizeof(error_buffer),fmt,list); + va_end( list ); + + i = (gint) mc->config_stack->len; + + while (i--) { + + if (i>0) { + incl = "\n included from: "; + } else { + incl = " "; + } + + current_frame = (mate_config_frame *)g_ptr_array_index(mc->config_stack,(guint)i); + + g_string_append_printf(mc->config_error,"%s%s at line %u",incl, current_frame->filename, current_frame->linenum); + } + + g_string_append_printf(mc->config_error,": %s\n",error_buffer); + + THROW(MateConfigError); + +} + +static AVPL_Transf* new_transform_elem(AVPL* match, AVPL* replace, avpl_match_mode match_mode, avpl_replace_mode replace_mode) { + AVPL_Transf* t = (AVPL_Transf *)g_malloc(sizeof(AVPL_Transf)); + + t->name = NULL; + t->match = match; + t->replace = replace; + t->match_mode = match_mode; + t->replace_mode = replace_mode; + + t->map = NULL; + t->next = NULL; + + return t; +} + +static gchar* recolonize(mate_config* mc, gchar* s) { + GString* str = g_string_new(""); + gchar** vec; + gchar* r; + guint i,v; + gchar c; + + vec = g_strsplit(s,":",0); + + for (i = 0; vec[i]; i++) { + ascii_strdown_inplace(vec[i]); + + v = 0; + switch ( strlen(vec[i]) ) { + case 2: + c = vec[i][1]; + vec[i][1] = vec[i][0]; + vec[i][0] = c; + if (vec[i][0] >= '0' && vec[i][0] <= '9') { + v += (vec[i][1] - '0' )*16; + } else { + v += (vec[i][1] - 'a' + 10)*16; + } + /* FALL THROUGH */ + case 1: + if (vec[i][0] >= '0' && vec[i][0] <= '9') { + v += (vec[i][0] - '0' ); + } else { + v += (vec[i][0] - 'a' + 10); + } + case 0: + break; + default: + configuration_error(mc,"bad token %s",s); + } + + g_string_append_printf(str,":%.2X",v); + } + + g_strfreev(vec); + + g_string_erase(str,0,1); + + r = str->str; + + g_string_free(str,FALSE); + + return r; +} + +DIAG_OFF_LEMON() +} /* end of %include */ + +%code { +DIAG_ON_LEMON() +} + +%name MateParser + +%token_prefix TOKEN_ + +%token_type { gchar* } +%token_destructor { + (void) mc; /* Mark unused, similar to Q_UNUSED */ + g_free($$); +} + +%extra_argument { mate_config* mc } + +%syntax_error { + configuration_error(mc,"Syntax Error before %s",yyminor); +} + +%parse_failure { + configuration_error(mc,"Parse Error"); +} + +%type transform_decl { AVPL_Transf* } +%type transform_body { AVPL_Transf* } +%type transform_statements { AVPL_Transf* } +%type transform_statement { AVPL_Transf* } +%type transform_match { transf_match_t* } +%type transform_action { transf_action_t* } +%type match_mode { avpl_match_mode } +%type action_mode { avpl_replace_mode } + +%type gop_name { gchar* } +%type time_value { float } +%type pdu_name { gchar* } +%type gop_tree_mode { gop_tree_mode_t } +%type true_false { gboolean } + +%type criteria_statement { pdu_criteria_t* } +%type accept_mode { accept_mode_t } +%type pdu_drop_unassigned_statement { gboolean } +%type discard_pdu_data_statement { gboolean } +%type last_extracted_statement { gboolean } + +%type extraction_statement {extraction_t*} +%type extraction_statements {extraction_t*} + +%type gop_options { gop_options_t* } + +%type gop_start_statement { AVPL* } +%type gop_stop_statement { AVPL* } +%type extra_statement { AVPL* } +%type gop_drop_unassigned_statement { gboolean } +%type show_goptree_statement { gop_tree_mode_t } +%type show_times_statement { gboolean } +%type gop_expiration_statement { float } +%type idle_timeout_statement { float } +%type lifetime_statement { float } + +%type gog_statements { gog_statement_t* } +%type gog_expiration_statement { float } +%type gog_goptree_statement { gop_tree_mode_t } +%type gog_key_statements { LoAL* } +%type gog_key_statement { AVPL* } +%type transform_list_statement { GPtrArray* } +%type transform { AVPL_Transf* } +%type gop_tree_type { gop_tree_mode_t } + +%type payload_statement { GPtrArray* } +%type proto_stack { GPtrArray* } +%type field { header_field_info* } +%type transform_list { GPtrArray* } +%type avpl { AVPL* } +%type avps { AVPL* } +%type avp { AVP* } +%type value { gchar* } +%type avp_oneoff { gchar* } + + +mate_config ::= decls. + +decls ::= decls decl. +decls ::= . + +decl ::= pdu_decl. +decl ::= gop_decl. +decl ::= gog_decl. +decl ::= transform_decl. +decl ::= defaults_decl. +decl ::= debug_decl. +decl ::= DONE_KW SEMICOLON. + +/************* DEBUG +*/ + +debug_decl ::= DEBUG_KW OPEN_BRACE dbgfile_default dbglevel_default pdu_dbglevel_default gop_dbglevel_default gog_dbglevel_default CLOSE_BRACE SEMICOLON. + +dbgfile_default ::= FILENAME_KW QUOTED(Filename) SEMICOLON. { mc->dbg_facility = ws_fopen(Filename,"w"); if (mc->dbg_facility == NULL) report_open_failure(Filename,errno,TRUE); } +dbgfile_default ::= FILENAME_KW NAME(Filename) SEMICOLON. { mc->dbg_facility = ws_fopen(Filename,"w"); if (mc->dbg_facility == NULL) report_open_failure(Filename,errno,TRUE); } +dbgfile_default ::= . + +dbglevel_default ::= LEVEL_KW INTEGER(LevelString) SEMICOLON. { mc->dbg_lvl = (int) strtol(LevelString,NULL,10); } +dbglevel_default ::= . + +pdu_dbglevel_default ::= PDU_KW LEVEL_KW INTEGER(LevelString) SEMICOLON. { mc->dbg_pdu_lvl = (int) strtol(LevelString,NULL,10); } +pdu_dbglevel_default ::= . + +gop_dbglevel_default ::= GOP_KW LEVEL_KW INTEGER(LevelString) SEMICOLON. { mc->dbg_gop_lvl = (int) strtol(LevelString,NULL,10); } +gop_dbglevel_default ::= . + +gog_dbglevel_default ::= GOG_KW LEVEL_KW INTEGER(LevelString) SEMICOLON. { mc->dbg_gog_lvl = (int) strtol(LevelString,NULL,10); } +gog_dbglevel_default ::= . + + +/************* DEFAULTS +*/ + +defaults_decl ::= DEFAULT_KW OPEN_BRACE pdu_defaults gop_defaults gog_defaults CLOSE_BRACE SEMICOLON. + +pdu_defaults ::= PDU_KW OPEN_BRACE pdu_last_extracted_default pdu_drop_unassigned_default pdu_discard_default CLOSE_BRACE SEMICOLON. +pdu_defaults ::= . + +pdu_last_extracted_default ::= LAST_EXTRACTED_KW true_false(Flag) SEMICOLON. { mc->defaults.pdu.last_extracted = Flag; } +pdu_last_extracted_default ::= . + +pdu_drop_unassigned_default ::= DROP_UNASSIGNED_KW true_false(Flag) SEMICOLON. { mc->defaults.pdu.drop_unassigned = Flag; } +pdu_drop_unassigned_default ::= . + +pdu_discard_default ::= DISCARD_PDU_DATA_KW true_false(Flag) SEMICOLON. { mc->defaults.pdu.discard = Flag; } +pdu_discard_default ::= . + +gop_defaults ::= GOP_KW OPEN_BRACE gop_expiration_default gop_idle_timeout_default gop_lifetime_default gop_drop_unassigned_default gop_tree_mode_default gop_show_times_default CLOSE_BRACE SEMICOLON. +gop_defaults ::= . + +gop_expiration_default ::= EXPIRATION_KW time_value(B) SEMICOLON. { mc->defaults.gop.expiration = B; } +gop_expiration_default ::= . + +gop_idle_timeout_default ::= IDLE_TIMEOUT_KW time_value(B) SEMICOLON. { mc->defaults.gop.idle_timeout = B; } +gop_idle_timeout_default ::= . + +gop_lifetime_default ::= LIFETIME_KW time_value(B) SEMICOLON. { mc->defaults.gop.lifetime = B; } +gop_lifetime_default ::= . + +gop_drop_unassigned_default ::= DROP_UNASSIGNED_KW true_false(B) SEMICOLON. { mc->defaults.gop.drop_unassigned = B; } +gop_drop_unassigned_default ::= . + +gop_tree_mode_default ::= SHOW_TREE_KW gop_tree_mode(B) SEMICOLON. { mc->defaults.gop.pdu_tree_mode = (gop_pdu_tree_t)B; } +gop_tree_mode_default ::= . + +gop_show_times_default ::= SHOW_TIMES_KW true_false(B) SEMICOLON. { mc->defaults.gop.show_times = B; } +gop_show_times_default ::= . + +gog_defaults ::= GOG_KW OPEN_BRACE gog_expiration_default gop_tree_mode_default gog_goptree_default gog_show_times_default CLOSE_BRACE SEMICOLON. +gog_defaults ::= . + +gog_expiration_default ::= EXPIRATION_KW time_value(B) SEMICOLON. { mc->defaults.gop.expiration = B; } +gog_expiration_default ::= . + +gog_goptree_default ::= GOP_TREE_KW gop_tree_type(B) SEMICOLON. { mc->defaults.gog.gop_tree_mode = B; } +gog_goptree_default ::= . + +gog_show_times_default ::= SHOW_TIMES_KW true_false(B) SEMICOLON. { mc->defaults.gog.show_times = B; } +gog_show_times_default ::= . + + +/******************************************* TRANSFORM +*/ + +transform_decl(A) ::= TRANSFORM_KW NAME(B) transform_body(C) SEMICOLON. { + AVPL_Transf* c; + + if ( g_hash_table_lookup(mc->transfs,B) ) { + configuration_error(mc,"A transformation called '%s' exists already",B); + } + + for ( c = C; c; c = c->next ) + c->name = g_strdup(B); + + g_hash_table_insert(mc->transfs,C->name,C); + + A = NULL; +} + +transform_body(A) ::= OPEN_BRACE transform_statements(B) CLOSE_BRACE. { A = B; } + +transform_statements(A) ::= transform_statements(C) transform_statement(B). { + AVPL_Transf* c; + + for ( c = C; c->next; c = c->next ) ; + c->next = B; + A = C; +} + +transform_statements(A) ::= transform_statement(B). { A = B; } + +transform_statement(A) ::= transform_match(Match) transform_action(Action) SEMICOLON. { + A = new_transform_elem(Match->avpl,Action->avpl,Match->match_mode,Action->replace_mode); +} + +transform_match(A) ::= MATCH_KW match_mode(Mode) avpl(Avpl). { + A = (transf_match_t *)g_malloc(sizeof(transf_match_t)); + A->match_mode = Mode; + A->avpl = Avpl; +} + +transform_match(A) ::= . { + A = (transf_match_t *)g_malloc(sizeof(transf_match_t)); + A->match_mode = AVPL_STRICT; + A->avpl = new_avpl(""); + +} + +transform_action(A) ::= . { + A = (transf_action_t *)g_malloc(sizeof(transf_action_t)); + A->replace_mode = AVPL_INSERT; + A->avpl = new_avpl(""); +} +transform_action(A) ::= action_mode(Mode) avpl(Avpl). { + A = (transf_action_t *)g_malloc(sizeof(transf_action_t)); + A->replace_mode = Mode; + A->avpl = Avpl; +} + +match_mode(A) ::= . { A = AVPL_STRICT; } +match_mode(A) ::= STRICT_KW. { A = AVPL_STRICT; } +match_mode(A) ::= EVERY_KW. { A = AVPL_EVERY; } +match_mode(A) ::= LOOSE_KW. { A = AVPL_LOOSE; } + +action_mode(A) ::= REPLACE_KW. { A = AVPL_REPLACE; } +action_mode(A) ::= INSERT_KW. { A = AVPL_INSERT; } +action_mode(A) ::= . { A = AVPL_INSERT; } + +/******************************************* PDU +*/ + +pdu_decl ::= + PDU_KW NAME(Name) PROTO_KW field(Field) TRANSPORT_KW proto_stack(Stack) + OPEN_BRACE + payload_statement(Payload) + extraction_statements(Extraction) + transform_list_statement(Transform) + criteria_statement(Criteria) + pdu_drop_unassigned_statement(DropUnassigned) + discard_pdu_data_statement(DistcardPduData) + last_extracted_statement(LastExtracted) + CLOSE_BRACE SEMICOLON. +{ + + mate_cfg_pdu* cfg = new_pducfg(mc, Name); + extraction_t *extraction, *next_extraction; + GPtrArray* transport_stack = g_ptr_array_new(); + int i; + + if (! cfg ) configuration_error(mc,"could not create Pdu %s.",Name); + + cfg->hfid_proto = Field->id; + + cfg->last_extracted = LastExtracted; + cfg->discard = DistcardPduData; + cfg->drop_unassigned = DropUnassigned; + + /* + * Add this protocol to our table of wanted hfids. + */ + mc->wanted_hfids = g_array_append_val(mc->wanted_hfids, Field->id); + + /* flip the transport_stack */ + for (i = Stack->len - 1; Stack->len; i--) { + g_ptr_array_add(transport_stack,g_ptr_array_remove_index(Stack,i)); + } + + g_ptr_array_free(Stack, TRUE); + + cfg->transport_ranges = transport_stack; + cfg->payload_ranges = Payload; + + if (Criteria) { + cfg->criterium = Criteria->criterium_avpl; + cfg->criterium_match_mode = Criteria->criterium_match_mode; + cfg->criterium_accept_mode = Criteria->criterium_accept_mode; + } + + cfg->transforms = Transform; + + for (extraction = Extraction; extraction; extraction = next_extraction) { + next_extraction = extraction->next; + + if ( ! add_hfid(mc, extraction->hfi, extraction->as, cfg->hfids_attr) ) { + configuration_error(mc,"MATE: failed to create extraction rule '%s'",extraction->as); + } + + g_free(extraction); + } +} + +payload_statement(A) ::= . { A = NULL; } +payload_statement(A) ::= PAYLOAD_KW proto_stack(B) SEMICOLON. { A = B; } + +criteria_statement(A) ::= . { A = NULL; } +criteria_statement(A) ::= CRITERIA_KW accept_mode(B) match_mode(C) avpl(D) SEMICOLON. { + A = g_new(pdu_criteria_t, 1); + A->criterium_avpl = D; + A->criterium_match_mode = C; + A->criterium_accept_mode = B; +} + +accept_mode(A) ::= . { A = ACCEPT_MODE; } +accept_mode(A) ::= ACCEPT_KW. { A = ACCEPT_MODE; } +accept_mode(A) ::= REJECT_KW. { A = REJECT_MODE; } + +extraction_statements(A) ::= extraction_statements(B) extraction_statement(C). { A = B; A->last = A->last->next = C; } +extraction_statements(A) ::= extraction_statement(B). { A = B; A->last = A; } + +extraction_statement(A) ::= EXTRACT_KW NAME(NAME) FROM_KW field(FIELD) SEMICOLON. { + A = g_new(extraction_t, 1); + A->as = NAME; + A->hfi = FIELD; + A->next = A->last = NULL; +} + + +pdu_drop_unassigned_statement(A) ::= DROP_UNASSIGNED_KW true_false(B) SEMICOLON. { A = B; } +pdu_drop_unassigned_statement(A) ::= . { A = mc->defaults.pdu.drop_unassigned; } + +discard_pdu_data_statement(A) ::= DISCARD_PDU_DATA_KW true_false(B) SEMICOLON. { A = B; } +discard_pdu_data_statement(A) ::= . { A = mc->defaults.pdu.discard; } + +last_extracted_statement(A) ::= LAST_PDU_KW true_false(B) SEMICOLON. { A = B; } +last_extracted_statement(A) ::= . { A = mc->defaults.pdu.last_extracted; } + +proto_stack(A) ::= proto_stack(B) SLASH field(C). { + int* hfidp = g_new(int, 1); + + *hfidp = C->id; + g_ptr_array_add(B,hfidp); + A = B; +} + +proto_stack(A) ::= field(B). { + int* hfidp = g_new(int, 1); + *hfidp = B->id; + + A = g_ptr_array_new(); + g_ptr_array_add(A,hfidp); +} + +field(A) ::= NAME(B). { + A = proto_registrar_get_byname(B); +} + +/******************************************* GOP +*/ + +gop_decl(A) ::= GOP_KW NAME(Name) ON_KW pdu_name(PduName) MATCH_KW avpl(Key) OPEN_BRACE + gop_start_statement(Start) + gop_stop_statement(Stop) + extra_statement(Extra) + transform_list_statement(Transform) + gop_expiration_statement(Expiration) + idle_timeout_statement(IdleTimeout) + lifetime_statement(Lifetime) + gop_drop_unassigned_statement(DropUnassigned) + show_goptree_statement(TreeMode) + show_times_statement(ShowTimes) + CLOSE_BRACE SEMICOLON. { + mate_cfg_gop* cfg; + + if (g_hash_table_lookup(mc->gopcfgs,Name)) configuration_error(mc,"A Gop Named '%s' exists already.",Name); + if (g_hash_table_lookup(mc->gops_by_pduname,PduName) ) configuration_error(mc,"Gop for Pdu '%s' exists already",PduName); + + cfg = new_gopcfg(mc, Name); + g_hash_table_insert(mc->gops_by_pduname,PduName,cfg); + g_hash_table_insert(mc->gopcfgs,cfg->name,cfg); + + cfg->on_pdu = PduName; + cfg->key = Key; + cfg->drop_unassigned = DropUnassigned; + cfg->show_times = ShowTimes; + cfg->pdu_tree_mode = (gop_pdu_tree_t)TreeMode; + cfg->expiration = Expiration; + cfg->idle_timeout = IdleTimeout; + cfg->lifetime = Lifetime; + cfg->start = Start; + cfg->stop = Stop; + cfg->transforms = Transform; + + merge_avpl(cfg->extra,Extra,TRUE); + delete_avpl(Extra,TRUE); +} + +gop_drop_unassigned_statement(A) ::= DROP_UNASSIGNED_KW true_false(B) SEMICOLON. { A = B; } +gop_drop_unassigned_statement(A) ::= . { A = mc->defaults.gop.drop_unassigned; } + +gop_start_statement(A) ::= START_KW avpl(B) SEMICOLON. { A = B; } +gop_start_statement(A) ::= . { A = NULL; } + +gop_stop_statement(A) ::= STOP_KW avpl(B) SEMICOLON. { A = B; } +gop_stop_statement(A) ::= . { A = NULL; } + +show_goptree_statement(A) ::= SHOW_TREE_KW gop_tree_mode(B) SEMICOLON. { A = B; } +show_goptree_statement(A) ::= . { A = (gop_tree_mode_t)mc->defaults.gop.pdu_tree_mode; } + +show_times_statement(A) ::= SHOW_TIMES_KW true_false(B) SEMICOLON. { A = B; } +show_times_statement(A) ::= . { A = mc->defaults.gop.show_times; } + +gop_expiration_statement(A) ::= EXPIRATION_KW time_value(B) SEMICOLON. { A = B; } +gop_expiration_statement(A) ::= . { A = mc->defaults.gop.lifetime; } + +idle_timeout_statement(A) ::= IDLE_TIMEOUT_KW time_value(B) SEMICOLON. { A = B; } +idle_timeout_statement(A) ::= . { A = mc->defaults.gop.lifetime; } + +lifetime_statement(A) ::= LIFETIME_KW time_value(B) SEMICOLON. { A = B; } +lifetime_statement(A) ::= . { A = mc->defaults.gop.lifetime; } + +gop_tree_mode(A) ::= NO_TREE_KW. { A = (gop_tree_mode_t)GOP_NO_TREE; } +gop_tree_mode(A) ::= PDU_TREE_KW. { A = (gop_tree_mode_t)GOP_PDU_TREE; } +gop_tree_mode(A) ::= FRAME_TREE_KW. { A = (gop_tree_mode_t)GOP_FRAME_TREE; } +gop_tree_mode(A) ::= BASIC_TREE_KW. { A = (gop_tree_mode_t)GOP_BASIC_PDU_TREE; } + +true_false(A) ::= TRUE_KW. { A = TRUE; } +true_false(A) ::= FALSE_KW. { A = FALSE; } + +pdu_name(A) ::= NAME(B). { + mate_cfg_pdu* c; + if (( c = (mate_cfg_pdu *)g_hash_table_lookup(mc->pducfgs,B) )) { + A = c->name; + } else { + configuration_error(mc,"No such Pdu: '%s'",B); + } +} + + +time_value(A) ::= FLOATING(B). { + A = (float) g_ascii_strtod(B,NULL); +} + +time_value(A) ::= INTEGER(B). { + A = (float) g_ascii_strtod(B,NULL); +} + +/************* GOG +*/ + +gog_decl ::= GOG_KW NAME(Name) OPEN_BRACE + gog_key_statements(Keys) + extra_statement(Extra) + transform_list_statement(Transforms) + gog_expiration_statement(Expiration) + gog_goptree_statement(Tree) + show_times_statement(ShowTimes) + CLOSE_BRACE SEMICOLON. { + mate_cfg_gog* cfg = NULL; + + if ( g_hash_table_lookup(mc->gogcfgs,Name) ) { + configuration_error(mc,"Gog '%s' exists already ",Name); + } + + cfg = new_gogcfg(mc, Name); + + cfg->expiration = Expiration; + cfg->gop_tree_mode = Tree; + cfg->transforms = Transforms; + cfg->keys = Keys; + cfg->show_times = ShowTimes; + + merge_avpl(cfg->extra,Extra,TRUE); + delete_avpl(Extra,TRUE); +} + +gog_goptree_statement(A) ::= GOP_TREE_KW gop_tree_type(B) SEMICOLON. { A = B; } +gog_goptree_statement(A) ::= . { A = mc->defaults.gog.gop_tree_mode; } + +gog_expiration_statement(A) ::= EXPIRATION_KW time_value(B) SEMICOLON. { A = B; } +gog_expiration_statement(A) ::= . { A = mc->defaults.gog.expiration; } + +gop_tree_type(A) ::= NULL_TREE_KW. { A = GOP_NULL_TREE; } +gop_tree_type(A) ::= FULL_TREE_KW. { A = GOP_FULL_TREE; } +gop_tree_type(A) ::= BASIC_TREE_KW. { A = GOP_BASIC_TREE; } + +gog_key_statements(A) ::= gog_key_statements(B) gog_key_statement(C). { + loal_append(B,C); + A = B; +} + +gog_key_statements(A) ::= gog_key_statement(B). { + A = new_loal(""); + loal_append(A,B); +} + + +gog_key_statement(A) ::= MEMBER_KW gop_name(B) avpl(C) SEMICOLON. { + rename_avpl(C,B); + A = C; +} + +gop_name(A) ::= NAME(B). { + mate_cfg_gop* c; + if (( c = (mate_cfg_gop *)g_hash_table_lookup(mc->gopcfgs,B) )) { + A = c->name; + } else { + configuration_error(mc,"No Gop called '%s' has been already declared",B); + } +} +/******************************************** GENERAL +*/ + + +extra_statement(A) ::= EXTRA_KW avpl(B) SEMICOLON. { A = B; } +extra_statement(A) ::= . { A = new_avpl(""); } + +transform_list_statement(A) ::= TRANSFORM_KW transform_list(B) SEMICOLON. { A = B; } +transform_list_statement(A) ::= . { A = g_ptr_array_new(); } + +transform_list(A) ::= transform_list(B) COMMA transform(C). { + A = B; + g_ptr_array_add(B,C); +} + +transform_list(A) ::= transform(B). { + A = g_ptr_array_new(); + g_ptr_array_add(A,B); +} + +transform(A) ::= NAME(B). { + AVPL_Transf* t; + + if (( t = (AVPL_Transf *)g_hash_table_lookup(mc->transfs,B) )) { + A = t; + } else { + configuration_error(mc,"There's no such Transformation: %s",B); + } +} + +avpl(A) ::= OPEN_PARENS avps(B) CLOSE_PARENS. { A = B; } +avpl(A) ::= OPEN_PARENS CLOSE_PARENS. { A = new_avpl(""); } + +avps(A) ::= avps(B) COMMA avp(C). { A = B; if ( ! insert_avp(B,C) ) delete_avp(C); } +avps(A) ::= avp(B). { A = new_avpl(""); if ( ! insert_avp(A,B) ) delete_avp(B); } + +avp(A) ::= NAME(B) AVP_OPERATOR(C) value(D). { A = new_avp(B,D,*C); } +avp(A) ::= NAME(B). { A = new_avp(B,"",'?'); } +avp(A) ::= NAME(B) OPEN_BRACE avp_oneoff(C) CLOSE_BRACE. { A = new_avp(B,C,'|'); } + +avp_oneoff(A) ::= avp_oneoff(B) PIPE value(C). { A = ws_strdup_printf("%s|%s",B,C); } +avp_oneoff(A) ::= value(B). { A = g_strdup(B); } + +value(A) ::= QUOTED(B). { A = g_strdup(B); } +value(A) ::= NAME(B). { A = g_strdup(B); } +value(A) ::= FLOATING(B). { A = g_strdup(B); } +value(A) ::= INTEGER(B). { A = g_strdup(B); } +value(A) ::= DOTED_IP(B). { A = g_strdup(B); } +value(A) ::= COLONIZED(B). { A = recolonize(mc,B); } + diff --git a/plugins/epan/mate/mate_parser.l b/plugins/epan/mate/mate_parser.l new file mode 100644 index 00000000..6e423abc --- /dev/null +++ b/plugins/epan/mate/mate_parser.l @@ -0,0 +1,409 @@ +%top { +/* Include this before everything else, for various large-file definitions */ +#include "config.h" +/* Include this before everything else, as it declares functions used here. */ +#include "mate.h" +} + +/* + * We want a reentrant scanner. + */ +%option reentrant + +/* + * We don't use input, so don't generate code for it. + */ +%option noinput + +/* + * We don't use unput, so don't generate code for it. + */ +%option nounput + +/* + * We don't read interactively from the terminal. + */ +%option never-interactive + +/* + * We want to stop processing when we get to the end of the input. + */ +%option noyywrap + +/* + * The type for the state we keep for a scanner. + */ +%option extra-type="Mate_scanner_state_t *" + +/* + * We have to override the memory allocators so that we don't get + * "unused argument" warnings from the yyscanner argument (which + * we don't use, as we have a global memory allocator). + * + * We provide, as macros, our own versions of the routines generated by Flex, + * which just call malloc()/realloc()/free() (as the Flex versions do), + * discarding the extra argument. + */ +%option noyyalloc +%option noyyrealloc +%option noyyfree + +/* + * Prefix scanner routines with "Mate_" rather than "yy", so this scanner + * can coexist with other scanners. + */ +%option prefix="Mate_" + +%{ + + /* mate_parser.l + * lexical analyzer for MATE configuration files + * + * Copyright 2004, Luis E. Garcia Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "mate_grammar.h" + +#include + +/* + * Disable diagnostics in the code generated by Flex. + */ +DIAG_OFF_FLEX() + + void MateParseTrace(FILE*,char*); + +#define MAX_INCLUDE_DEPTH 10 +typedef struct { + mate_config* mc; + + mate_config_frame* current_frame; + + void* pParser; + + YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; + int include_stack_ptr; +} Mate_scanner_state_t; + +#define MATE_PARSE(token_type) MateParser(yyextra->pParser, (token_type), g_strdup(yytext), yyextra->mc); + +/* + * Flex (v 2.5.35) uses this symbol to "exclude" unistd.h + */ +#ifdef _WIN32 +#define YY_NO_UNISTD_H +#endif + +static void free_config_frame(mate_config_frame *frame) { + g_free(frame->filename); + g_free(frame); +} + +#define YY_USER_INIT BEGIN OUTSIDE; + +/* + * Sleazy hack to suppress compiler warnings in yy_fatal_error(). + */ +#define YY_EXIT_FAILURE ((void)yyscanner, 2) + +/* + * Macros for the allocators, to discard the extra argument. + */ +#define Mate_alloc(size, yyscanner) (void *)malloc(size) +#define Mate_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size)) +#define Mate_free(ptr, yyscanner) free((char *)ptr) + +%} + +pdu_kw Pdu +gop_kw Gop +gog_kw Gog +transform_kw Transform +match_kw Match +always_kw Always +strict_kw Strict +every_kw Every +loose_kw Loose +replace_kw Replace +insert_kw Insert +gop_tree_kw GopTree +member_kw Member +on_kw On +start_kw Start +stop_kw Stop +extra_kw Extra +show_tree_kw ShowTree +show_times_kw ShowTimes +expiration_kw Expiration +idle_timeout_kw IdleTimeout +lifetime_kw Lifetime +no_tree_kw NoTree +pdu_tree_kw PduTree +frame_tree_kw FrameTree +basic_tree_kw BasicTree +true_kw [Tt][Rr][Uu][Ee] +false_kw [Ff][Aa][Ll][Ss][Ee] +proto_kw Proto +payload_kw Payload +transport_kw Transport +criteria_kw Criteria +accept_kw Accept +reject_kw Reject +extract_kw Extract +from_kw From +drop_unassigned_kw DropUnassigned +discard_pdu_data_kw DiscardPduData +last_pdu_kw LastPdu +done_kw Done +filename_kw Filename +debug_kw Debug +level_kw Level +default_kw Default + + +open_parens "(" +close_parens ")" +open_brace "{" +close_brace "}" +comma "," +semicolon ";" +slash "/" +pipe "|" + +integer [0-9]+ +floating ([0-9]+\.[0-9]+) +doted_ip [0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]?\.[0-9][0-9]?[0-9]? +colonized [0-9A-Fa-f:]*[:][0-9A-Fa-f:]* + +name [a-z][-\.a-zA-Z0-9_]* +avp_operator [$^~=<>!] +quote ["] +not_quoted [^"]* + +include "#include" +filename [-A-Za-z0-9_/.]+ + +whitespace [[:blank:]\r]+ +newline \n + +comment "//"[^\n]*\n + +blk_cmnt_start "/*" +cmnt_char . +blk_cmnt_stop "*/" + +%START OUTSIDE QUOTED INCLUDING COMMENT +%% + +{newline} yyextra->current_frame->linenum++; +{whitespace} ; + +{include} BEGIN INCLUDING; + +{filename} { + if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH ) + ws_error("dtd_preparse: include files nested too deeply"); + + yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER; + yyin = ws_fopen( yytext, "r" ); + + if (!yyin) { + Mate__delete_buffer(YY_CURRENT_BUFFER, yyscanner); + + /* coverity[negative_sink] */ + Mate__switch_to_buffer(yyextra->include_stack[--yyextra->include_stack_ptr], yyscanner); + + if (errno) + g_string_append_printf(yyextra->mc->config_error, "Mate parser: Could not open file: '%s': %s", yytext, g_strerror(errno) ); + + } else { + + yyextra->current_frame = g_new(mate_config_frame, 1); + yyextra->current_frame->filename = g_strdup(yytext); + yyextra->current_frame->linenum = 1; + + g_ptr_array_add(yyextra->mc->config_stack,yyextra->current_frame); + + Mate__switch_to_buffer(Mate__create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner); + } + + BEGIN OUTSIDE; +} + +<> { + /* coverity[check_after_sink] */ + if ( --yyextra->include_stack_ptr < 0 ) { + yyterminate(); + } else { + Mate__delete_buffer(YY_CURRENT_BUFFER, yyscanner); + Mate__switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner); + + free_config_frame(yyextra->current_frame); + yyextra->current_frame = (mate_config_frame *)g_ptr_array_remove_index(yyextra->mc->config_stack,yyextra->mc->config_stack->len-1); + } +} + +{comment} ; + +{blk_cmnt_start} BEGIN COMMENT; +{cmnt_char} ; +{blk_cmnt_stop} BEGIN OUTSIDE; + +{pdu_kw} MATE_PARSE(TOKEN_PDU_KW); +{gop_kw} MATE_PARSE(TOKEN_GOP_KW); +{gog_kw} MATE_PARSE(TOKEN_GOG_KW); +{transform_kw} MATE_PARSE(TOKEN_TRANSFORM_KW); +{match_kw} MATE_PARSE(TOKEN_MATCH_KW); +{strict_kw} MATE_PARSE(TOKEN_STRICT_KW); +{every_kw} MATE_PARSE(TOKEN_EVERY_KW); +{loose_kw} MATE_PARSE(TOKEN_LOOSE_KW); +{replace_kw} MATE_PARSE(TOKEN_REPLACE_KW); +{insert_kw} MATE_PARSE(TOKEN_INSERT_KW); +{gop_tree_kw} MATE_PARSE(TOKEN_GOP_TREE_KW); +{member_kw} MATE_PARSE(TOKEN_MEMBER_KW); +{on_kw} MATE_PARSE(TOKEN_ON_KW); +{start_kw} MATE_PARSE(TOKEN_START_KW); +{stop_kw} MATE_PARSE(TOKEN_STOP_KW); +{extra_kw} MATE_PARSE(TOKEN_EXTRA_KW); +{show_tree_kw} MATE_PARSE(TOKEN_SHOW_TREE_KW); +{show_times_kw} MATE_PARSE(TOKEN_SHOW_TIMES_KW); +{expiration_kw} MATE_PARSE(TOKEN_EXPIRATION_KW); +{idle_timeout_kw} MATE_PARSE(TOKEN_IDLE_TIMEOUT_KW); +{lifetime_kw} MATE_PARSE(TOKEN_LIFETIME_KW); +{no_tree_kw} MATE_PARSE(TOKEN_NO_TREE_KW); +{pdu_tree_kw} MATE_PARSE(TOKEN_PDU_TREE_KW); +{frame_tree_kw} MATE_PARSE(TOKEN_FRAME_TREE_KW); +{basic_tree_kw} MATE_PARSE(TOKEN_BASIC_TREE_KW); +{true_kw} MATE_PARSE(TOKEN_TRUE_KW); +{false_kw} MATE_PARSE(TOKEN_FALSE_KW); +{proto_kw} MATE_PARSE(TOKEN_PROTO_KW); +{payload_kw} MATE_PARSE(TOKEN_PAYLOAD_KW); +{transport_kw} MATE_PARSE(TOKEN_TRANSPORT_KW); +{criteria_kw} MATE_PARSE(TOKEN_CRITERIA_KW); +{accept_kw} MATE_PARSE(TOKEN_ACCEPT_KW); +{reject_kw} MATE_PARSE(TOKEN_REJECT_KW); +{extract_kw} MATE_PARSE(TOKEN_EXTRACT_KW); +{from_kw} MATE_PARSE(TOKEN_FROM_KW); +{drop_unassigned_kw} MATE_PARSE(TOKEN_DROP_UNASSIGNED_KW); +{discard_pdu_data_kw} MATE_PARSE(TOKEN_DISCARD_PDU_DATA_KW); +{last_pdu_kw} MATE_PARSE(TOKEN_LAST_PDU_KW); +{done_kw} MATE_PARSE(TOKEN_DONE_KW); +{filename_kw} MATE_PARSE(TOKEN_FILENAME_KW); +{debug_kw} MATE_PARSE(TOKEN_DEBUG_KW); +{level_kw} MATE_PARSE(TOKEN_LEVEL_KW); +{default_kw} MATE_PARSE(TOKEN_DEFAULT_KW); + +{open_parens} MATE_PARSE(TOKEN_OPEN_PARENS); +{close_parens} MATE_PARSE(TOKEN_CLOSE_PARENS); +{open_brace} MATE_PARSE(TOKEN_OPEN_BRACE); +{close_brace} MATE_PARSE(TOKEN_CLOSE_BRACE); +{comma} MATE_PARSE(TOKEN_COMMA); +{semicolon} MATE_PARSE(TOKEN_SEMICOLON); +{slash} MATE_PARSE(TOKEN_SLASH); +{pipe} MATE_PARSE(TOKEN_PIPE); + +{integer} MATE_PARSE(TOKEN_INTEGER); +{floating} MATE_PARSE(TOKEN_FLOATING); +{doted_ip} MATE_PARSE(TOKEN_DOTED_IP); +{colonized} MATE_PARSE(TOKEN_COLONIZED); +{name} MATE_PARSE(TOKEN_NAME); +{avp_operator} MATE_PARSE(TOKEN_AVP_OPERATOR); + + +{quote} BEGIN QUOTED; +{not_quoted} MATE_PARSE(TOKEN_QUOTED); +{quote} BEGIN OUTSIDE; + +%% + +/* + * Turn diagnostics back on, so we check the code that we've written. + */ +DIAG_ON_FLEX() + +static void ptr_array_free(gpointer data, gpointer user_data _U_) +{ + free_config_frame((mate_config_frame *)data); +} + +extern gboolean mate_load_config(const gchar* filename, mate_config* mc) { + FILE *in; + yyscan_t scanner; + Mate_scanner_state_t state; + volatile gboolean status = TRUE; + + in = ws_fopen(filename,"r"); + + if (!in) { + g_string_append_printf(mc->config_error,"Mate parser: Could not open file: '%s', error: %s", filename, g_strerror(errno) ); + return FALSE; + } + + if (Mate_lex_init(&scanner) != 0) { + g_string_append_printf(mc->config_error, "Mate parse: Could not initialize scanner: %s", g_strerror(errno)); + fclose(in); + return FALSE; + } + + Mate_set_in(in, scanner); + + mc->config_stack = g_ptr_array_new(); + + state.mc = mc; + + state.current_frame = g_new(mate_config_frame, 1); + state.current_frame->filename = g_strdup(filename); + state.current_frame->linenum = 1; + + g_ptr_array_add(mc->config_stack,state.current_frame); + + state.pParser = MateParserAlloc(g_malloc); + + state.include_stack_ptr = 0; + + /* Associate the state with the scanner */ + Mate_set_extra(&state, scanner); + + /* MateParserTrace(stdout,""); */ + + TRY { + Mate_lex(scanner); + + /* Inform parser that end of input has reached. */ + MateParser(state.pParser, 0, NULL, mc); + + MateParserFree(state.pParser, g_free); + } CATCH(MateConfigError) { + status = FALSE; + } CATCH_ALL { + status = FALSE; + g_string_append_printf(mc->config_error,"An unexpected error occurred"); + } + ENDTRY; + + Mate_lex_destroy(scanner); + fclose(in); + + g_ptr_array_foreach(mc->config_stack, ptr_array_free, NULL); + g_ptr_array_free(mc->config_stack, TRUE); + + return status; +} diff --git a/plugins/epan/mate/mate_runtime.c b/plugins/epan/mate/mate_runtime.c new file mode 100644 index 00000000..41d9c0de --- /dev/null +++ b/plugins/epan/mate/mate_runtime.c @@ -0,0 +1,930 @@ +/* mate_runtime.c + * MATE -- Meta Analysis Tracing Engine + * + * Copyright 2004, Luis E. Garcia Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include "mate.h" +#include + +typedef struct _mate_range mate_range; + +struct _mate_range { + guint start; + guint end; +}; + + +typedef struct _tmp_pdu_data { + GPtrArray* ranges; + proto_tree* tree; + mate_pdu* pdu; +} tmp_pdu_data; + + +typedef struct _gogkey { + gchar* key; + mate_cfg_gop* cfg; +} gogkey; + + +static mate_runtime_data* rd = NULL; + +static int zero = 5; + +static int* dbg = &zero; +static int* dbg_pdu = &zero; +static int* dbg_gop = &zero; +static int* dbg_gog = &zero; +static FILE* dbg_facility = NULL; + +static gboolean destroy_mate_pdus(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_pdu* pdu = (mate_pdu*) v; + if (pdu->avpl) delete_avpl(pdu->avpl,TRUE); + g_slice_free(mate_max_size, (mate_max_size *)pdu); + return TRUE; +} + +static gboolean destroy_mate_gops(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_gop* gop = (mate_gop*) v; + + if (gop->avpl) delete_avpl(gop->avpl,TRUE); + + if (gop->gop_key) { + if (g_hash_table_lookup(gop->cfg->gop_index,gop->gop_key) == gop) { + g_hash_table_remove(gop->cfg->gop_index,gop->gop_key); + } + + g_free(gop->gop_key); + } + + g_slice_free(mate_max_size,(mate_max_size*)gop); + + return TRUE; +} + + +static void gog_remove_keys (mate_gog* gog); + +static gboolean destroy_mate_gogs(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_gog* gog = (mate_gog*) v; + + if (gog->avpl) delete_avpl(gog->avpl,TRUE); + + if (gog->gog_keys) { + gog_remove_keys(gog); + g_ptr_array_free(gog->gog_keys, TRUE); + } + + g_slice_free(mate_max_size,(mate_max_size*)gog); + + return TRUE; +} + +static gboolean return_true(gpointer k _U_, gpointer v _U_, gpointer p _U_) { + return TRUE; +} + +static void destroy_pdus_in_cfg(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_pdu* c = (mate_cfg_pdu *)v; + g_hash_table_foreach_remove(c->items,destroy_mate_pdus,NULL); + c->last_id = 0; +} + + +static void destroy_gops_in_cfg(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_gop* c = (mate_cfg_gop *)v; + + g_hash_table_foreach_remove(c->gop_index,return_true,NULL); + g_hash_table_destroy(c->gop_index); + c->gop_index = g_hash_table_new(g_str_hash,g_str_equal); + + g_hash_table_foreach_remove(c->gog_index,return_true,NULL); + g_hash_table_destroy(c->gog_index); + c->gog_index = g_hash_table_new(g_str_hash,g_str_equal); + + g_hash_table_foreach_remove(c->items,destroy_mate_gops,NULL); + c->last_id = 0; +} + +static void destroy_gogs_in_cfg(gpointer k _U_, gpointer v, gpointer p _U_) { + mate_cfg_gog* c = (mate_cfg_gog *)v; + g_hash_table_foreach_remove(c->items,destroy_mate_gogs,NULL); + c->last_id = 0; +} + +void initialize_mate_runtime(mate_config* mc) { + + dbg_print (dbg,5,dbg_facility,"initialize_mate: entering"); + + if (mc) { + if (rd == NULL ) { + rd = g_new(mate_runtime_data, 1); + } else { + g_hash_table_foreach(mc->pducfgs,destroy_pdus_in_cfg,NULL); + g_hash_table_foreach(mc->gopcfgs,destroy_gops_in_cfg,NULL); + g_hash_table_foreach(mc->gogcfgs,destroy_gogs_in_cfg,NULL); + + g_hash_table_destroy(rd->frames); + } + + rd->current_items = 0; + rd->now = -1.0f; + rd->highest_analyzed_frame = 0; + rd->frames = g_hash_table_new(g_direct_hash,g_direct_equal); + + + /*mc->dbg_gop_lvl = 5; + mc->dbg_gog_lvl = 5; + */ + dbg_pdu = &(mc->dbg_pdu_lvl); + dbg_gop = &(mc->dbg_gop_lvl); + dbg_gog = &(mc->dbg_gog_lvl); + dbg = &(mc->dbg_lvl); + dbg_facility = mc->dbg_facility; + + dbg_print(dbg, 1, dbg_facility, "starting mate"); + + } else { + rd = NULL; + } +} + + +static mate_gop* new_gop(mate_cfg_gop* cfg, mate_pdu* pdu, gchar* key) { + mate_gop* gop = (mate_gop*)g_slice_new(mate_max_size); + + gop->id = ++(cfg->last_id); + gop->cfg = cfg; + + dbg_print(dbg_gop, 1, dbg_facility, "new_gop: %s: ``%s:%d''", key, gop->cfg->name, gop->id); + + gop->gop_key = key; + gop->avpl = new_avpl(cfg->name); + gop->last_n = 0; + + gop->gog = NULL; + gop->next = NULL; + + gop->expiration = cfg->expiration > 0.0 ? cfg->expiration + rd->now : (float) -1.0 ; + gop->idle_expiration = cfg->idle_timeout > 0.0 ? cfg->idle_timeout + rd->now : (float) -1.0 ; + gop->time_to_die = cfg->lifetime > 0.0 ? cfg->lifetime + rd->now : (float) -1.0 ; + gop->time_to_timeout = 0.0f; + + gop->last_time = gop->start_time = rd->now; + gop->release_time = 0.0f; + + gop->num_of_pdus = 0; + gop->num_of_after_release_pdus = 0; + + gop->pdus = pdu; + gop->last_pdu = pdu; + + gop->released = FALSE; + + pdu->gop = gop; + pdu->next = NULL; + pdu->is_start = TRUE; + pdu->time_in_gop = 0.0f; + + g_hash_table_insert(cfg->gop_index,gop->gop_key,gop); + return gop; +} + +static void adopt_gop(mate_gog* gog, mate_gop* gop) { + dbg_print (dbg_gog,5,dbg_facility,"adopt_gop: gog=%p gop=%p",(void*)gog,(void*)gop); + + gop->gog = gog; + gop->next = NULL; + + if (gop->cfg->start) { + gog->num_of_counting_gops++; + } + + gog->num_of_gops++; + + if (gog->last_gop) { + gog->last_gop->next = gop; + } + + gog->last_gop = gop; + + if (! gog->gops ) { + gog->gops = gop; + } + +} + +static mate_gog* new_gog(mate_cfg_gog* cfg, mate_gop* gop) { + mate_gog* gog = (mate_gog*)g_slice_new(mate_max_size); + gog->id = ++(cfg->last_id); + gog->cfg = cfg; + + dbg_print (dbg_gog,1,dbg_facility,"new_gog: %s:%u for %s:%u",gog->cfg->name,gog->id,gop->cfg->name,gop->id); + + gog->avpl = new_avpl(cfg->name); + gog->last_n = 0; + + gog->expiration = 0.0f; + gog->idle_expiration = 0.0f; + + gog->start_time = rd->now; + gog->release_time = 0.0f; + gog->last_time = 0.0f; + + gog->gops = NULL; + gog->last_gop = NULL; + + gog->num_of_gops = 0; + gog->num_of_counting_gops = 0; + gog->num_of_released_gops = 0; + + gog->gog_keys = g_ptr_array_new(); + + adopt_gop(gog,gop); + + return gog; +} + +static void apply_transforms(GPtrArray* transforms, AVPL* avpl) { + AVPL_Transf* transform = NULL; + guint i; + + for (i = 0; i < transforms->len; i++) { + transform = (AVPL_Transf *)g_ptr_array_index(transforms,i); + avpl_transform(avpl, transform); + } +} + + +/* applies the extras for which type to what avpl */ +static void apply_extras(AVPL* from, AVPL* to, AVPL* extras) { + AVPL* our_extras = new_avpl_loose_match("",from, extras, FALSE) ; + + if (our_extras) { + merge_avpl(to,our_extras,TRUE); + delete_avpl(our_extras,FALSE); + } +} + +static void gog_remove_keys (mate_gog* gog) { + gogkey* gog_key; + + while (gog->gog_keys->len) { + gog_key = (gogkey *)g_ptr_array_remove_index_fast(gog->gog_keys,0); + + if (g_hash_table_lookup(gog_key->cfg->gog_index,gog_key->key) == gog) { + g_hash_table_remove(gog_key->cfg->gog_index,gog_key->key); + } + + g_free(gog_key->key); + g_free(gog_key); + } + +} + +static void reanalyze_gop(mate_config* mc, mate_gop* gop) { + LoAL* gog_keys = NULL; + AVPL* curr_gogkey = NULL; + mate_cfg_gop* gop_cfg = NULL; + void* cookie = NULL; + AVPL* gogkey_match = NULL; + mate_gog* gog = gop->gog; + gogkey* gog_key; + + if ( ! gog ) return; + + gog->last_time = rd->now; + + dbg_print (dbg_gog,1,dbg_facility,"reanalyze_gop: %s:%d",gop->cfg->name,gop->id); + + apply_extras(gop->avpl,gog->avpl,gog->cfg->extra); + + /* XXX: Instead of using the length of the avpl to check if an avpl has changed, + which is not accurate at all, we should have apply_extras, + apply_transformations and other functions that can modify the avpl + to flag the avpl if it has changed, then we'll check for the flag + and clear it after analysis */ + + if (gog->last_n != gog->avpl->len) { + + dbg_print (dbg_gog,2,dbg_facility,"reanalyze_gop: gog has new attributes let's look for new keys"); + + gog_keys = gog->cfg->keys; + + while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) { + gop_cfg = (mate_cfg_gop *)g_hash_table_lookup(mc->gopcfgs,curr_gogkey->name); + + if (( gogkey_match = new_avpl_pairs_match(gop_cfg->name, gog->avpl, curr_gogkey, TRUE, FALSE) )) { + + gog_key = g_new(gogkey, 1); + + gog_key->key = avpl_to_str(gogkey_match); + delete_avpl(gogkey_match,FALSE); + + gog_key->cfg = gop_cfg; + + if (g_hash_table_lookup(gop_cfg->gog_index,gog_key->key)) { + g_free(gog_key->key); + g_free(gog_key); + gog_key = NULL; + } + + if (! gog_key ) { + /* XXX: since these gogs actually share key info + we should try to merge (non released) gogs + that happen to have equal keys */ + } else { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: new key for gog=%s:%d : %s",gog->cfg->name,gog->id,gog_key->key); + g_ptr_array_add(gog->gog_keys,gog_key); + g_hash_table_insert(gog_key->cfg->gog_index,gog_key->key,gog); + } + + } + } + + gog->last_n = gog->avpl->len; + } + + if (gog->num_of_released_gops == gog->num_of_counting_gops) { + gog->released = TRUE; + gog->expiration = gog->cfg->expiration + rd->now; + } else { + gog->released = FALSE; + } +} + +static void analyze_gop(mate_config* mc, mate_gop* gop) { + mate_cfg_gog* cfg = NULL; + LoAL* gog_keys = NULL; + AVPL* curr_gogkey = NULL; + void* cookie = NULL; + AVPL* gogkey_match = NULL; + mate_gog* gog = NULL; + gchar* key = NULL; + + if ( ! gop->gog ) { + /* no gog, let's either find one or create it if due */ + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no gog"); + + gog_keys = (LoAL *)g_hash_table_lookup(mc->gogs_by_gopname,gop->cfg->name); + + if ( ! gog_keys ) { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no gog_keys for this gop"); + return; + } + + /* We have gog_keys! look for matching gogkeys */ + + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got gog_keys: %s",gog_keys->name) ; + + while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) { + if (( gogkey_match = new_avpl_pairs_match(gop->cfg->name, gop->avpl, curr_gogkey, TRUE, TRUE) )) { + + key = avpl_to_str(gogkey_match); + + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got gogkey_match: %s",key); + + if (( gog = (mate_gog *)g_hash_table_lookup(gop->cfg->gog_index,key) )) { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: got already a matching gog"); + + if (gog->num_of_counting_gops == gog->num_of_released_gops && gog->expiration < rd->now) { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: this is a new gog, not the old one, let's create it"); + + gog_remove_keys(gog); + + new_gog(gog->cfg,gop); + + break; + } else { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: this is our gog"); + + if (! gop->gog ) adopt_gop(gog,gop); + + break; + } + } else { + dbg_print (dbg_gog,1,dbg_facility,"analyze_gop: no such gog in hash, let's create a new %s",curr_gogkey->name); + + cfg = (mate_cfg_gog *)g_hash_table_lookup(mc->gogcfgs,curr_gogkey->name); + + if (cfg) { + gog = new_gog(cfg,gop); + gog->num_of_gops = 1; + + if (gop->cfg->start) { + gog->num_of_counting_gops = 1; + } + + } else { + dbg_print (dbg_gog,0,dbg_facility,"analyze_gop: no such gog_cfg: %s",curr_gogkey->name); + } + + break; + } + + /** Can't get here because of "breaks" above */ + ws_assert_not_reached(); + } + } /* while */ + + g_free(key); + key = NULL; + + if (gogkey_match) delete_avpl(gogkey_match,TRUE); + + reanalyze_gop(mc, gop); + } +} + + + +static void analyze_pdu(mate_config* mc, mate_pdu* pdu) { + /* TODO: + return a g_boolean to tell we've destroyed the pdu when the pdu is unnassigned + destroy the unassigned pdu + */ + mate_cfg_gop* cfg = NULL; + mate_gop* gop = NULL; + gchar* gop_key; + gchar* orig_gop_key = NULL; + AVPL* candidate_start = NULL; + AVPL* candidate_stop = NULL; + AVPL* is_start = NULL; + AVPL* is_stop = NULL; + AVPL* gopkey_match = NULL; + LoAL* gog_keys = NULL; + AVPL* curr_gogkey = NULL; + void* cookie = NULL; + AVPL* gogkey_match = NULL; + gchar* gogkey_str = NULL; + + dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: %s",pdu->cfg->name); + + if (! (cfg = (mate_cfg_gop *)g_hash_table_lookup(mc->gops_by_pduname,pdu->cfg->name)) ) + return; + + if ((gopkey_match = new_avpl_pairs_match("gop_key_match", pdu->avpl, cfg->key, TRUE, TRUE))) { + gop_key = avpl_to_str(gopkey_match); + + g_hash_table_lookup_extended(cfg->gop_index,(gconstpointer)gop_key,(gpointer *)&orig_gop_key,(gpointer *)&gop); + + if ( gop ) { + g_free(gop_key); + + /* is the gop dead ? */ + if ( ! gop->released && + ( ( gop->cfg->lifetime > 0.0 && gop->time_to_die >= rd->now) || + ( gop->cfg->idle_timeout > 0.0 && gop->time_to_timeout >= rd->now) ) ) { + dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: expiring released gop"); + gop->released = TRUE; + + if (gop->gog && gop->cfg->start) gop->gog->num_of_released_gops++; + } + + /* TODO: is the gop expired? */ + + gop_key = orig_gop_key; + + dbg_print (dbg_gop,2,dbg_facility,"analyze_pdu: got gop: %s",gop_key); + + if (( candidate_start = cfg->start )) { + + dbg_print (dbg_gop,2,dbg_facility,"analyze_pdu: got candidate start"); + + if (( is_start = new_avpl_pairs_match("", pdu->avpl, candidate_start, TRUE, FALSE) )) { + delete_avpl(is_start,FALSE); + if ( gop->released ) { + dbg_print (dbg_gop,3,dbg_facility,"analyze_pdu: start on released gop, let's create a new gop"); + + g_hash_table_remove(cfg->gop_index,gop_key); + gop->gop_key = NULL; + gop = new_gop(cfg,pdu,gop_key); + g_hash_table_insert(cfg->gop_index,gop_key,gop); + } else { + dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: duplicate start on gop"); + } + } + } + + pdu->gop = gop; + + if (gop->last_pdu) gop->last_pdu->next = pdu; + gop->last_pdu = pdu; + pdu->next = NULL; + pdu->time_in_gop = rd->now - gop->start_time; + + if (gop->released) pdu->after_release = TRUE; + + } else { + + dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: no gop already"); + + if ( ! cfg->start ) { + /* there is no GopStart, we'll check for matching GogKeys + if we have one we'll create the Gop */ + + apply_extras(pdu->avpl,gopkey_match,cfg->extra); + + gog_keys = (LoAL *)g_hash_table_lookup(mc->gogs_by_gopname,cfg->name); + + if (gog_keys) { + + while (( curr_gogkey = get_next_avpl(gog_keys,&cookie) )) { + if (( gogkey_match = new_avpl_pairs_match(cfg->name, gopkey_match, curr_gogkey, TRUE, FALSE) )) { + gogkey_str = avpl_to_str(gogkey_match); + + if (g_hash_table_lookup(cfg->gog_index,gogkey_str)) { + gop = new_gop(cfg,pdu,gop_key); + g_hash_table_insert(cfg->gop_index,gop_key,gop); + delete_avpl(gogkey_match,FALSE); + g_free(gogkey_str); + break; + } else { + delete_avpl(gogkey_match,FALSE); + g_free(gogkey_str); + } + } + } + + if ( ! gop ) { + g_free(gop_key); + delete_avpl(gopkey_match,TRUE); + return; + } + + } else { + g_free(gop_key); + delete_avpl(gopkey_match,TRUE); + return; + } + + } else { + candidate_start = cfg->start; + + if (( is_start = new_avpl_pairs_match("", pdu->avpl, candidate_start, TRUE, FALSE) )) { + delete_avpl(is_start,FALSE); + gop = new_gop(cfg,pdu,gop_key); + } else { + g_free(gop_key); + return; + } + + pdu->gop = gop; + } + } + + if (gop->last_pdu) gop->last_pdu->next = pdu; + gop->last_pdu = pdu; + pdu->next = NULL; + + pdu->time_in_gop = rd->now - gop->start_time; + + gop->num_of_pdus++; + gop->time_to_timeout = cfg->idle_timeout > 0.0 ? cfg->idle_timeout + rd->now : (float) -1.0 ; + + dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: merge with key"); + + merge_avpl(gop->avpl,gopkey_match,TRUE); + delete_avpl(gopkey_match,TRUE); + + dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: apply extras"); + + apply_extras(pdu->avpl,gop->avpl,gop->cfg->extra); + + gop->last_time = pdu->rel_time; + + if ( ! gop->released) { + candidate_stop = cfg->stop; + + if (candidate_stop) { + is_stop = new_avpl_pairs_match("", pdu->avpl, candidate_stop, TRUE, FALSE); + } else { + is_stop = new_avpl(""); + } + + if(is_stop) { + dbg_print (dbg_gop,1,dbg_facility,"analyze_pdu: is a `stop"); + delete_avpl(is_stop,FALSE); + + if (! gop->released) { + gop->released = TRUE; + gop->release_time = pdu->rel_time; + if (gop->gog && gop->cfg->start) gop->gog->num_of_released_gops++; + } + + pdu->is_stop = TRUE; + + } + } + + if (gop->last_n != gop->avpl->len) apply_transforms(gop->cfg->transforms,gop->avpl); + + gop->last_n = gop->avpl->len; + + if (gop->gog) { + reanalyze_gop(mc, gop); + } else { + analyze_gop(mc, gop); + } + + } else { + dbg_print (dbg_gop,4,dbg_facility,"analyze_pdu: no match for this pdu"); + + pdu->gop = NULL; + } +} + +static void get_pdu_fields(gpointer k, gpointer v, gpointer p) { + int hfid = *((int*) k); + gchar* name = (gchar*) v; + tmp_pdu_data* data = (tmp_pdu_data*) p; + GPtrArray* fis; + field_info* fi; + guint i,j; + mate_range* curr_range; + guint start; + guint end; + AVP* avp; + gchar* s; + + + fis = proto_get_finfo_ptr_array(data->tree, hfid); + + if (fis) { + for (i = 0; i < fis->len; i++) { + fi = (field_info*) g_ptr_array_index(fis,i); + + + start = fi->start; + end = fi->start + fi->length; + + dbg_print(dbg_pdu,5,dbg_facility,"get_pdu_fields: found field %s, %i-%i, length %i", fi->hfinfo->abbrev, start, end, fi->length); + + for (j = 0; j < data->ranges->len; j++) { + + curr_range = (mate_range*) g_ptr_array_index(data->ranges,j); + + if (curr_range->end >= end && curr_range->start <= start) { + avp = new_avp_from_finfo(name, fi); + + if (*dbg_pdu > 4) { + s = avp_to_str(avp); + dbg_print(dbg_pdu,0,dbg_facility,"get_pdu_fields: got %s",s); + g_free(s); + } + + if (! insert_avp(data->pdu->avpl,avp) ) { + delete_avp(avp); + } + + } + } + } + } +} + +static void ptr_array_free(gpointer data, gpointer user_data _U_) +{ + g_free(data); +} + +static mate_pdu* new_pdu(mate_cfg_pdu* cfg, guint32 framenum, field_info* proto, proto_tree* tree) { + mate_pdu* pdu = (mate_pdu*)g_slice_new(mate_max_size); + field_info* cfi; + GPtrArray* ptrs; + mate_range* range; + mate_range* proto_range; + tmp_pdu_data data; + guint i,j; + gint min_dist; + field_info* range_fi; + gint32 last_start; + gint32 first_end; + gint32 curr_end; + int hfid; + + dbg_print (dbg_pdu,1,dbg_facility,"new_pdu: type=%s framenum=%i",cfg->name,framenum); + + pdu->id = ++(cfg->last_id); + pdu->cfg = cfg; + + pdu->avpl = new_avpl(cfg->name); + + pdu->frame = framenum; + pdu->next_in_frame = NULL; + pdu->rel_time = rd->now; + + pdu->gop = NULL; + pdu->next = NULL; + pdu->time_in_gop = -1.0f; + + pdu->first = FALSE; + pdu->is_start = FALSE; + pdu->is_stop = FALSE; + pdu->after_release = FALSE; + + data.ranges = g_ptr_array_new(); + data.pdu = pdu; + data.tree = tree; + + /* first we create the proto range */ + proto_range = g_new(mate_range, 1); + proto_range->start = proto->start; + proto_range->end = proto->start + proto->length; + g_ptr_array_add(data.ranges,proto_range); + + dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: proto range %u-%u",proto_range->start,proto_range->end); + + last_start = proto_range->start; + + /* we move forward in the tranport */ + for (i = cfg->transport_ranges->len; i--; ) { + hfid = *((int*)g_ptr_array_index(cfg->transport_ranges,i)); + ptrs = proto_get_finfo_ptr_array(tree, hfid); + min_dist = 99999; + range_fi = NULL; + + if (ptrs) { + for (j=0; j < ptrs->len; j++) { + cfi = (field_info*) g_ptr_array_index(ptrs,j); + if (cfi->start < last_start && min_dist >= (last_start - cfi->start) ) { + range_fi = cfi; + min_dist = last_start - cfi->start; + } + } + + if ( range_fi ) { + range = (mate_range *)g_malloc(sizeof(*range)); + range->start = range_fi->start; + range->end = range_fi->start + range_fi->length; + g_ptr_array_add(data.ranges,range); + + last_start = range_fi->start; + + dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: transport(%i) range %i-%i",hfid,range->start,range->end); + } else { + /* we missed a range */ + dbg_print(dbg_pdu,6,dbg_facility,"new_pdu: transport(%i) missed",hfid); + } + + } + } + + if (cfg->payload_ranges) { + + first_end = proto_range->end; + + for (i = 0 ; i < cfg->payload_ranges->len; i++) { + hfid = *((int*)g_ptr_array_index(cfg->payload_ranges,i)); + ptrs = proto_get_finfo_ptr_array(tree, hfid); + min_dist = 99999; + range_fi = NULL; + + if (ptrs) { + for (j=0; j < ptrs->len; j++) { + cfi = (field_info*) g_ptr_array_index(ptrs,j); + curr_end = cfi->start + cfi->length; + if (curr_end > first_end && min_dist >= (curr_end - first_end) ) { + range_fi = cfi; + min_dist = curr_end - first_end; + } + } + + if ( range_fi ) { + range = (mate_range *)g_malloc(sizeof(*range)); + range->start = range_fi->start; + range->end = range_fi->start + range_fi->length; + g_ptr_array_add(data.ranges,range); + + dbg_print(dbg_pdu,3,dbg_facility,"new_pdu: payload(%i) range %i-%i",hfid,range->start,range->end); + } else { + /* we missed a range */ + dbg_print(dbg_pdu,5,dbg_facility,"new_pdu: payload(%i) missed",hfid); + } + + } + } + } + + g_hash_table_foreach(cfg->hfids_attr,get_pdu_fields,&data); + + apply_transforms(pdu->cfg->transforms,pdu->avpl); + + g_ptr_array_foreach(data.ranges, ptr_array_free, NULL); + g_ptr_array_free(data.ranges,TRUE); + + return pdu; +} + + +extern void mate_analyze_frame(mate_config *mc, packet_info *pinfo, proto_tree* tree) { + mate_cfg_pdu* cfg; + GPtrArray* protos; + field_info* proto; + guint i,j; + AVPL* criterium_match; + + mate_pdu* pdu = NULL; + mate_pdu* last = NULL; + + rd->now = (float) nstime_to_sec(&pinfo->rel_ts); + + if ( proto_tracking_interesting_fields(tree) + && rd->highest_analyzed_frame < pinfo->num ) { + for ( i = 0; i < mc->pducfglist->len; i++ ) { + + cfg = (mate_cfg_pdu *)g_ptr_array_index(mc->pducfglist,i); + + dbg_print (dbg_pdu,4,dbg_facility,"mate_analyze_frame: trying to extract: %s",cfg->name); + protos = proto_get_finfo_ptr_array(tree, cfg->hfid_proto); + + if (protos) { + pdu = NULL; + + for (j = 0; j < protos->len; j++) { + + dbg_print (dbg_pdu,3,dbg_facility,"mate_analyze_frame: found matching proto, extracting: %s",cfg->name); + + proto = (field_info*) g_ptr_array_index(protos,j); + pdu = new_pdu(cfg, pinfo->num, proto, tree); + + if (cfg->criterium) { + criterium_match = new_avpl_from_match(cfg->criterium_match_mode,"",pdu->avpl,cfg->criterium,FALSE); + + if (criterium_match) { + delete_avpl(criterium_match,FALSE); + } + + if ( (criterium_match && cfg->criterium_accept_mode == REJECT_MODE ) + || ( ! criterium_match && cfg->criterium_accept_mode == ACCEPT_MODE )) { + + delete_avpl(pdu->avpl,TRUE); + g_slice_free(mate_max_size,(mate_max_size*)pdu); + pdu = NULL; + + continue; + } + } + + analyze_pdu(mc, pdu); + + if ( ! pdu->gop && cfg->drop_unassigned) { + delete_avpl(pdu->avpl,TRUE); + g_slice_free(mate_max_size,(mate_max_size*)pdu); + pdu = NULL; + continue; + } + + if ( cfg->discard ) { + delete_avpl(pdu->avpl,TRUE); + pdu->avpl = NULL; + } + + if (!last) { + g_hash_table_insert(rd->frames,GINT_TO_POINTER(pinfo->num),pdu); + last = pdu; + } else { + last->next_in_frame = pdu; + last = pdu; + } + + } + + if ( pdu && cfg->last_extracted ) break; + } + } + + rd->highest_analyzed_frame = pinfo->num; + } +} + +extern mate_pdu* mate_get_pdus(guint32 framenum) { + + if (rd) { + return (mate_pdu*) g_hash_table_lookup(rd->frames,GUINT_TO_POINTER(framenum)); + } else { + return NULL; + } +} + +/* + * 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: + */ diff --git a/plugins/epan/mate/mate_setup.c b/plugins/epan/mate/mate_setup.c new file mode 100644 index 00000000..eef97643 --- /dev/null +++ b/plugins/epan/mate/mate_setup.c @@ -0,0 +1,667 @@ +/* mate_setup.c + * MATE -- Meta Analysis Tracing Engine + * + * Copyright 2004, Luis E. Garcia Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include "mate.h" + +/* appends the formatted string to the current error log */ +static void report_error(mate_config* mc, const gchar* fmt, ...) { + static gchar error_buffer[DEBUG_BUFFER_SIZE]; + + va_list list; + + va_start( list, fmt ); + vsnprintf(error_buffer,DEBUG_BUFFER_SIZE,fmt,list); + va_end( list ); + + g_string_append(mc->config_error,error_buffer); + g_string_append_c(mc->config_error,'\n'); + +} + +/* creates a blank pdu config + is going to be called only by the grammar + which will set all those elements that aren't set here */ +extern mate_cfg_pdu* new_pducfg(mate_config* mc, gchar* name) { + mate_cfg_pdu* cfg = g_new(mate_cfg_pdu, 1); + + cfg->name = g_strdup(name); + cfg->last_id = 0; + + cfg->items = g_hash_table_new(g_direct_hash,g_direct_equal); + cfg->transforms = NULL; + + cfg->hfid = -1; + + cfg->hfid_pdu_rel_time = -1; + cfg->hfid_pdu_time_in_gop = -1; + + cfg->my_hfids = g_hash_table_new(g_str_hash,g_str_equal); + + cfg->ett = -1; + cfg->ett_attr = -1; + + cfg->criterium = NULL; + cfg->criterium_match_mode = AVPL_NO_MATCH; + cfg->criterium_accept_mode = ACCEPT_MODE; + + g_ptr_array_add(mc->pducfglist,(gpointer) cfg); + g_hash_table_insert(mc->pducfgs,(gpointer) cfg->name,(gpointer) cfg); + + cfg->hfids_attr = g_hash_table_new(g_int_hash,g_int_equal); + + return cfg; +} + +extern mate_cfg_gop* new_gopcfg(mate_config* mc, gchar* name) { + mate_cfg_gop* cfg = g_new(mate_cfg_gop, 1); + + cfg->name = g_strdup(name); + cfg->last_id = 0; + + cfg->items = g_hash_table_new(g_direct_hash,g_direct_equal); + cfg->transforms = NULL; + + cfg->extra = new_avpl("extra"); + + cfg->hfid = -1; + + cfg->ett = -1; + cfg->ett_attr = -1; + cfg->ett_times = -1; + cfg->ett_children = -1; + + cfg->hfid_start_time = -1; + cfg->hfid_stop_time = -1; + cfg->hfid_last_time = -1; + + cfg->hfid_gop_pdu = -1; + cfg->hfid_gop_num_pdus = -1; + + cfg->my_hfids = g_hash_table_new(g_str_hash,g_str_equal); + + cfg->gop_index = g_hash_table_new(g_str_hash,g_str_equal); + cfg->gog_index = g_hash_table_new(g_str_hash,g_str_equal); + + g_hash_table_insert(mc->gopcfgs,(gpointer) cfg->name, (gpointer) cfg); + + return cfg; +} + +extern mate_cfg_gog* new_gogcfg(mate_config* mc, gchar* name) { + mate_cfg_gog* cfg = g_new(mate_cfg_gog, 1); + + cfg->name = g_strdup(name); + cfg->last_id = 0; + + cfg->items = g_hash_table_new(g_direct_hash,g_direct_equal); + cfg->transforms = NULL; + + cfg->extra = new_avpl("extra"); + + cfg->my_hfids = g_hash_table_new(g_str_hash,g_str_equal); + cfg->hfid = -1; + + cfg->ett = -1; + cfg->ett_attr = -1; + cfg->ett_times = -1; + cfg->ett_children = -1; + cfg->ett_gog_gop = -1; + + cfg->hfid_gog_num_of_gops = -1; + cfg->hfid_gog_gop = -1; + cfg->hfid_gog_gopstart = -1; + cfg->hfid_gog_gopstop = -1; + + cfg->hfid_start_time = -1; + cfg->hfid_stop_time = -1; + cfg->hfid_last_time = -1; + + g_hash_table_insert(mc->gogcfgs,(gpointer) cfg->name, (gpointer) cfg); + + return cfg; +} + +extern gboolean add_hfid(mate_config* mc, header_field_info* hfi, gchar* how, GHashTable* where) { + header_field_info* first_hfi = NULL; + gboolean exists = FALSE; + gchar* as; + gchar* h; + int* ip; + + while(hfi) { + first_hfi = hfi; + hfi = (hfi->same_name_prev_id != -1) ? proto_registrar_get_nth(hfi->same_name_prev_id) : NULL; + } + + hfi = first_hfi; + + while (hfi) { + exists = TRUE; + ip = g_new(int, 1); + + *ip = hfi->id; + + if (( as = (gchar *)g_hash_table_lookup(where,ip) )) { + g_free(ip); + if (! g_str_equal(as,how)) { + report_error(mc, + "MATE Error: add field to Pdu: attempt to add %s(%i) as %s" + " failed: field already added as '%s'",hfi->abbrev,hfi->id,how,as); + return FALSE; + } + } else { + h = g_strdup(how); + g_hash_table_insert(where,ip,h); + } + + hfi = hfi->same_name_next; + + } + + if (! exists) { + report_error(mc, "MATE Error: cannot find field for attribute %s",how); + } + return exists; +} + +#if 0 +/* + * XXX - where is this suposed to be used? + */ +extern gchar* add_ranges(mate_config* mc, gchar* range,GPtrArray* range_ptr_arr) { + gchar** ranges; + guint i; + header_field_info* hfi; + int* hfidp; + + ranges = g_strsplit(range,"/",0); + + if (ranges) { + for (i=0; ranges[i]; i++) { + hfi = proto_registrar_get_byname(ranges[i]); + if (hfi) { + hfidp = g_new(int, 1); + *hfidp = hfi->id; + g_ptr_array_add(range_ptr_arr,(gpointer)hfidp); + } else { + g_strfreev(ranges); + return ws_strdup_printf("no such proto: '%s'",ranges[i]); + } + } + + g_strfreev(ranges); + } + + return NULL; +} +#endif + +static void new_attr_hfri(mate_config* mc, gchar* item_name, GHashTable* hfids, gchar* name) { + int* p_id = g_new(int, 1); + hf_register_info hfri; + + memset(&hfri, 0, sizeof hfri); + *p_id = -1; + hfri.p_id = p_id; + hfri.hfinfo.name = g_strdup(name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.%s",item_name,name); + hfri.hfinfo.type = FT_STRING; + hfri.hfinfo.display = BASE_NONE; + hfri.hfinfo.strings = NULL; + hfri.hfinfo.bitmask = 0; + hfri.hfinfo.blurb = ws_strdup_printf("%s attribute of %s",name,item_name); + + *p_id = -1; + g_hash_table_insert(hfids,name,p_id); + g_array_append_val(mc->hfrs,hfri); + +} + +typedef struct { + mate_config* mc; + mate_cfg_pdu* cfg; +} analyze_pdu_hfids_arg; + +static void analyze_pdu_hfids(gpointer k, gpointer v, gpointer p) { + analyze_pdu_hfids_arg* argp = (analyze_pdu_hfids_arg*)p; + mate_config* mc = argp->mc; + mate_cfg_pdu* cfg = argp->cfg; + new_attr_hfri(mc, cfg->name,cfg->my_hfids,(gchar*) v); + + /* + * Add this hfid to our table of wanted hfids. + */ + mc->wanted_hfids = g_array_append_val(mc->wanted_hfids, *(int *)k); + mc->num_fields_wanted++; +} + +static void analyze_transform_hfrs(mate_config* mc, gchar* name, GPtrArray* transforms, GHashTable* hfids) { + guint i; + void* cookie = NULL; + AVPL_Transf* t; + AVP* avp; + + for (i=0; i < transforms->len;i++) { + for (t = (AVPL_Transf *)g_ptr_array_index(transforms,i); t; t=t->next ) { + cookie = NULL; + while(( avp = get_next_avp(t->replace,&cookie) )) { + if (! g_hash_table_lookup(hfids,avp->n)) { + new_attr_hfri(mc, name,hfids,avp->n); + } + } + } + } +} + +static void analyze_pdu_config(mate_config* mc, mate_cfg_pdu* cfg) { + hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}}; + gint* ett; + analyze_pdu_hfids_arg arg; + + hfri.p_id = &(cfg->hfid); + hfri.hfinfo.name = g_strdup(cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s",cfg->name); + hfri.hfinfo.blurb = ws_strdup_printf("%s id",cfg->name); + hfri.hfinfo.type = FT_UINT32; + hfri.hfinfo.display = BASE_DEC; + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_pdu_rel_time); + hfri.hfinfo.name = ws_strdup_printf("%s time",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.RelativeTime",cfg->name); + hfri.hfinfo.type = FT_FLOAT; + hfri.hfinfo.display = BASE_NONE; + hfri.hfinfo.blurb = "Seconds passed since the start of capture"; + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_pdu_time_in_gop); + hfri.hfinfo.name = ws_strdup_printf("%s time since beginning of Gop",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.TimeInGop",cfg->name); + hfri.hfinfo.type = FT_FLOAT; + hfri.hfinfo.display = BASE_NONE; + hfri.hfinfo.blurb = "Seconds passed since the start of the GOP"; + + g_array_append_val(mc->hfrs,hfri); + + arg.mc = mc; + arg.cfg = cfg; + g_hash_table_foreach(cfg->hfids_attr,analyze_pdu_hfids,&arg); + + /* Add the hfids of transport protocols as wanted hfids */ + for (guint i = 0; i < cfg->transport_ranges->len; i++) { + int hfid = *((int*)g_ptr_array_index(cfg->transport_ranges,i)); + mc->wanted_hfids = g_array_append_val(mc->wanted_hfids, hfid); + mc->num_fields_wanted++; + } + + ett = &cfg->ett; + g_array_append_val(mc->ett,ett); + + ett = &cfg->ett_attr; + g_array_append_val(mc->ett,ett); + + analyze_transform_hfrs(mc, cfg->name,cfg->transforms,cfg->my_hfids); +} + +static void analyze_gop_config(gpointer k _U_, gpointer v, gpointer p) { + mate_config* mc = (mate_config*)p; + mate_cfg_gop* cfg = (mate_cfg_gop *)v; + void* cookie = NULL; + AVP* avp; + gint* ett; + hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}}; + + hfri.p_id = &(cfg->hfid); + hfri.hfinfo.name = g_strdup(cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s",cfg->name); + hfri.hfinfo.blurb = ws_strdup_printf("%s id",cfg->name); + hfri.hfinfo.type = FT_UINT32; + hfri.hfinfo.display = BASE_DEC; + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_start_time); + hfri.hfinfo.name = ws_strdup_printf("%s start time",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.StartTime",cfg->name); + hfri.hfinfo.type = FT_FLOAT; + hfri.hfinfo.display = BASE_NONE; + hfri.hfinfo.blurb = ws_strdup_printf("Seconds passed since the beginning of capture to the start of this %s",cfg->name); + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_stop_time); + hfri.hfinfo.name = ws_strdup_printf("%s hold time",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.Time",cfg->name); + hfri.hfinfo.blurb = ws_strdup_printf("Duration in seconds from start to stop of this %s",cfg->name); + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_last_time); + hfri.hfinfo.name = ws_strdup_printf("%s duration",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.Duration",cfg->name); + hfri.hfinfo.blurb = ws_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name); + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gop_num_pdus); + hfri.hfinfo.name = ws_strdup_printf("%s number of PDUs",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.NumOfPdus",cfg->name); + hfri.hfinfo.blurb = ws_strdup_printf("Number of PDUs assigned to this %s",cfg->name); + hfri.hfinfo.type = FT_UINT32; + hfri.hfinfo.display = BASE_DEC; + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gop_pdu); + hfri.hfinfo.name = ws_strdup_printf("A PDU of %s",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.Pdu",cfg->name); + hfri.hfinfo.blurb = ws_strdup_printf("A PDU assigned to this %s",cfg->name); + + if (cfg->pdu_tree_mode == GOP_FRAME_TREE) { + hfri.hfinfo.type = FT_FRAMENUM; + hfri.hfinfo.display = BASE_NONE; + g_array_append_val(mc->hfrs,hfri); + } else if (cfg->pdu_tree_mode == GOP_PDU_TREE) { + hfri.hfinfo.type = FT_UINT32; + g_array_append_val(mc->hfrs,hfri); + } else { + cfg->pdu_tree_mode = GOP_NO_TREE; + } + + while(( avp = get_next_avp(cfg->key,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(mc, cfg->name,cfg->my_hfids,avp->n); + } + } + + if(cfg->start) { + cookie = NULL; + while(( avp = get_next_avp(cfg->start,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(mc, cfg->name,cfg->my_hfids,avp->n); + } + } + } + + if (cfg->stop) { + cookie = NULL; + while(( avp = get_next_avp(cfg->stop,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(mc, cfg->name,cfg->my_hfids,avp->n); + } + } + } + + cookie = NULL; + while(( avp = get_next_avp(cfg->extra,&cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(mc, cfg->name,cfg->my_hfids,avp->n); + } + } + + analyze_transform_hfrs(mc, cfg->name,cfg->transforms,cfg->my_hfids); + + ett = &cfg->ett; + g_array_append_val(mc->ett,ett); + + ett = &cfg->ett_attr; + g_array_append_val(mc->ett,ett); + + ett = &cfg->ett_times; + g_array_append_val(mc->ett,ett); + + ett = &cfg->ett_children; + g_array_append_val(mc->ett,ett); + + g_hash_table_insert(mc->gops_by_pduname,cfg->name,cfg); +} + +static void analyze_gog_config(gpointer k _U_, gpointer v, gpointer p) { + mate_config* mc = (mate_config*)p; + mate_cfg_gog* cfg = (mate_cfg_gog *)v; + void* avp_cookie; + void* avpl_cookie; + AVP* avp; + AVPL* avpl; + AVPL* gopkey_avpl; + AVPL* key_avps; + LoAL* gog_keys = NULL; + hf_register_info hfri = { NULL, {NULL, NULL, FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL}}; + gint* ett; + + /* create the hf array for this gog */ + hfri.p_id = &(cfg->hfid); + hfri.hfinfo.name = g_strdup(cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s",cfg->name); + hfri.hfinfo.blurb = ws_strdup_printf("%s Id",cfg->name); + hfri.hfinfo.type = FT_UINT32; + hfri.hfinfo.display = BASE_DEC; + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gog_num_of_gops); + hfri.hfinfo.name = "number of GOPs"; + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.NumOfGops",cfg->name); + hfri.hfinfo.type = FT_UINT32; + hfri.hfinfo.display = BASE_DEC; + hfri.hfinfo.blurb = ws_strdup_printf("Number of GOPs assigned to this %s",cfg->name); + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gog_gopstart); + hfri.hfinfo.name = "GopStart frame"; + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.GopStart",cfg->name); + hfri.hfinfo.type = FT_FRAMENUM; + hfri.hfinfo.display = BASE_NONE; + hfri.hfinfo.blurb = g_strdup("The start frame of a GOP"); + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_gog_gopstop); + hfri.hfinfo.name = "GopStop frame"; + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.GopStop",cfg->name); + hfri.hfinfo.type = FT_FRAMENUM; + hfri.hfinfo.display = BASE_NONE; + hfri.hfinfo.blurb = g_strdup("The stop frame of a GOP"); + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_start_time); + hfri.hfinfo.name = ws_strdup_printf("%s start time",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.StartTime",cfg->name); + hfri.hfinfo.type = FT_FLOAT; + hfri.hfinfo.blurb = ws_strdup_printf("Seconds passed since the beginning of capture to the start of this %s",cfg->name); + + g_array_append_val(mc->hfrs,hfri); + + hfri.p_id = &(cfg->hfid_last_time); + hfri.hfinfo.name = ws_strdup_printf("%s duration",cfg->name); + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.Duration",cfg->name); + hfri.hfinfo.blurb = ws_strdup_printf("Time passed between the start of this %s and the last pdu assigned to it",cfg->name); + + g_array_append_val(mc->hfrs,hfri); + + /* this might become mate.gogname.gopname */ + hfri.p_id = &(cfg->hfid_gog_gop); + hfri.hfinfo.name = "a GOP"; + hfri.hfinfo.abbrev = ws_strdup_printf("mate.%s.Gop",cfg->name); + hfri.hfinfo.type = FT_STRING; + hfri.hfinfo.display = BASE_NONE; + hfri.hfinfo.blurb = ws_strdup_printf("a GOPs assigned to this %s",cfg->name); + + g_array_append_val(mc->hfrs,hfri); + + /* index the keys of gog for every gop + and insert the avps of the keys to the hfarray */ + key_avps = new_avpl(""); + + avpl_cookie = NULL; + while (( avpl = get_next_avpl(cfg->keys,&avpl_cookie) )) { + + if (! ( gog_keys = (LoAL *)g_hash_table_lookup(mc->gogs_by_gopname,avpl->name))) { + gog_keys = new_loal(avpl->name); + g_hash_table_insert(mc->gogs_by_gopname,gog_keys->name,gog_keys); + } + + gopkey_avpl = new_avpl_from_avpl(cfg->name, avpl, TRUE); + loal_append(gog_keys,gopkey_avpl); + + avp_cookie = NULL; + while (( avp = get_next_avp(avpl,&avp_cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(mc, cfg->name,cfg->my_hfids,avp->n); + insert_avp(key_avps,avp); + } + } + } + + /* insert the extra avps to the hfarray */ + avp_cookie = NULL; + while (( avp = get_next_avp(cfg->extra,&avp_cookie) )) { + if (! g_hash_table_lookup(cfg->my_hfids,avp->n)) { + new_attr_hfri(mc, cfg->name,cfg->my_hfids,avp->n); + } + } + + /* every key_avp ios an extra as well. + one day every Member will have its own extras */ + merge_avpl(cfg->extra,key_avps,TRUE); + + + analyze_transform_hfrs(mc, cfg->name,cfg->transforms,cfg->my_hfids); + + ett = &cfg->ett; + g_array_append_val(mc->ett,ett); + + ett = &cfg->ett_attr; + g_array_append_val(mc->ett,ett); + + ett = &cfg->ett_children; + g_array_append_val(mc->ett,ett); + + ett = &cfg->ett_times; + g_array_append_val(mc->ett,ett); + + ett = &cfg->ett_gog_gop; + g_array_append_val(mc->ett,ett); + +} + +static void analyze_config(mate_config* mc) { + guint i; + + for (i=0; i < mc->pducfglist->len; i++) { + analyze_pdu_config(mc, (mate_cfg_pdu*) g_ptr_array_index(mc->pducfglist,i)); + } + + g_hash_table_foreach(mc->gopcfgs,analyze_gop_config,mc); + g_hash_table_foreach(mc->gogcfgs,analyze_gog_config,mc); + +} + +extern mate_config* mate_make_config(const gchar* filename, int mate_hfid) { + mate_config* mc; + gint* ett; + avp_init(); + + mc = g_new(mate_config, 1); + + mc->hfid_mate = mate_hfid; + + mc->wanted_hfids = g_array_new(FALSE, FALSE, (guint)sizeof(int)); + mc->num_fields_wanted = 0; + + mc->dbg_facility = NULL; + + mc->mate_lib_path = ws_strdup_printf("%s%c%s%c",get_datafile_dir(),DIR_SEP,DEFAULT_MATE_LIB_PATH,DIR_SEP); + + mc->pducfgs = g_hash_table_new(g_str_hash,g_str_equal); + mc->gopcfgs = g_hash_table_new(g_str_hash,g_str_equal); + mc->gogcfgs = g_hash_table_new(g_str_hash,g_str_equal); + mc->transfs = g_hash_table_new(g_str_hash,g_str_equal); + + mc->pducfglist = g_ptr_array_new(); + mc->gops_by_pduname = g_hash_table_new(g_str_hash,g_str_equal); + mc->gogs_by_gopname = g_hash_table_new(g_str_hash,g_str_equal); + + mc->ett_root = -1; + + mc->hfrs = g_array_new(FALSE,FALSE,sizeof(hf_register_info)); + mc->ett = g_array_new(FALSE,FALSE,sizeof(gint*)); + + mc->defaults.pdu.drop_unassigned = FALSE; + mc->defaults.pdu.discard = FALSE; + mc->defaults.pdu.last_extracted = FALSE; + mc->defaults.pdu.match_mode = AVPL_STRICT; + mc->defaults.pdu.replace_mode = AVPL_INSERT; + + /* gop prefs */ + mc->defaults.gop.expiration = -1.0f; + mc->defaults.gop.idle_timeout = -1.0f; + mc->defaults.gop.lifetime = -1.0f; + mc->defaults.gop.pdu_tree_mode = GOP_FRAME_TREE; + mc->defaults.gop.show_times = TRUE; + mc->defaults.gop.drop_unassigned = FALSE; + + /* gog prefs */ + mc->defaults.gog.expiration = 5.0f; + mc->defaults.gog.show_times = TRUE; + mc->defaults.gog.gop_tree_mode = GOP_BASIC_TREE; + + /* what to dbgprint */ + mc->dbg_lvl = 0; + mc->dbg_pdu_lvl = 0; + mc->dbg_gop_lvl = 0; + mc->dbg_gog_lvl = 0; + + mc->config_error = g_string_new(""); + + ett = &mc->ett_root; + g_array_append_val(mc->ett,ett); + + if ( mate_load_config(filename,mc) ) { + analyze_config(mc); + } else { + report_failure("MATE failed to configure!\n" + "It is recommended that you fix your config and restart Wireshark.\n" + "The reported error is:\n%s\n",mc->config_error->str); + + /* if (mc) destroy_mate_config(mc,FALSE); */ + return NULL; + } + + if (mc->num_fields_wanted == 0) { + /* We have no interest in any fields, so we have no + work to do. */ + /*destroy_mate_config(mc,FALSE);*/ + return NULL; + } + + return mc; +} + +/* + * 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: + */ diff --git a/plugins/epan/mate/mate_util.c b/plugins/epan/mate/mate_util.c new file mode 100644 index 00000000..5b4d0780 --- /dev/null +++ b/plugins/epan/mate/mate_util.c @@ -0,0 +1,1690 @@ +/* mate_util.c + * MATE -- Meta Analysis Tracing Engine + * Utility Library: Single Copy Strings and Attribute Value Pairs + * + * Copyright 2004, Luis E. Garcia Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include "mate.h" +#include "mate_util.h" + +#include +#include + + +/*************************************************************************** +* dbg_print +*************************************************************************** +* This is the debug facility of the thing. +***************************************************************************/ + +/* dbg_print: + * which: a pointer to the current level of debugging for a feature + * how: the level over which this message should be printed out + * where: the file on which to print (ws_message if null) + * fmt, ...: what to print + */ + +void dbg_print(const gint* which, gint how, FILE* where, const gchar* fmt, ... ) { + static gchar debug_buffer[DEBUG_BUFFER_SIZE]; + va_list list; + + if ( ! which || *which < how ) return; + + va_start( list, fmt ); + vsnprintf(debug_buffer,DEBUG_BUFFER_SIZE,fmt,list); + va_end( list ); + + if (! where) { + ws_message("%s", debug_buffer); + } else { + fputs(debug_buffer,where); + fputs("\n",where); + } + +} + +/*************************************************************************** + * single copy strings + *************************************************************************** + * Strings repeat more often than don't. In order to save memory + * we'll keep only one copy of each as key to a hash with a count of + * subscribers as value. + ***************************************************************************/ + +/** + * scs_init: + * + * Initializes the scs hash. + **/ + +struct _scs_collection { + GHashTable* hash; /* key: a string value: guint number of subscribers */ +}; + +/* ToDo? free any string,ctr entries pointed to by the hash table ?? + * XXX: AFAIKT destroy_scs_collection() might be called only when reading a + * mate config file. Since reading a new config file can apparently currently + * only be done once after starting Wireshark, in theory this fcn + * currently should never be called since there will never be an existing + * scs_collection to be destroyed. + */ +static void destroy_scs_collection(SCS_collection* c) { + if (c->hash) g_hash_table_destroy(c->hash); +} + +static SCS_collection* scs_init(void) { + SCS_collection* c = g_new(SCS_collection, 1); + + c->hash = g_hash_table_new(g_str_hash,g_str_equal); + + return c; +} + + +/** + * subscribe: + * @param c the scs hash + * @param s a string + * + * Checks if the given string exists already and if so it increases the count of + * subsscribers and returns a pointer to the stored string. If not It will copy + * the given string store it in the hash and return the pointer to the copy. + * Remember, containment is handled internally, take care of your own strings. + * + * Return value: a pointer to the subscribed string. + **/ +gchar* scs_subscribe(SCS_collection* c, const gchar* s) { + gchar* orig = NULL; + guint* ip = NULL; + size_t len = 0; + + g_hash_table_lookup_extended(c->hash,(gconstpointer)s,(gpointer *)&orig,(gpointer *)&ip); + + if (ip) { + (*ip)++; + } else { + ip = g_slice_new(guint); + *ip = 0; + + len = strlen(s) + 1; + + if (len <= SCS_SMALL_SIZE) { + len = SCS_SMALL_SIZE; + } else if (len <= SCS_MEDIUM_SIZE) { + len = SCS_MEDIUM_SIZE; + } else if (len <= SCS_LARGE_SIZE) { + len = SCS_LARGE_SIZE; + } else if (len < SCS_HUGE_SIZE) { + len = SCS_HUGE_SIZE; + } else { + len = SCS_HUGE_SIZE; + ws_warning("mate SCS: string truncated due to huge size"); + } + + orig = (gchar *)g_slice_alloc(len); + (void) g_strlcpy(orig,s,len); + + g_hash_table_insert(c->hash,orig,ip); + } + + return orig; +} + +/** + * unsubscribe: + * @param c the scs hash + * @param s a string. + * + * decreases the count of subscribers, if zero frees the internal copy of + * the string. + **/ +void scs_unsubscribe(SCS_collection* c, gchar* s) { + gchar* orig = NULL; + guint* ip = NULL; + size_t len = 0xffff; + + g_hash_table_lookup_extended(c->hash,(gconstpointer)s,(gpointer *)&orig,(gpointer *)&ip); + + if (ip) { + if (*ip == 0) { + g_hash_table_remove(c->hash,orig); + + len = strlen(orig); + + if (len < SCS_SMALL_SIZE) { + len = SCS_SMALL_SIZE; + } else if (len < SCS_MEDIUM_SIZE) { + len = SCS_MEDIUM_SIZE; + } else if (len < SCS_LARGE_SIZE) { + len = SCS_LARGE_SIZE; + } else { + len = SCS_HUGE_SIZE; + } + + g_slice_free1(len, orig); + g_slice_free(guint,ip); + } + else { + (*ip)--; + } + } else { + ws_warning("unsubscribe: not subscribed"); + } +} + +/** + * scs_subscribe_printf: + * @param fmt a format string ... + * + * Formats the input and subscribes it. + * + * Return value: the stored copy of the formated string. + * + **/ +gchar* scs_subscribe_printf(SCS_collection* c, gchar* fmt, ...) { + va_list list; + static gchar buf[SCS_HUGE_SIZE]; + + va_start( list, fmt ); + vsnprintf(buf, SCS_HUGE_SIZE, fmt, list); + va_end( list ); + + return scs_subscribe(c,buf); +} + +/*************************************************************************** +* AVPs & Co. +*************************************************************************** +* The Thing operates mainly on avps, avpls and loals +* - attribute value pairs (two strings: the name and the value and an operator) +* - avp lists a somehow sorted list of avps +* - loal (list of avp lists) an arbitrarily sorted list of avpls +* +* +***************************************************************************/ + + +typedef union _any_avp_type { + AVP avp; + AVPN avpn; + AVPL avpl; + LoAL loal; + LoALnode loaln; +} any_avp_type; + + +static SCS_collection* avp_strings = NULL; + +#ifdef _AVP_DEBUGGING +static FILE* dbg_fp = NULL; + +static int dbg_level = 0; +static int* dbg = &dbg_level; + +static int dbg_avp_level = 0; +static int* dbg_avp = &dbg_avp_level; + +static int dbg_avp_op_level = 0; +static int* dbg_avp_op = &dbg_avp_op_level; + +static int dbg_avpl_level = 0; +static int* dbg_avpl = &dbg_avpl_level; + +static int dbg_avpl_op_level = 0; +static int* dbg_avpl_op = &dbg_avpl_op_level; + +/** + * setup_avp_debug: + * @param fp the file in which to send debugging output. + * @param general a pointer to the level of debugging of facility "general" + * @param avp a pointer to the level of debugging of facility "avp" + * @param avp_op a pointer to the level of debugging of facility "avp_op" + * @param avpl a pointer to the level of debugging of facility "avpl" + * @param avpl_op a pointer to the level of debugging of facility "avpl_op" + * + * If enabled sets up the debug facilities for the avp library. + * + **/ +extern void setup_avp_debug(FILE* fp, int* general, int* avp, int* avp_op, int* avpl, int* avpl_op) { + dbg_fp = fp; + dbg = general; + dbg_avp = avp; + dbg_avp_op = avp_op; + dbg_avpl = avpl; + dbg_avpl_op = avpl_op; +} + +#endif /* _AVP_DEBUGGING */ + +/** + * avp_init: + * + * (Re)Initializes the avp library. + * + **/ +extern void avp_init(void) { + + if (avp_strings) destroy_scs_collection(avp_strings); + avp_strings = scs_init(); + +} + +/** + * new_avp_from_finfo: + * @param name the name the avp will have. + * @param finfo the field_info from which to fetch the data. + * + * Creates an avp from a field_info record. + * + * Return value: a pointer to the newly created avp. + * + **/ +extern AVP* new_avp_from_finfo(const gchar* name, field_info* finfo) { + AVP* new_avp_val = (AVP*)g_slice_new(any_avp_type); + gchar* value; + gchar* repr; + + new_avp_val->n = scs_subscribe(avp_strings, name); + + repr = fvalue_to_string_repr(NULL, finfo->value, FTREPR_DISPLAY, finfo->hfinfo->display); + + if (repr) { + value = scs_subscribe(avp_strings, repr); + wmem_free(NULL, repr); +#ifdef _AVP_DEBUGGING + dbg_print (dbg_avp,2,dbg_fp,"new_avp_from_finfo: from string: %s",value); +#endif + } else { +#ifdef _AVP_DEBUGGING + dbg_print (dbg_avp,2,dbg_fp,"new_avp_from_finfo: a proto: %s",finfo->hfinfo->abbrev); +#endif + value = scs_subscribe(avp_strings, ""); + } + + new_avp_val->v = value; + + new_avp_val->o = '='; + +#ifdef _AVP_DEBUGGING + dbg_print (dbg_avp,1,dbg_fp,"new_avp_from_finfo: %p %s%c%s;",new_avp_val,new_avp_val->n,new_avp_val->o,new_avp_val->v); +#endif + + return new_avp_val; +} + + +/** + * new_avp: + * @param name the name the avp will have. + * @param value the value the avp will have. + * @param o the operator of this avp. + * + * Creates an avp given every parameter. + * + * Return value: a pointer to the newly created avp. + * + **/ +extern AVP* new_avp(const gchar* name, const gchar* value, gchar o) { + AVP* new_avp_val = (AVP*)g_slice_new(any_avp_type); + + new_avp_val->n = scs_subscribe(avp_strings, name); + new_avp_val->v = scs_subscribe(avp_strings, value); + new_avp_val->o = o; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avp,1,dbg_fp,"new_avp_val: %p %s%c%s;",new_avp_val,new_avp_val->n,new_avp_val->o,new_avp_val->v); +#endif + return new_avp_val; +} + + +/** +* delete_avp: + * @param avp the avp to delete. + * + * Destroys an avp and releases the resources it uses. + * + **/ +extern void delete_avp(AVP* avp) { +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avp,1,dbg_fp,"delete_avp: %p %s%c%s;",avp,avp->n,avp->o,avp->v); +#endif + + scs_unsubscribe(avp_strings, avp->n); + scs_unsubscribe(avp_strings, avp->v); + g_slice_free(any_avp_type,(any_avp_type*)avp); +} + + +/** +* avp_copy: + * @param from the avp to be copied. + * + * Creates an avp whose name op and value are copies of the given one. + * + * Return value: a pointer to the newly created avp. + * + **/ +extern AVP* avp_copy(AVP* from) { + AVP* new_avp_val = (AVP*)g_slice_new(any_avp_type); + + new_avp_val->n = scs_subscribe(avp_strings, from->n); + new_avp_val->v = scs_subscribe(avp_strings, from->v); + new_avp_val->o = from->o; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avp,1,dbg_fp,"copy_avp: %p %s%c%s;",new_avp_val,new_avp_val->n,new_avp_val->o,new_avp_val->v); +#endif + + return new_avp_val; +} + +/** + * new_avpl: + * @param name the name the avpl will have. + * + * Creates an empty avpl. + * + * Return value: a pointer to the newly created avpl. + * + **/ +extern AVPL* new_avpl(const gchar* name) { + AVPL* new_avpl_p = (AVPL*)g_slice_new(any_avp_type); + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"new_avpl_p: %p name=%s",new_avpl_p,name); +#endif + + new_avpl_p->name = name ? scs_subscribe(avp_strings, name) : scs_subscribe(avp_strings, ""); + new_avpl_p->len = 0; + new_avpl_p->null.avp = NULL; + new_avpl_p->null.next = &new_avpl_p->null; + new_avpl_p->null.prev = &new_avpl_p->null; + + + return new_avpl_p; +} + +extern void rename_avpl(AVPL* avpl, gchar* name) { + scs_unsubscribe(avp_strings,avpl->name); + avpl->name = scs_subscribe(avp_strings,name); +} + +/** + * insert_avp_before_node: + * @param avpl the avpl in which to insert. + * @param next_node the next node before which the new avpn has to be inserted. + * @param avp the avp to be inserted. + * @param copy_avp whether the original AVP or a copy thereof must be inserted. + * + * Pre-condition: the avp is sorted before before_avp and does not already exist + * in the avpl. + */ +static void insert_avp_before_node(AVPL* avpl, AVPN* next_node, AVP *avp, gboolean copy_avp) { + AVPN* new_avp_val = (AVPN*)g_slice_new(any_avp_type); + + new_avp_val->avp = copy_avp ? avp_copy(avp) : avp; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"new_avpn: %p",new_avp_val); + dbg_print(dbg_avpl,5,dbg_fp,"insert_avp: inserting %p in %p before %p;",avp,avpl,next_node); +#endif + + new_avp_val->next = next_node; + new_avp_val->prev = next_node->prev; + next_node->prev->next = new_avp_val; + next_node->prev = new_avp_val; + + avpl->len++; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,4,dbg_fp,"avpl: %p new len: %i",avpl,avpl->len); +#endif +} + +/** + * insert_avp: + * @param avpl the avpl in which to insert. + * @param avp the avp to be inserted. + * + * Inserts the given AVP into the given AVPL if an identical one isn't yet there. + * + * Return value: whether it was inserted or not. + * + * BEWARE: Check the return value, you might need to delete the avp if + * it is not inserted. + **/ +extern gboolean insert_avp(AVPL* avpl, AVP* avp) { + AVPN* c; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,4,dbg_fp,"insert_avp: %p %p %s%c%s;",avpl,avp,avp->n,avp->o,avp->v); +#endif + + /* get to the insertion point */ + for (c=avpl->null.next; c->avp; c = c->next) { + int name_diff = strcmp(avp->n, c->avp->n); + + if (name_diff == 0) { + int value_diff = strcmp(avp->v, c->avp->v); + + if (value_diff < 0) { + break; + } + + if (value_diff == 0) { + // ignore duplicate values, prevents (a=1, a=1) + // note that this is also used to insert + // conditions AVPs, so really check if the name, + // value and operator are all equal. + if (c->avp->o == avp->o && avp->o == AVP_OP_EQUAL) { + return FALSE; + } + } + } + + if (name_diff < 0) { + break; + } + } + + insert_avp_before_node(avpl, c, avp, FALSE); + + return TRUE; +} + +/** + * get_avp_by_name: + * @param avpl the avpl from which to try to get the avp. + * @param name the name of the avp we are looking for. + * @param cookie variable in which to store the state between calls. + * + * Gets pointer to the next avp whose name is given; uses cookie to store its + * state between calls. + * + * Return value: a pointer to the next matching avp if there's one, else NULL. + * + **/ +extern AVP* get_avp_by_name(AVPL* avpl, gchar* name, void** cookie) { + AVPN* curr; + AVPN* start = (AVPN*) *cookie; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"get_avp_by_name: entering: %p %s %p",avpl,name,*cookie); +#endif + + name = scs_subscribe(avp_strings, name); + + if (!start) start = avpl->null.next; + + for ( curr = start; curr->avp; curr = curr->next ) { + if ( curr->avp->n == name ) { + break; + } + } + + *cookie = curr; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"get_avp_by_name: got avp: %p",curr); +#endif + + scs_unsubscribe(avp_strings, name); + + return curr->avp; +} + +/** + * extract_avp_by_name: + * @param avpl the avpl from which to try to extract the avp. + * @param name the name of the avp we are looking for. + * + * Extracts from the avpl the next avp whose name is given; + * + * Return value: a pointer to extracted avp if there's one, else NULL. + * + **/ +extern AVP* extract_avp_by_name(AVPL* avpl, gchar* name) { + AVPN* curr; + AVP* avp = NULL; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"extract_avp_by_name: entering: %p %s",avpl,name); +#endif + + name = scs_subscribe(avp_strings, name); + + for ( curr = avpl->null.next; curr->avp; curr = curr->next ) { + if ( curr->avp->n == name ) { + break; + } + } + + scs_unsubscribe(avp_strings, name); + + if( ! curr->avp ) return NULL; + + curr->next->prev = curr->prev; + curr->prev->next = curr->next; + + avp = curr->avp; + + g_slice_free(any_avp_type,(any_avp_type*)curr); + + (avpl->len)--; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,4,dbg_fp,"avpl: %p new len: %i",avpl,avpl->len); +#endif + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"extract_avp_by_name: got avp: %p",avp); +#endif + + return avp; +} + + +/** + * extract_first_avp: + * @param avpl the avpl from which to try to extract the avp. + * + * Extracts the fisrt avp from the avpl. + * + * Return value: a pointer to extracted avp if there's one, else NULL. + * + **/ +extern AVP* extract_first_avp(AVPL* avpl) { + AVP* avp; + AVPN* node; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,7,dbg_fp,"extract_first_avp: %p",avpl); +#endif + + node = avpl->null.next; + + avpl->null.next->prev = &avpl->null; + avpl->null.next = node->next; + + avp = node->avp; + + if (avp) { + g_slice_free(any_avp_type,(any_avp_type*)node); + (avpl->len)--; +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,4,dbg_fp,"avpl: %p new len: %i",avpl,avpl->len); +#endif + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"extract_first_avp: got avp: %p",avp); +#endif + + return avp; + +} + + +/** + * extract_last_avp: + * @param avpl the avpl from which to try to extract the avp. + * + * Extracts the last avp from the avpl. + * + * Return value: a pointer to extracted avp if there's one, else NULL. + * + **/ +extern AVP* extract_last_avp(AVPL* avpl) { + AVP* avp; + AVPN* node; + + node = avpl->null.prev; + + avpl->null.prev->next = &avpl->null; + avpl->null.prev = node->prev; + + avp = node->avp; + + if (avp) { + g_slice_free(any_avp_type,(any_avp_type*)node); + (avpl->len)--; +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,4,dbg_fp,"avpl: %p new len: %i",avpl,avpl->len); +#endif + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"extract_last_avp: got avp: %p",avp); +#endif + + return avp; + +} + + +/** + * delete_avpl: + * @param avpl the avpl from which to try to extract the avp. + * @param avps_too whether or not it should delete the avps as well. + * + * Destroys an avpl and releases the resources it uses. If told to do + * so releases the avps as well. + * + **/ +extern void delete_avpl(AVPL* avpl, gboolean avps_too) { + AVP* avp; +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl,3,dbg_fp,"delete_avpl: %p",avpl); +#endif + + while(( avp = extract_last_avp(avpl))) { + if (avps_too) { + delete_avp(avp); + } + } + + scs_unsubscribe(avp_strings,avpl->name); + g_slice_free(any_avp_type,(any_avp_type*)avpl); +} + + + +/** + * get_next_avp: + * @param avpl the avpl from which to try to get the avps. + * @param cookie variable in which to store the state between calls. + * + * Iterates on an avpl to get its avps. + * + * Return value: a pointer to the next avp if there's one, else NULL. + * + **/ +extern AVP* get_next_avp(AVPL* avpl, void** cookie) { + AVPN* node; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"get_next_avp: avpl: %p avpn: %p",avpl,*cookie); +#endif + + if (*cookie) { + node = (AVPN*) *cookie; + } else { + node = avpl->null.next; + } + + *cookie = node->next; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,5,dbg_fp,"extract_last_avp: got avp: %p",node->avp); +#endif + + return node->avp; +} + +/** + * avpl_to_str: + * @param avpl the avpl to represent. + * + * Creates a newly allocated string containing a representation of an avpl. + * + * Return value: a pointer to the newly allocated string. + * + **/ +gchar* avpl_to_str(AVPL* avpl) { + AVPN* c; + GString* s = g_string_new(""); + gchar* avp_s; + gchar* r; + + for(c=avpl->null.next; c->avp; c = c->next) { + avp_s = avp_to_str(c->avp); + g_string_append_printf(s," %s;",avp_s); + g_free(avp_s); + } + + r = g_string_free(s,FALSE); + + /* g_strchug(r); ? */ + return r; +} + +extern gchar* avpl_to_dotstr(AVPL* avpl) { + AVPN* c; + GString* s = g_string_new(""); + gchar* avp_s; + gchar* r; + + for(c=avpl->null.next; c->avp; c = c->next) { + avp_s = avp_to_str(c->avp); + g_string_append_printf(s," .%s;",avp_s); + g_free(avp_s); + } + + r = g_string_free(s,FALSE); + + /* g_strchug(r); ? */ + return r; +} + +/** +* merge_avpl: + * @param dst the avpl in which to merge the avps. + * @param src the avpl from which to get the avps. + * @param copy_avps whether avps should be copied instead of referenced. + * + * Adds the avps of src that are not existent in dst into dst. + * + **/ +extern void merge_avpl(AVPL* dst, AVPL* src, gboolean copy_avps) { + AVPN* cd = NULL; + AVPN* cs = NULL; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"merge_avpl: %p %p",dst,src); +#endif + + cs = src->null.next; + cd = dst->null.next; + + while (cs->avp && cd->avp) { + + int name_diff = strcmp(cd->avp->n, cs->avp->n); + + if (name_diff < 0) { + // dest < source, advance dest to find a better place to insert + cd = cd->next; + } else if (name_diff > 0) { + // dest > source, so it can be definitely inserted here. + insert_avp_before_node(dst, cd, cs->avp, copy_avps); + cs = cs->next; + } else { + // attribute names are equal. Ignore duplicate values but ensure that other values are sorted. + int value_diff = strcmp(cd->avp->v, cs->avp->v); + + if (value_diff < 0) { + // dest < source, do not insert it yet + cd = cd->next; + } else if (value_diff > 0) { + // dest > source, insert AVP before the current dest AVP + insert_avp_before_node(dst, cd, cs->avp, copy_avps); + cs = cs->next; + } else { + // identical AVPs, do not create a duplicate. + cs = cs->next; + } + } + } + + // if there are remaing source AVPs while there are no more destination + // AVPs (cd now represents the NULL item, after the last item), append + // all remaining source AVPs to the end + while (cs->avp) { + insert_avp_before_node(dst, cd, cs->avp, copy_avps); + cs = cs->next; + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,8,dbg_fp,"merge_avpl: done"); +#endif + + return; +} + + +/** + * new_avpl_from_avpl: + * @param name the name of the new avpl. + * @param avpl the avpl from which to get the avps. + * @param copy_avps whether avps should be copied instead of referenced. + * + * Creates a new avpl containing the same avps as the given avpl + * It will either reference or copie the avps. + * + * Return value: a pointer to the newly allocated string. + * + **/ +extern AVPL* new_avpl_from_avpl(const gchar* name, AVPL* avpl, gboolean copy_avps) { + AVPL* newavpl = new_avpl(name); + void* cookie = NULL; + AVP* avp; + AVP* copy; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_avpl_from_avpl: %p from=%p name='%s'",newavpl,avpl,name); +#endif + + while(( avp = get_next_avp(avpl,&cookie) )) { + if (copy_avps) { + copy = avp_copy(avp); + if ( ! insert_avp(newavpl,copy) ) { + delete_avp(copy); + } + } else { + insert_avp(newavpl,avp); + } + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,8,dbg_fp,"new_avpl_from_avpl: done"); +#endif + + return newavpl; +} + +/** +* match_avp: + * @param src an src to be compared agains an "op" avp + * @param op the "op" avp that will be matched against the src avp + * + * Checks whether or not two avp's match. + * + * Return value: a pointer to the src avp if there's a match. + * + **/ +extern AVP* match_avp(AVP* src, AVP* op) { + gchar** splited; + int i; + gchar* p; + guint ls; + guint lo; + float fs = 0.0f; + float fo = 0.0f; + gboolean lower = FALSE; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"match_avp: %s%c%s; vs. %s%c%s;",src->n,src->o,src->v,op->n,op->o,op->v); +#endif + + if ( src->n != op->n ) { + return NULL; + } + + switch (op->o) { + case AVP_OP_EXISTS: + return src; + case AVP_OP_EQUAL: + return src->v == op->v ? src : NULL; + case AVP_OP_NOTEQUAL: + return !( src->v == op->v) ? src : NULL; + case AVP_OP_STARTS: + return strncmp(src->v,op->v,strlen(op->v)) == 0 ? src : NULL; + case AVP_OP_ONEOFF: + splited = g_strsplit(op->v,"|",0); + if (splited) { + for (i=0;splited[i];i++) { + if(g_str_equal(splited[i],src->v)) { + g_strfreev(splited); + return src; + } + } + g_strfreev(splited); + } + return NULL; + + case AVP_OP_LOWER: + lower = TRUE; + /* FALLTHRU */ + case AVP_OP_HIGHER: + + fs = (float) g_ascii_strtod(src->v, NULL); + fo = (float) g_ascii_strtod(op->v, NULL); + + if (lower) { + if (fsfo) return src; + else return NULL; + } + case AVP_OP_ENDS: + /* does this work? */ + ls = (guint) strlen(src->v); + lo = (guint) strlen(op->v); + + if ( ls < lo ) { + return NULL; + } else { + p = src->v + ( ls - lo ); + return g_str_equal(p,op->v) ? src : NULL; + } + + /* case AVP_OP_TRANSF: */ + /* return do_transform(src,op); */ + case AVP_OP_CONTAINS: + return g_strrstr(src->v, op->v) ? src : NULL;; + } + /* will never get here */ + return NULL; +} + + + +/** + * new_avpl_loose_match: + * @param name the name of the resulting avpl + * @param src the data AVPL to be matched against a condition AVPL + * @param op the conditions AVPL that will be matched against the data AVPL + * @param copy_avps whether the avps in the resulting avpl should be copied + * + * Creates a new AVP list containing all data AVPs that matched any of the + * conditions AVPs. If there are no matches, an empty list will be returned. + * + * Note: Loose will always be considered a successful match, it matches zero or + * more conditions. + */ +extern AVPL* new_avpl_loose_match(const gchar* name, + AVPL* src, + AVPL* op, + gboolean copy_avps) { + + AVPL* newavpl = new_avpl(scs_subscribe(avp_strings, name)); + AVPN* co = NULL; + AVPN* cs = NULL; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_avpl_loose_match: %p src=%p op=%p name='%s'",newavpl,src,op,name); +#endif + + + cs = src->null.next; + co = op->null.next; + while (cs->avp && co->avp) { + int name_diff = strcmp(co->avp->n, cs->avp->n); + + if (name_diff < 0) { + // op < source, op is not matching + co = co->next; + } else if (name_diff > 0) { + // op > source, source is not matching + cs = cs->next; + } else { + // attribute match found, let's see if there is any condition (op) that accepts this data AVP. + AVPN *cond = co; + do { + if (match_avp(cs->avp, cond->avp)) { + insert_avp_before_node(newavpl, newavpl->null.prev, cs->avp, copy_avps); + break; + } + cond = cond->next; + } while (cond->avp && cond->avp->n == cs->avp->n); + cs = cs->next; + } + } + + // return matches (possible none) + return newavpl; +} + +/** +* new_avpl_pairs_match: + * @param name the name of the resulting avpl + * @param src the data AVPL to be matched against a condition AVPL + * @param op the conditions AVPL that will be matched against the data AVPL + * @param strict TRUE if every condition must have a matching data AVP, FALSE if + * it is also acceptable that only one of the condition AVPs for the same + * attribute is matching. + * @param copy_avps whether the avps in the resulting avpl should be copied + * + * Creates an AVP list by matching pairs of conditions and data AVPs, returning + * the data AVPs. If strict is TRUE, then each condition must be paired with a + * matching data AVP. If strict is FALSE, then some conditions are allowed to + * fail when other conditions for the same attribute do have a match. Note that + * if the condition AVPL is empty, the result will be a match (an empty list). + * + * Return value: a pointer to the newly created avpl containing the + * matching avps or NULL if there is no match. + */ +extern AVPL* new_avpl_pairs_match(const gchar* name, AVPL* src, AVPL* op, gboolean strict, gboolean copy_avps) { + AVPL* newavpl; + AVPN* co = NULL; + AVPN* cs = NULL; + const gchar *last_match = NULL; + gboolean matched = TRUE; + + newavpl = new_avpl(scs_subscribe(avp_strings, name)); + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"%s: %p src=%p op=%p name='%s'",G_STRFUNC,newavpl,src,op,name); +#endif + + cs = src->null.next; + co = op->null.next; + while (cs->avp && co->avp) { + int name_diff = g_strcmp0(co->avp->n, cs->avp->n); + const gchar *failed_match = NULL; + + if (name_diff < 0) { + // op < source, op has no data avp with same attribute. + failed_match = co->avp->n; + co = co->next; + } else if (name_diff > 0) { + // op > source, the source avp is not matched by any condition + cs = cs->next; + } else { + // Matching attributes found, now try to find a matching data AVP for the condition. + if (match_avp(cs->avp, co->avp)) { + insert_avp_before_node(newavpl, newavpl->null.prev, cs->avp, copy_avps); + last_match = co->avp->n; + cs = cs->next; + } else { + failed_match = co->avp->n; + } + co = co->next; + } + + // condition did not match, check if we can continue matching. + if (failed_match) { + if (strict) { + matched = FALSE; + break; + } else if (last_match != failed_match) { + // None of the conditions so far matched the attribute, check for other candidates + if (!co->avp || co->avp->n != last_match) { + matched = FALSE; + break; + } + } + } + } + + // if there are any conditions remaining, then those could not be matched + if (matched && strict && co->avp) { + matched = FALSE; + } + + if (matched) { + // there was a match, accept it + return newavpl; + } else { + // no match, only delete AVPs too if they were copied + delete_avpl(newavpl, copy_avps); + return NULL; + } +} + + +/** + * new_avpl_from_match: + * @param mode The matching method, one of AVPL_STRICT, AVPL_LOOSE, AVPL_EVERY. + * @param name the name of the resulting avpl + * @param src the data AVPL to be matched agains a condition AVPL + * @param op the conditions AVPL that will be matched against the data AVPL + * + * Matches the conditions AVPL against the original AVPL according to the mode. + * If there is no match, NULL is returned. If there is actually a match, then + * the matching AVPs (a subset of the data) are returned. + */ +extern AVPL* new_avpl_from_match(avpl_match_mode mode, const gchar* name,AVPL* src, AVPL* op, gboolean copy_avps) { + AVPL* avpl = NULL; + + switch (mode) { + case AVPL_STRICT: + avpl = new_avpl_pairs_match(name, src, op, TRUE, copy_avps); + break; + case AVPL_LOOSE: + avpl = new_avpl_loose_match(name,src,op,copy_avps); + break; + case AVPL_EVERY: + avpl = new_avpl_pairs_match(name, src, op, FALSE, copy_avps); + break; + case AVPL_NO_MATCH: + // XXX this seems unused + avpl = new_avpl_from_avpl(name,src,copy_avps); + merge_avpl(avpl, op, copy_avps); + break; + } + + return avpl; +} + +/** + * delete_avpl_transform: + * @param op a pointer to the avpl transformation object + * + * Destroys an avpl transformation object and releases all the resources it + * uses. + * + **/ +extern void delete_avpl_transform(AVPL_Transf* op) { + AVPL_Transf* next; + + for (; op ; op = next) { + next = op->next; + + g_free(op->name); + + if (op->match) { + delete_avpl(op->match,TRUE); + } + + if (op->replace) { + delete_avpl(op->replace,TRUE); + } + + g_free(op); + } + +} + + +/** + * avpl_transform: + * @param src the source avpl for the transform operation. + * @param op a pointer to the avpl transformation object to apply. + * + * Applies the "op" transformation to an avpl, matches it and eventually + * replaces or inserts the transformed avps. + * + * Return value: whether the transformation was performed or not. + **/ +extern void avpl_transform(AVPL* src, AVPL_Transf* op) { + AVPL* avpl = NULL; + AVPN* cs; + AVPN* cm; + AVPN* n; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"avpl_transform: src=%p op=%p",src,op); +#endif + + for ( ; op ; op = op->next) { + + avpl = new_avpl_from_match(op->match_mode, src->name,src, op->match, TRUE); + + if (avpl) { + switch (op->replace_mode) { + case AVPL_NO_REPLACE: + delete_avpl(avpl,TRUE); + return; + case AVPL_INSERT: + merge_avpl(src,op->replace,TRUE); + delete_avpl(avpl,TRUE); + return; + case AVPL_REPLACE: + cs = src->null.next; + cm = avpl->null.next; + // Removes AVPs from the source which are in the matched data. + // Assume that the matched set is a subset of the source. + while (cs->avp && cm->avp) { + if (cs->avp->n == cm->avp->n && cs->avp->v == cm->avp->v) { + n = cs->next; + + cs->prev->next = cs->next; + cs->next->prev = cs->prev; + g_slice_free(any_avp_type,(any_avp_type*)cs); + + cs = n; + cm = cm->next; + } else { + // Current matched AVP is not equal to the current + // source AVP. Since there must be a source AVP for + // each matched AVP, advance current source and not + // the match AVP. + cs = cs->next; + } + } + + merge_avpl(src,op->replace,TRUE); + delete_avpl(avpl,TRUE); + return; + } + } + } +} + + +/** + * new_loal: + * @param name the name the loal will take. + * + * Creates an empty list of avp lists. + * + * Return value: a pointer to the newly created loal. + **/ +extern LoAL* new_loal(const gchar* name) { + LoAL* new_loal_p = (LoAL*)g_slice_new(any_avp_type); + + if (! name) { + name = "anonymous"; + } + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_loal_p: %p name=%s",new_loal_p,name); +#endif + + new_loal_p->name = scs_subscribe(avp_strings,name); + new_loal_p->null.avpl = NULL; + new_loal_p->null.next = &new_loal_p->null; + new_loal_p->null.prev = &new_loal_p->null; + new_loal_p->len = 0; + return new_loal_p; +} + +/** + * loal_append: + * @param loal the loal on which to operate. + * @param avpl the avpl to append. + * + * Appends an avpl to a loal. + * + **/ +extern void loal_append(LoAL* loal, AVPL* avpl) { + LoALnode* node = (LoALnode*)g_slice_new(any_avp_type); + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"new_loal_node: %p",node); +#endif + + node->avpl = avpl; + node->next = &loal->null; + node->prev = loal->null.prev; + + loal->null.prev->next = node; + loal->null.prev = node; + loal->len++; +} + + +/** + * extract_first_avpl: + * @param loal the loal on which to operate. + * + * Extracts the first avpl contained in a loal. + * + * Return value: a pointer to the extracted avpl. + * + **/ +extern AVPL* extract_first_avpl(LoAL* loal) { + LoALnode* node; + AVPL* avpl; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"extract_first_avpl: from: %s",loal->name); +#endif + + node = loal->null.next; + + loal->null.next->next->prev = &loal->null; + loal->null.next = node->next; + + loal->len--; + + avpl = node->avpl; + + if ( avpl ) { + g_slice_free(any_avp_type,(any_avp_type*)node); + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"extract_first_avpl: got %s",avpl->name); + dbg_print(dbg_avpl_op,3,dbg_fp,"delete_loal_node: %p",node); +#endif + } + + return avpl; +} + +/** +* extract_first_avpl: + * @param loal the loal on which to operate. + * + * Extracts the last avpl contained in a loal. + * + * Return value: a pointer to the extracted avpl. + * + **/ +extern AVPL* extract_last_avpl(LoAL* loal){ + LoALnode* node; + AVPL* avpl; + + node = loal->null.prev; + + loal->null.prev->prev->next = &loal->null; + loal->null.prev = node->prev; + + loal->len--; + + avpl = node->avpl; + + if ( avpl ) { + g_slice_free(any_avp_type,(any_avp_type*)node); +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"delete_loal_node: %p",node); +#endif + } + + return avpl; +} + +/** + * extract_first_avpl: + * @param loal the loal on which to operate. + * @param cookie pointer to the pointer variable to contain the state between calls + * + * At each call will return the following avpl from a loal. The given cookie + * will be used to manatain the state between calls. + * + * Return value: a pointer to the next avpl. + * + **/ +extern AVPL* get_next_avpl(LoAL* loal,void** cookie) { + LoALnode* node; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"get_next_avpl: loal=%p node=%p",loal,*cookie); +#endif + + if (*cookie) { + node = (LoALnode*) *cookie; + } else { + node = loal->null.next; + } + + *cookie = node->next; + + return node->avpl; +} + +/** + * delete_loal: + * @param loal the loal to be deleted. + * @param avpls_too whether avpls contained by the loal should be deleted as well + * @param avps_too whether avps contained by the avpls should be also deleted + * + * Destroys a loal and eventually desstroys avpls and avps. + * + **/ +extern void delete_loal(LoAL* loal, gboolean avpls_too, gboolean avps_too) { + AVPL* avpl; + +#ifdef _AVP_DEBUGGING + dbg_print(dbg_avpl_op,3,dbg_fp,"delete_loal: %p",loal); +#endif + + while(( avpl = extract_last_avpl(loal) )) { + if (avpls_too) { + delete_avpl(avpl,avps_too); + } + } + + scs_unsubscribe(avp_strings,loal->name); + g_slice_free(any_avp_type,(any_avp_type*)loal); +} + + + +/**************************************************************************** + ******************* the following are used in load_loal_from_file + ****************************************************************************/ + +/** + * load_loal_error: + * Used by loal_from_file to handle errors while loading. + **/ +static LoAL* load_loal_error(FILE* fp, LoAL* loal, AVPL* curr, int linenum, const gchar* fmt, ...) { + va_list list; + gchar* desc; + LoAL* ret = NULL; + gchar* err; + + va_start( list, fmt ); + desc = ws_strdup_vprintf(fmt, list); + va_end( list ); + + if (loal) { + err = ws_strdup_printf("Error Loading LoAL from file: in %s at line: %i, %s",loal->name,linenum,desc); + } else { + err = ws_strdup_printf("Error Loading LoAL at line: %i, %s",linenum,desc); + } + ret = new_loal(err); + + g_free(desc); + g_free(err); + + if (fp) fclose(fp); + if (loal) delete_loal(loal,TRUE,TRUE); + if (curr) delete_avpl(curr,TRUE); + + return ret; +} + + +/* the maximum length allowed for a line */ +#define MAX_ITEM_LEN 8192 + +/* this two ugly things are used for tokenizing */ +#define AVP_OP_CHAR '=': case '^': case '$': case '~': case '<': case '>': case '?': case '|': case '&' : case '!' + +#define AVP_NAME_CHAR 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J':\ +case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T':\ +case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd':\ +case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':\ +case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x':\ +case 'y': case 'z': case '_': case '0': case '1': case '2': case '3': case '4': case '5': case '6':\ +case '7': case '8': case '9': case '.' + + +/** + * loal_from_file: + * @param filename the file containing a loals text representation. + * + * Given a filename it will attempt to load a loal containing a copy of + * the avpls represented in the file. + * + * Return value: if successful a pointer to the new populated loal, else NULL. + * + **/ +extern LoAL* loal_from_file(gchar* filename) { + FILE *fp = NULL; + gchar c; + int i = 0; + guint32 linenum = 1; + gchar *linenum_buf; + gchar *name; + gchar *value; + gchar op = '?'; + LoAL *loal_error, *loal = new_loal(filename); + AVPL* curr = NULL; + AVP* avp; + + enum _load_loal_states { + START, + BEFORE_NAME, + IN_NAME, + IN_VALUE, + MY_IGNORE + } state; + + linenum_buf = (gchar*)g_malloc(MAX_ITEM_LEN); + name = (gchar*)g_malloc(MAX_ITEM_LEN); + value = (gchar*)g_malloc(MAX_ITEM_LEN); +#ifndef _WIN32 + if (! getuid()) { + loal_error = load_loal_error(fp,loal,curr,linenum,"MATE Will not run as root"); + goto error; + } +#endif + + state = START; + + if (( fp = ws_fopen(filename,"r") )) { + while(( c = (gchar) fgetc(fp) )){ + + if ( feof(fp) ) { + if ( ferror(fp) ) { + report_read_failure(filename,errno); + loal_error = load_loal_error(fp,loal,curr,linenum,"Error while reading '%f'",filename); + goto error; + } + break; + } + + if ( c == '\n' ) { + linenum++; + } + + if ( i >= MAX_ITEM_LEN - 1 ) { + loal_error = load_loal_error(fp,loal,curr,linenum,"Maximum item length exceeded"); + goto error; + } + + switch(state) { + case MY_IGNORE: + switch (c) { + case '\n': + state = START; + i = 0; + continue; + default: + continue; + } + case START: + switch (c) { + case ' ': case '\t': + /* ignore whitespace at line start */ + continue; + case '\n': + /* ignore empty lines */ + i = 0; + continue; + case AVP_NAME_CHAR: + state = IN_NAME; + i = 0; + name[i++] = c; + name[i] = '\0'; + snprintf(linenum_buf,MAX_ITEM_LEN,"%s:%u",filename,linenum); + curr = new_avpl(linenum_buf); + continue; + case '#': + state = MY_IGNORE; + continue; + default: + loal_error = load_loal_error(fp,loal,curr,linenum,"expecting name got: '%c'",c); + goto error; + } + case BEFORE_NAME: + i = 0; + name[0] = '\0'; + switch (c) { + case '\\': + c = (gchar) fgetc(fp); + if (c != '\n') ungetc(c,fp); + continue; + case ' ': + case '\t': + continue; + case AVP_NAME_CHAR: + state = IN_NAME; + + name[i++] = c; + name[i] = '\0'; + continue; + case '\n': + loal_append(loal,curr); + state = START; + continue; + default: + loal_error = load_loal_error(fp,loal,curr,linenum,"expecting name got: '%c'",c); + goto error; + } + case IN_NAME: + switch (c) { + case ';': + state = BEFORE_NAME; + + op = '?'; + name[i] = '\0'; + value[0] = '\0'; + i = 0; + + avp = new_avp(name,value,op); + + if (! insert_avp(curr,avp) ) { + delete_avp(avp); + } + + continue; + case AVP_OP_CHAR: + name[i] = '\0'; + i = 0; + op = c; + state = IN_VALUE; + continue; + case AVP_NAME_CHAR: + name[i++] = c; + continue; + case '\n': + loal_error = load_loal_error(fp,loal,curr,linenum,"operator expected found new line"); + goto error; + default: + loal_error = load_loal_error(fp,loal,curr,linenum,"name or match operator expected found '%c'",c); + goto error; + } + case IN_VALUE: + switch (c) { + case '\\': + value[i++] = (gchar) fgetc(fp); + continue; + case ';': + state = BEFORE_NAME; + + value[i] = '\0'; + i = 0; + + avp = new_avp(name,value,op); + + if (! insert_avp(curr,avp) ) { + delete_avp(avp); + } + continue; + case '\n': + loal_error = load_loal_error(fp,loal,curr,linenum,"';' expected found new line"); + goto error; + default: + value[i++] = c; + continue; + } + } + } + fclose (fp); + + g_free(linenum_buf); + g_free(name); + g_free(value); + + return loal; + + } else { + report_open_failure(filename,errno,FALSE); + loal_error = load_loal_error(NULL,loal,NULL,0,"Cannot Open file '%s'",filename); + } + +error: + g_free(linenum_buf); + g_free(name); + g_free(value); + + return loal_error; +} + +/* + * 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: + */ diff --git a/plugins/epan/mate/mate_util.h b/plugins/epan/mate/mate_util.h new file mode 100644 index 00000000..0764ea5e --- /dev/null +++ b/plugins/epan/mate/mate_util.h @@ -0,0 +1,249 @@ +/* mate_util.h + * + * Copyright 2004, Luis E. Garcia Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#ifndef __AVP_H_ +#define __AVP_H_ +#include "epan/proto.h" +#include + +/* #define _AVP_DEBUGGING */ + + +/******* dbg_print *********/ +#define DEBUG_BUFFER_SIZE 4096 +extern void dbg_print(const gint* which, gint how, FILE* where, + const gchar* fmt, ... ) G_GNUC_PRINTF(4, 5); + + +/******* single copy strings *********/ +typedef struct _scs_collection SCS_collection; + +#define SCS_SMALL_SIZE 16 +#define SCS_MEDIUM_SIZE 256 +#define SCS_LARGE_SIZE 4096 +#define SCS_HUGE_SIZE 65536 + +extern gchar* scs_subscribe(SCS_collection* collection, const gchar* s); +extern void scs_unsubscribe(SCS_collection* collection, gchar* s); +extern gchar* scs_subscribe_printf(SCS_collection* collection, gchar* fmt, ...) + G_GNUC_PRINTF(2, 3); + +/******* AVPs & Co. *********/ + +/* these are the defined oreators of avps */ +#define AVP_OP_EQUAL '=' +#define AVP_OP_NOTEQUAL '!' +#define AVP_OP_STARTS '^' +#define AVP_OP_ENDS '$' +#define AVP_OP_CONTAINS '~' +#define AVP_OP_LOWER '<' +#define AVP_OP_HIGHER '>' +#define AVP_OP_EXISTS '?' +#define AVP_OP_ONEOFF '|' +#define AVP_OP_TRANSF '&' + + +/* an avp is an object made of a name a value and an operator */ +typedef struct _avp { + gchar* n; + gchar* v; + gchar o; +} AVP; + +/* avp nodes are used in avp lists */ +typedef struct _avp_node { + AVP* avp; + struct _avp_node* next; + struct _avp_node* prev; +} AVPN; + +/* an avp list is a sorted set of avps */ +typedef struct _avp_list { + gchar* name; + guint32 len; + AVPN null; +} AVPL; + + + +/* an avpl transformation operation */ +typedef enum _avpl_match_mode { + AVPL_NO_MATCH, + AVPL_STRICT, + AVPL_LOOSE, + AVPL_EVERY +} avpl_match_mode; + +typedef enum _avpl_replace_mode { + AVPL_NO_REPLACE, + AVPL_INSERT, + AVPL_REPLACE +} avpl_replace_mode; + +typedef struct _avpl_transf AVPL_Transf; + +struct _avpl_transf { + gchar* name; + + AVPL* match; + AVPL* replace; + + avpl_match_mode match_mode; + avpl_replace_mode replace_mode; + + GHashTable* map; + AVPL_Transf* next; +}; + +/* loalnodes are used in LoALs */ +typedef struct _loal_node { + AVPL* avpl; + struct _loal_node *next; + struct _loal_node *prev; +} LoALnode; + + +/* a loal is a list of avp lists */ +typedef struct _loal { + gchar* name; + guint len; + LoALnode null; +} LoAL; + + +/* avp library (re)initialization */ +extern void avp_init(void); + +/* If enabled set's up the debug facilities for the avp library */ +#ifdef _AVP_DEBUGGING +extern void setup_avp_debug(FILE* fp, int* general, int* avp, int* avp_op, int* avpl, int* avpl_op); +#endif /* _AVP_DEBUGGING */ + +/* + * avp constructors + */ + +/* creates a new avp */ +extern AVP* new_avp(const gchar* name, const gchar* value, gchar op); + +/* creates a copy od an avp */ +extern AVP* avp_copy(AVP* from); + +/* creates an avp from a field_info record */ +extern AVP* new_avp_from_finfo(const gchar* name, field_info* finfo); + +/* + * avp destructor + */ +extern void delete_avp(AVP* avp); + +/* + * avp methods + */ +/* returns a newly allocated string containing a representation of the avp */ +#define avp_to_str(avp) (ws_strdup_printf("%s%c%s",avp->n,avp->o,avp->v)) + +/* returns the src avp if the src avp matches(*) the op avp or NULL if it doesn't */ +extern AVP* match_avp(AVP* src, AVP* op); + + +/* + * avplist constructors + */ + +/* creates an empty avp list */ +extern AVPL* new_avpl(const gchar* name); + + +/* creates a copy of an avp list */ +extern AVPL* new_avpl_from_avpl(const gchar* name, AVPL* avpl, gboolean copy_avps); + +extern AVPL* new_avpl_loose_match(const gchar* name, AVPL* src, AVPL* op, gboolean copy_avps); + +extern AVPL* new_avpl_pairs_match(const gchar* name, AVPL* src, AVPL* op, gboolean strict, gboolean copy_avps); + +/* uses mode to call one of the former matches. NO_MATCH = merge(merge(copy(src),op)) */ +extern AVPL* new_avpl_from_match(avpl_match_mode mode, const gchar* name,AVPL* src, AVPL* op, gboolean copy_avps); + + +/* + * functions on avpls + */ + +/* it will insert an avp to an avpl */ +extern gboolean insert_avp(AVPL* avpl, AVP* avp); + +/* renames an avpl */ +extern void rename_avpl(AVPL* avpl, gchar* name); + +/* it will add all the avps in src which don't match(*) any attribute in dest */ +extern void merge_avpl(AVPL* dest, AVPL* src, gboolean copy); + +/* it will return the first avp in an avpl whose name matches the given name. + will return NULL if there is not anyone matching */ +extern AVP* get_avp_by_name(AVPL* avpl, gchar* name, void** cookie); + +/* it will get the next avp from an avpl, using cookie to keep state */ +extern AVP* get_next_avp(AVPL* avpl, void** cookie); + +/* it will extract the first avp from an avp list */ +extern AVP* extract_first_avp(AVPL* avpl); + +/* it will extract the last avp from an avp list */ +extern AVP* extract_last_avp(AVPL* avpl); + +/* it will extract the first avp in an avpl whose name matches the given name. + it will not extract any and return NULL if there is not anyone matching */ +extern AVP* extract_avp_by_name(AVPL* avpl, gchar* name); + +/* returns a newly allocated string containing a representation of the avp list */ +extern gchar* avpl_to_str(AVPL* avpl); +extern gchar* avpl_to_dotstr(AVPL*); + +/* deletes an avp list and eventually its contents */ +extern void delete_avpl(AVPL* avpl, gboolean avps_too); + +/* + * AVPL transformations + */ +extern void delete_avpl_transform(AVPL_Transf* it); +extern void avpl_transform(AVPL* src, AVPL_Transf* op); + + +/* + * Lists of AVP lists + */ + +/* creates an empty list of avp lists */ +extern LoAL* new_loal(const gchar* name); + +/* given a file loads all the avpls contained in it + every line is formatted as it is the output of avplist_to_string */ +extern LoAL* loal_from_file(gchar* filename); + +/* inserts an avplist into a LoAL */ +extern void loal_append(LoAL* loal, AVPL* avpl); + +/* extracts the first avp list from the loal */ +extern AVPL* extract_first_avpl(LoAL* loal); + +/* extracts the last avp list from the loal */ +extern AVPL* extract_last_avpl(LoAL* loal); + +/* it will get the next avp list from a LoAL, using cookie to keep state */ +extern AVPL* get_next_avpl(LoAL* loal,void** cookie); + +/* deletes a loal and eventually its contents */ +extern void delete_loal(LoAL* loal, gboolean avpls_too, gboolean avps_too); + + +#endif diff --git a/plugins/epan/mate/matelib/dns.mate b/plugins/epan/mate/matelib/dns.mate new file mode 100644 index 00000000..be426bc5 --- /dev/null +++ b/plugins/epan/mate/matelib/dns.mate @@ -0,0 +1,6 @@ +# dns.mate + +Action=PduDef; Name=dns_pdu; Proto=dns; Transport=udp/ip; addr=ip.addr; port=udp.port; dns_id=dns.id; dns_rsp=dns.flags.response; +Action=GopDef; Name=dns_req; On=dns_pdu; addr; addr; port!53; dns_id; +Action=GopStart; For=dns_req; dns_rsp=0; +Action=GopStop; For=dns_req; dns_rsp=1; diff --git a/plugins/epan/mate/matelib/h225_ras.mate b/plugins/epan/mate/matelib/h225_ras.mate new file mode 100644 index 00000000..7c6698ef --- /dev/null +++ b/plugins/epan/mate/matelib/h225_ras.mate @@ -0,0 +1,9 @@ +# h225_ras.mate + +Action=PduDef; Name=ras_pdu; Proto=h225.RasMessage; Transport=udp/ip; ras_sn=h225.requestSeqNum; ras_msg=h225.RasMessage; addr=ip.addr; +Action=GopDef; Name=ras_leg; On=ras_pdu; addr; addr; ras_sn; +Action=GopStart; For=ras_leg; ras_msg|0|3|6|9|12|15|18|21|26|30; +Action=GopStop; For=ras_leg; ras_msg|1|2|4|5|7|8|10|11|13|14|16|17|19|20|22|24|27|28|29|31; + +Action=PduExtra; For=ras_pdu; guid=h225.guid; +Action=GopExtra; For=ras_leg; guid; diff --git a/plugins/epan/mate/matelib/isup.mate b/plugins/epan/mate/matelib/isup.mate new file mode 100644 index 00000000..8ff6d309 --- /dev/null +++ b/plugins/epan/mate/matelib/isup.mate @@ -0,0 +1,23 @@ +# isup.mate + +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=1; .isup_IAM=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=2; .isup_SAM=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=3; .isup_INR=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=4; .isup_INF=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=5; .isup_COT=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=6; .isup_ACM=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=7; .isup_CON=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=8; .isup_FOT=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=9; .isup_ANM=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=12; .isup_REL=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=13; .isup_SUS=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=14; .isup_RES=; +#Action=Transform; Name=isup_msg_type; Mode=Insert; Match=Strict; isup_msg=16; .isup_RLC=; + +Action=PduDef; Name=isup_pdu; Proto=isup; Transport=mtp3; mtp3pc=mtp3.dpc; mtp3pc=mtp3.opc; cic=isup.cic; isup_msg=isup.message_type; +#Action=PduTransform; For=isup_pdu; Name=isup_msg_type; + +Action=GopDef; Name=isup_leg; On=isup_pdu; ShowPduTree=TRUE; mtp3pc; mtp3pc; cic; +Action=GopStart; For=isup_leg; isup_msg=1; +Action=GopStop; For=isup_leg; isup_msg=16; + diff --git a/plugins/epan/mate/matelib/megaco.mate b/plugins/epan/mate/matelib/megaco.mate new file mode 100644 index 00000000..044aba78 --- /dev/null +++ b/plugins/epan/mate/matelib/megaco.mate @@ -0,0 +1,8 @@ +# megaco.mate + +Action=PduDef; Name=mgc_pdu; Proto=megaco; Transport=ip; addr=ip.addr; megaco_ctx=megaco.context; megaco_trx=megaco.transid; megaco_msg=megaco.transaction; term=megaco.termid; + +Action=GopDef; Name=mgc_tr; On=mgc_pdu; addr; addr; megaco_trx; +Action=GopStart; For=mgc_tr; megaco_msg|Request|Notify; +Action=GopStop; For=mgc_tr; megaco_msg=Reply; +Action=GopExtra; For=mgc_tr; term^DS1; megaco_ctx!Choose one; diff --git a/plugins/epan/mate/matelib/q931.mate b/plugins/epan/mate/matelib/q931.mate new file mode 100644 index 00000000..5bea5b1a --- /dev/null +++ b/plugins/epan/mate/matelib/q931.mate @@ -0,0 +1,6 @@ +# q931.thing + +Action=PduDef; Name=q931_pdu; Proto=q931; Stop=TRUE; Transport=tcp/ip; addr=ip.addr; call_ref=q931.call_ref; q931_msg=q931.message_type; +Action=GopDef; Name=q931_leg; On=q931_pdu; addr; addr; call_ref; +Action=GopStart; For=q931_leg; q931_msg=5; +Action=GopStop; For=q931_leg; q931_msg=90; diff --git a/plugins/epan/mate/matelib/radius.mate b/plugins/epan/mate/matelib/radius.mate new file mode 100644 index 00000000..66a910b8 --- /dev/null +++ b/plugins/epan/mate/matelib/radius.mate @@ -0,0 +1,12 @@ +# radius.mate + +Action=Transform; Name=radius_same_port; Mode=Insert; Match=Strict; radius_port; radius_port; +Action=Transform; Name=radius_same_port; Mode=Insert; Match=Every; radius_port; .radius_port=0; + +Action=PduDef; Name=radius_pdu; Proto=radius; Transport=udp/ip; radius_addr=ip.addr; radius_port=udp.port; radius_id=radius.id; radius_code=radius.code; +Action=PduTransform; For=radius_pdu; Name=radius_same_port; + +Action=GopDef; Name=radius_req; On=radius_pdu; radius_id; radius_addr; radius_addr; radius_port; radius_port; +Action=GopStart; For=radius_req; radius_code|1|4|7; +Action=GopStop; For=radius_req; radius_code|2|3|5|8|9; + diff --git a/plugins/epan/mate/matelib/rtsp.mate b/plugins/epan/mate/matelib/rtsp.mate new file mode 100644 index 00000000..35f25ab2 --- /dev/null +++ b/plugins/epan/mate/matelib/rtsp.mate @@ -0,0 +1,10 @@ +# rtsp.mate + +Action=PduDef; Name=rtsp_pdu; Proto=rtsp; Transport=tcp/ip; addr=ip.addr; port=tcp.port; rtsp_method=rtsp.method; +Action=PduExtra; For=rtsp_pdu; rtsp_ses=rtsp.session; rtsp_url=rtsp.url; + +Action=GopDef; Name=rtsp_ses; On=rtsp_pdu; addr; addr; port; port; +Action=GopStart; For=rtsp_ses; rtsp_method=DESCRIBE; +Action=GopStop; For=rtsp_ses; rtsp_method=TEARDOWN; +Action=GopExtra; For=rtsp_ses; rtsp_ses; rtsp_url; + diff --git a/plugins/epan/mate/matelib/sip.mate b/plugins/epan/mate/matelib/sip.mate new file mode 100644 index 00000000..593c915b --- /dev/null +++ b/plugins/epan/mate/matelib/sip.mate @@ -0,0 +1,12 @@ +# sip.mate + +Action=PduDef; Name=sip_pdu; Proto=sip; Transport=tcp/ip; addr=ip.addr; port=tcp.port; sip_method=sip.Method; sip_callid=sip.Call-ID; calling=sdp.owner.username; +Action=GopDef; Name=sip_leg; On=sip_pdu; addr; addr; port; port; +Action=GopStart; For=sip_leg; sip_method=INVITE; +Action=GopStop; For=sip_leg; sip_method=BYE; + +Action=PduDef; Name=sip_trunk_pdu; Proto=sip; Transport=udp/ip; addr=ip.addr; port=udp.port; sip_method=sip.Method; sip_callid=sip.Call-ID; calling=sdp.owner.username; +Action=GopDef; Name=sip_trunk_leg; On=sip_trunk_pdu; addr; addr; sip_callid; +Action=GopStart; For=sip_trunk_leg; sip_method=INVITE; +Action=GopStop; For=sip_trunk_leg; sip_method=BYE; + diff --git a/plugins/epan/mate/packet-mate.c b/plugins/epan/mate/packet-mate.c new file mode 100644 index 00000000..97774cd1 --- /dev/null +++ b/plugins/epan/mate/packet-mate.c @@ -0,0 +1,453 @@ +/* packet-mate.c + * Routines for the mate Facility's Pseudo-Protocol dissection + * + * Copyright 2004, Luis E. Garcia Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +/************************************************************************** + * This is the pseudo protocol dissector for the mate module. *** + * It is intended for this to be just the user interface to the module. *** + **************************************************************************/ + +#include "config.h" + +#include "mate.h" +#include + +void proto_register_mate(void); +void proto_reg_handoff_mate(void); + +static mate_config* mc = NULL; + +static int proto_mate = -1; + +static int hf_mate_released_time = -1; +static int hf_mate_duration = -1; +static int hf_mate_number_of_pdus = -1; +static int hf_mate_started_at = -1; +static int hf_mate_gop_key = -1; + +static expert_field ei_mate_undefined_attribute = EI_INIT; + +static const gchar* pref_mate_config_filename = ""; +static const gchar* current_mate_config_filename = NULL; + +#ifdef _AVP_DEBUGGING +static int pref_avp_debug_general = 0; +static int pref_avp_debug_avp = 0; +static int pref_avp_debug_avp_op = 0; +static int pref_avp_debug_avpl = 0; +static int pref_avp_debug_avpl_op = 0; +#endif + +static dissector_handle_t mate_handle; + +static void +pdu_attrs_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_pdu* pdu) +{ + AVPN* c; + proto_tree *avpl_t; + int* hfi_p; + + avpl_t = proto_tree_add_subtree_format(tree,tvb,0,0,pdu->cfg->ett_attr,NULL,"%s Attributes",pdu->cfg->name); + + for ( c = pdu->avpl->null.next; c->avp; c = c->next) { + hfi_p = (int *)g_hash_table_lookup(pdu->cfg->my_hfids,(char*)c->avp->n); + + if (hfi_p) { + proto_tree_add_string(avpl_t,*hfi_p,tvb,0,0,c->avp->v); + } else { + proto_tree_add_expert_format(avpl_t,pinfo,&ei_mate_undefined_attribute,tvb,0,0,"Undefined attribute: %s=%s",c->avp->n, c->avp->v); + } + } +} + +static void +gop_attrs_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_gop* gop) +{ + AVPN* c; + proto_tree *avpl_t; + int* hfi_p; + + avpl_t = proto_tree_add_subtree_format(tree,tvb,0,0,gop->cfg->ett_attr,NULL,"%s Attributes",gop->cfg->name); + + for ( c = gop->avpl->null.next; c->avp; c = c->next) { + hfi_p = (int *)g_hash_table_lookup(gop->cfg->my_hfids,(char*)c->avp->n); + + if (hfi_p) { + proto_tree_add_string(avpl_t,*hfi_p,tvb,0,0,c->avp->v); + } else { + proto_tree_add_expert_format(avpl_t,pinfo,&ei_mate_undefined_attribute,tvb,0,0,"Undefined attribute: %s=%s",c->avp->n, c->avp->v); + } + } +} + +static void +gog_attrs_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_gog* gog) +{ + AVPN* c; + proto_tree *avpl_t; + int* hfi_p; + + avpl_t = proto_tree_add_subtree_format(tree,tvb,0,0,gog->cfg->ett_attr,NULL,"%s Attributes",gog->cfg->name); + + for ( c = gog->avpl->null.next; c->avp; c = c->next) { + hfi_p = (int *)g_hash_table_lookup(gog->cfg->my_hfids,(char*)c->avp->n); + + if (hfi_p) { + proto_tree_add_string(avpl_t,*hfi_p,tvb,0,0,c->avp->v); + } else { + proto_tree_add_expert_format(avpl_t,pinfo,&ei_mate_undefined_attribute,tvb,0,0,"Undefined attribute: %s=%s",c->avp->n, c->avp->v); + } + } +} + +static void mate_gop_tree(proto_tree* pdu_tree, packet_info *pinfo, tvbuff_t *tvb, mate_gop* gop); + +static void +mate_gog_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_gog* gog, mate_gop* gop) +{ + proto_item *gog_item; + proto_tree *gog_tree; + proto_tree *gog_time_tree; + proto_item *gog_gops_item; + proto_tree *gog_gops_tree; + mate_gop* gog_gops; + proto_item *gog_gop_item; + proto_tree *gog_gop_tree; + mate_pdu* pdu; + + gog_item = proto_tree_add_uint(tree,gog->cfg->hfid,tvb,0,0,gog->id); + gog_tree = proto_item_add_subtree(gog_item,gog->cfg->ett); + + gog_attrs_tree(gog_tree,pinfo,tvb,gog); + + if (gog->cfg->show_times) { + gog_time_tree = proto_tree_add_subtree_format(gog_tree,tvb,0,0,gog->cfg->ett_times,NULL,"%s Times",gog->cfg->name); + + proto_tree_add_float(gog_time_tree, gog->cfg->hfid_start_time, tvb, 0, 0, gog->start_time); + proto_tree_add_float(gog_time_tree, gog->cfg->hfid_last_time, tvb, 0, 0, gog->last_time - gog->start_time); + } + + gog_gops_item = proto_tree_add_uint(gog_tree, gog->cfg->hfid_gog_num_of_gops, tvb, 0, 0, gog->num_of_gops); + + gog_gops_tree = proto_item_add_subtree(gog_gops_item, gog->cfg->ett_children); + + for (gog_gops = gog->gops; gog_gops; gog_gops = gog_gops->next) { + + if (gop != gog_gops) { + if (gog->cfg->gop_tree_mode == GOP_FULL_TREE) { + mate_gop_tree(gog_gops_tree, pinfo, tvb, gog_gops); + } else { + gog_gop_item = proto_tree_add_uint(gog_gops_tree,gog_gops->cfg->hfid,tvb,0,0,gog_gops->id); + + if (gog->cfg->gop_tree_mode == GOP_BASIC_TREE) { + gog_gop_tree = proto_item_add_subtree(gog_gop_item, gog->cfg->ett_gog_gop); + + proto_tree_add_float(gog_gop_tree, hf_mate_started_at, tvb,0,0,gog_gops->start_time); + + proto_tree_add_float_format(gog_gop_tree, hf_mate_duration, tvb,0,0, gog_gops->last_time - gog_gops->start_time, + "%s Duration: %f", gog_gops->cfg->name, gog_gops->last_time - gog_gops->start_time); + + if (gog_gops->released) + proto_tree_add_float_format(gog_gop_tree, hf_mate_released_time, tvb,0,0, gog_gops->release_time - gog_gops->start_time, + "%s has been released, Time: %f", gog_gops->cfg->name, gog_gops->release_time - gog_gops->start_time); + + proto_tree_add_uint(gog_gop_tree, hf_mate_number_of_pdus, tvb,0,0, gog_gops->num_of_pdus); + + if (gop->pdus && gop->cfg->pdu_tree_mode != GOP_NO_TREE) { + proto_tree_add_uint(gog_gop_tree,gog->cfg->hfid_gog_gopstart,tvb,0,0,gog_gops->pdus->frame); + + for (pdu = gog_gops->pdus->next ; pdu; pdu = pdu->next) { + if (pdu->is_stop) { + proto_tree_add_uint(gog_gop_tree,gog->cfg->hfid_gog_gopstop,tvb,0,0,pdu->frame); + break; + } + } + } + } + + } + } else { + proto_tree_add_uint_format(gog_gops_tree,gop->cfg->hfid,tvb,0,0,gop->id,"current %s Gop: %d",gop->cfg->name,gop->id); + } + } +} + +static void +mate_gop_tree(proto_tree* tree, packet_info *pinfo, tvbuff_t *tvb, mate_gop* gop) +{ + proto_item *gop_item; + proto_tree *gop_time_tree; + proto_tree *gop_tree; + proto_item *gop_pdu_item; + proto_tree *gop_pdu_tree; + mate_pdu* gop_pdus; + float rel_time; + float pdu_rel_time; + const gchar* pdu_str; + const gchar* type_str; + guint32 pdu_item; + + gop_item = proto_tree_add_uint(tree,gop->cfg->hfid,tvb,0,0,gop->id); + gop_tree = proto_item_add_subtree(gop_item, gop->cfg->ett); + + if (gop->gop_key) proto_tree_add_string(gop_tree,hf_mate_gop_key,tvb,0,0,gop->gop_key); + + gop_attrs_tree(gop_tree,pinfo,tvb,gop); + + if (gop->cfg->show_times) { + gop_time_tree = proto_tree_add_subtree_format(gop_tree,tvb,0,0,gop->cfg->ett_times,NULL,"%s Times",gop->cfg->name); + + proto_tree_add_float(gop_time_tree, gop->cfg->hfid_start_time, tvb, 0, 0, gop->start_time); + + if (gop->released) { + proto_tree_add_float(gop_time_tree, gop->cfg->hfid_stop_time, tvb, 0, 0, gop->release_time - gop->start_time); + proto_tree_add_float(gop_time_tree, gop->cfg->hfid_last_time, tvb, 0, 0, gop->last_time - gop->start_time); + } else { + proto_tree_add_float(gop_time_tree, gop->cfg->hfid_last_time, tvb, 0, 0, gop->last_time - gop->start_time); + } + } + + gop_pdu_item = proto_tree_add_uint(gop_tree, gop->cfg->hfid_gop_num_pdus, tvb, 0, 0,gop->num_of_pdus); + + if (gop->cfg->pdu_tree_mode != GOP_NO_TREE) { + + gop_pdu_tree = proto_item_add_subtree(gop_pdu_item, gop->cfg->ett_children); + + rel_time = gop->start_time; + + type_str = (gop->cfg->pdu_tree_mode == GOP_FRAME_TREE ) ? "in frame:" : "id:"; + + for (gop_pdus = gop->pdus; gop_pdus; gop_pdus = gop_pdus->next) { + + pdu_item = (gop->cfg->pdu_tree_mode == GOP_FRAME_TREE ) ? gop_pdus->frame : gop_pdus->id; + + if (gop_pdus->is_start) { + pdu_str = "Start "; + } else if (gop_pdus->is_stop) { + pdu_str = "Stop "; + } else if (gop_pdus->after_release) { + pdu_str = "After stop "; + } else { + pdu_str = ""; + } + + pdu_rel_time = gop_pdus->time_in_gop != 0.0 ? gop_pdus->time_in_gop - rel_time : (float) 0.0; + + proto_tree_add_uint_format(gop_pdu_tree,gop->cfg->hfid_gop_pdu,tvb,0,0,pdu_item, + "%sPDU: %s %i (%f : %f)",pdu_str, type_str, + pdu_item, gop_pdus->time_in_gop, + pdu_rel_time); + + rel_time = gop_pdus->time_in_gop; + + } + } +} + + +static void +mate_pdu_tree(mate_pdu *pdu, packet_info *pinfo, tvbuff_t *tvb, proto_item *item, proto_tree* tree) +{ + proto_item *pdu_item; + proto_tree *pdu_tree; + + if ( ! pdu ) return; + + if (pdu->gop && pdu->gop->gog) { + proto_item_append_text(item," %s:%d->%s:%d->%s:%d", + pdu->cfg->name,pdu->id, + pdu->gop->cfg->name,pdu->gop->id, + pdu->gop->gog->cfg->name,pdu->gop->gog->id); + } else if (pdu->gop) { + proto_item_append_text(item," %s:%d->%s:%d", + pdu->cfg->name,pdu->id, + pdu->gop->cfg->name,pdu->gop->id); + } else { + proto_item_append_text(item," %s:%d",pdu->cfg->name,pdu->id); + } + + pdu_item = proto_tree_add_uint(tree,pdu->cfg->hfid,tvb,0,0,pdu->id); + pdu_tree = proto_item_add_subtree(pdu_item, pdu->cfg->ett); + proto_tree_add_float(pdu_tree,pdu->cfg->hfid_pdu_rel_time, tvb, 0, 0, pdu->rel_time); + + if (pdu->gop) { + proto_tree_add_float(pdu_tree,pdu->cfg->hfid_pdu_time_in_gop, tvb, 0, 0, pdu->time_in_gop); + mate_gop_tree(tree,pinfo,tvb,pdu->gop); + + if (pdu->gop->gog) + mate_gog_tree(tree,pinfo,tvb,pdu->gop->gog,pdu->gop); + } + + if (pdu->avpl) { + pdu_attrs_tree(pdu_tree,pinfo,tvb,pdu); + } +} + +static int +mate_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + mate_pdu* pdus; + proto_item *mate_i; + proto_tree *mate_t; + + /* If there is no MATE configuration, don't claim the packet */ + if ( mc == NULL) + return 0; + + /* There is a MATE configuration, just no tree, so there's nothing to do */ + if ( tree == NULL) + return tvb_captured_length(tvb); + + mate_analyze_frame(mc, pinfo,tree); + + if (( pdus = mate_get_pdus(pinfo->num) )) { + for ( ; pdus; pdus = pdus->next_in_frame) { + mate_i = proto_tree_add_protocol_format(tree,mc->hfid_mate,tvb,0,0,"MATE"); + mate_t = proto_item_add_subtree(mate_i, mc->ett_root); + mate_pdu_tree(pdus,pinfo,tvb,mate_i,mate_t); + } + } + return tvb_captured_length(tvb); +} + +static void +initialize_mate(void) +{ + initialize_mate_runtime(mc); +#ifdef _AVP_DEBUGGING + setup_avp_debug(mc->dbg_facility, + &pref_avp_debug_general, + &pref_avp_debug_avp, + &pref_avp_debug_avp_op, + &pref_avp_debug_avpl, + &pref_avp_debug_avpl_op); +#endif +} + +static void +flush_mate_debug(void) +{ + /* Flush debug information */ + if (mc->dbg_facility) + fflush(mc->dbg_facility); +} + +extern +void +proto_reg_handoff_mate(void) +{ + if ( *pref_mate_config_filename != '\0' ) { + + if (current_mate_config_filename) { + report_failure("MATE cannot reconfigure itself.\n" + "For changes to be applied you have to restart Wireshark\n"); + return; + } + + if (!mc) { + mc = mate_make_config(pref_mate_config_filename,proto_mate); + + if (mc) { + /* XXX: alignment warnings, what do they mean? */ + proto_register_field_array(proto_mate, (hf_register_info*)(void *)mc->hfrs->data, mc->hfrs->len ); + proto_register_subtree_array((gint**)(void*)mc->ett->data, mc->ett->len); + register_init_routine(initialize_mate); + register_postseq_cleanup_routine(flush_mate_debug); + + /* + * Set the list of hfids we want. + */ + set_postdissector_wanted_hfids(mate_handle, + mc->wanted_hfids); + + initialize_mate_runtime(mc); + } + + current_mate_config_filename = pref_mate_config_filename; + + } + } +} + +extern +void +proto_register_mate(void) +{ + static hf_register_info hf[] = { + { &hf_mate_started_at, { "Started at", "mate.started_at", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_mate_duration, { "Duration", "mate.duration", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_mate_released_time, { "Release time", "mate.released_time", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + { &hf_mate_number_of_pdus, { "Number of Pdus", "mate.number_of_pdus", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_mate_gop_key, { "GOP Key", "mate.gop_key", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + }; + + static ei_register_info ei[] = { + { &ei_mate_undefined_attribute, { "mate.undefined_attribute", PI_PROTOCOL, PI_ERROR, "Undefined attribute", EXPFILL }}, + }; + + expert_module_t* expert_mate; + module_t *mate_module; + + proto_mate = proto_register_protocol("Meta Analysis Tracing Engine", "MATE", "mate"); + proto_register_field_array(proto_mate, hf, array_length(hf)); + expert_mate = expert_register_protocol(proto_mate); + expert_register_field_array(expert_mate, ei, array_length(ei)); + + mate_handle = register_dissector("mate",mate_tree,proto_mate); + mate_module = prefs_register_protocol(proto_mate, proto_reg_handoff_mate); + prefs_register_filename_preference(mate_module, "config", + "Configuration Filename", + "The name of the file containing the mate module's configuration", + &pref_mate_config_filename, FALSE); +#ifdef _AVP_DEBUGGING + prefs_register_uint_preference(mate_module, "avp_debug_general", + "AVP Debug general", + "General debugging level (0..5)", + 10, + &pref_avp_debug_general); + prefs_register_uint_preference(mate_module, "avp_debug_avp", + "Debug AVP", + "Attribute Value Pairs debugging level (0..5)", + 10, + &pref_avp_debug_avp); + prefs_register_uint_preference(mate_module, "avp_debug_avp_op", + "Debug AVP operations", + "Attribute Value Pairs operations debugging level (0..5)", + 10, + &pref_avp_debug_avp_op); + prefs_register_uint_preference(mate_module, "avp_debug_avpl", + "Debug AVP list", + "Attribute Value Pairs list debugging level (0..5)", + 10, + &pref_avp_debug_avpl); + prefs_register_uint_preference(mate_module, "avp_debug_avpl_op", + "Debug AVP list operations", + "Attribute Value Pairs list operations debugging level (0..5)", + 10, + &pref_avp_debug_avpl_op); +#endif + + register_postdissector(mate_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: + */ diff --git a/plugins/epan/opcua/AUTHORS b/plugins/epan/opcua/AUTHORS new file mode 100644 index 00000000..fffa8685 --- /dev/null +++ b/plugins/epan/opcua/AUTHORS @@ -0,0 +1,7 @@ +Authors : +Gerhard Gappmeier +Hannes Mezger +ascolab GmbH +http://www.ascolab.com + + diff --git a/plugins/epan/opcua/CMakeLists.txt b/plugins/epan/opcua/CMakeLists.txt new file mode 100644 index 00000000..2f43d42c --- /dev/null +++ b/plugins/epan/opcua/CMakeLists.txt @@ -0,0 +1,81 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(opcua 1 0 0 0) + +set(DISSECTOR_SRC + opcua.c +) + +set(DISSECTOR_SUPPORT_SRC + opcua_transport_layer.c + opcua_security_layer.c + opcua_application_layer.c + opcua_serviceparser.c + opcua_complextypeparser.c + opcua_enumparser.c + opcua_simpletypes.c + opcua_servicetable.c + opcua_extensionobjecttable.c + opcua_hfindeces.c + opcua_statuscode.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +add_wireshark_plugin_library(opcua epan) + +target_link_libraries(opcua epan) + +install_plugin(opcua epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + opcua + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/opcua/ChangeLog b/plugins/epan/opcua/ChangeLog new file mode 100644 index 00000000..5ebfc8f9 --- /dev/null +++ b/plugins/epan/opcua/ChangeLog @@ -0,0 +1,19 @@ +Overview of changes in OpcUa plugin: + +Version 0.0.1: + +* initial implementation without security + +Version 1.0.0: + +* released implementation that works for OPC UA V1.0. + - The protocol is not compatible to the previous version. + Transport-layer, security-layer as well as the application-layer + data types have changed. + - This implementation is compliant to + "OPC UA Part 6 - Mappings 1.00 Specification" + - The security-layer is always present, but this plugin can only + decode communication with security policy + http://opcfoundation.org/UA/SecurityPolicy#None, which means + that neither encryption nor signing is active. + diff --git a/plugins/epan/opcua/Doxyfile b/plugins/epan/opcua/Doxyfile new file mode 100644 index 00000000..478bcdb8 --- /dev/null +++ b/plugins/epan/opcua/Doxyfile @@ -0,0 +1,275 @@ +# Doxyfile 1.4.1-KDevelop + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = opcua.kdevelop +PROJECT_NUMBER = $VERSION$ +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = /home/gergap/ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = /home/gergap/work/wireshark/plugins/opcua +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.C \ + *.H \ + *.tlh \ + *.diff \ + *.patch \ + *.moc \ + *.xpm \ + *.dox +RECURSIVE = yes +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = yes +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = opcua.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/plugins/epan/opcua/README b/plugins/epan/opcua/README new file mode 100644 index 00000000..8c4993be --- /dev/null +++ b/plugins/epan/opcua/README @@ -0,0 +1,86 @@ +OpcUa Plugin: +============= + +This plugin implements the dissection of the OpcUa Binary Protocol. +Authors: Gerhard Gappmeier & Hannes Mezger + ascolab GmbH + http://www.ascolab.com + +Overview: +========= + +OpcUa (OPC Unified Architecture) is a vendor and platform independent +protocol for automation technology. It is the successor of the +COM/DCOM based specifications OPC DA, OPC Alarm & Events, OPC HDA, etc. +It unifies all this technologies into a single protocol. + +The specification describes abstract services that are independent +of the underlying protocol. For now there exist protocol mappings +to a Binary TCP based protocol and a SOAP based Webservice. +Also a hybrid version will be available where the Binary messages are transported +by a single webservice command called "Invoke". + +More information about the technology you can find on +http://www.ascolab.com/index.php?file=ua&lang=en. + +Protocol Mappings: +================== + +Binary (TCP): The fastest and most flexible version (small footprint, no XML and SOAP necessary) + can easily be tunneled (SSH, IPSEC, etc.), redirected, ... +SOAP version: Easy to implement with verious tools like .Net, JAVA, gSOAP, etc. + Better to communicate through firewalls via HTTP. +SOAP with Binary Attachment: Combines the advantages of both. + The messages are encoded as Binary, and transported via SOAP as binary + attachment. + +The OPC Foundation offers a free Opc Ua stack implementation in ANSI C +for all members. This stack implements the binary protocol as well +as the SOAP version. It's easily portable to different kinds of operating +systems from embedded devices to servers. +This makes it easy to implement Opc Ua applications based on this stack +and it is expected that the binary protocol will be the most used +protocol. +Nevertheless it's free to everbody to implement an own stack according +to the specification. An own implementation of the SOAP version +should be easy with the various SOAP toolkits. + +For more information see http://www.opcfoundation.org + +Known limitations: +================== + +* Only the security policy http://opcfoundation.org/UA/SecurityPolicy#None is + supported, which means the encryption and signing is turned off. + +Machine-generated dissector: +============================ +Parts of the OpcUa dissector are machine generated. Several of the files are +marked "DON'T MODIFY THIS FILE!" for this reason. + +However, the code to create this dissector is not part of the Wireshark source +source code distribution. This was discussed prior to the plugin's inclusion. +From https://www.wireshark.org/lists/wireshark-dev/200704/msg00025.html : + +~~~ +> a lot of the code seems to be autogenerated (as the comments suggest) +> It might make sense to include the sources and the build process instead +> of the intermediate files (if the amount of code/tools to build the +> files seems reasonable). The reason: When people start to hack your code +> (e.g. to remove warnings on a compiler you don't even think about), +> you'll might get into annoying trouble with merging code the next time +> you've update the upcua files. +> +> +I'm sorry, but I cannot give you the sources of the code generator, +because they are owned by the OPC Foundation. +I only extended the existing code generator to produce also wireshark code. +It's .Net based so I guess you don't want to have it anyway ;-) +~~~ + +So, if changes must be made to the machine-generated files, it just means the +upstream source will have to be modified before pushing any updates back to +Wireshark. + +Of course it also means that care must be taken when applying patches from +upstream to ensure local changes aren't reversed. diff --git a/plugins/epan/opcua/opcua.c b/plugins/epan/opcua/opcua.c new file mode 100644 index 00000000..7eec5b69 --- /dev/null +++ b/plugins/epan/opcua/opcua.c @@ -0,0 +1,457 @@ +/****************************************************************************** +** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Protocol Decoder. +** +** Author: Gerhard Gappmeier +******************************************************************************/ + +#include "config.h" + +#include +#include +#include +#include "opcua_transport_layer.h" +#include "opcua_security_layer.h" +#include "opcua_application_layer.h" +#include "opcua_complextypeparser.h" +#include "opcua_serviceparser.h" +#include "opcua_enumparser.h" +#include "opcua_simpletypes.h" +#include "opcua_hfindeces.h" + +void proto_register_opcua(void); + +extern const value_string g_requesttypes[]; +extern const int g_NumServices; + +/* forward reference */ +void proto_reg_handoff_opcua(void); +/* declare parse function pointer */ +typedef int (*FctParse)(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); + +int proto_opcua = -1; +static dissector_handle_t opcua_handle; +/** Official IANA registered port for OPC UA Binary Protocol. */ +#define OPCUA_PORT_RANGE "4840" + +/** subtree types used in opcua_transport_layer.c */ +gint ett_opcua_extensionobject = -1; +gint ett_opcua_nodeid = -1; + +/** subtree types used locally */ +static gint ett_opcua_transport = -1; +static gint ett_opcua_fragment = -1; +static gint ett_opcua_fragments = -1; + +static int hf_opcua_fragments = -1; +static int hf_opcua_fragment = -1; +static int hf_opcua_fragment_overlap = -1; +static int hf_opcua_fragment_overlap_conflicts = -1; +static int hf_opcua_fragment_multiple_tails = -1; +static int hf_opcua_fragment_too_long_fragment = -1; +static int hf_opcua_fragment_error = -1; +static int hf_opcua_fragment_count = -1; +static int hf_opcua_reassembled_in = -1; +static int hf_opcua_reassembled_length = -1; + +static const fragment_items opcua_frag_items = { + /* Fragment subtrees */ + &ett_opcua_fragment, + &ett_opcua_fragments, + /* Fragment fields */ + &hf_opcua_fragments, + &hf_opcua_fragment, + &hf_opcua_fragment_overlap, + &hf_opcua_fragment_overlap_conflicts, + &hf_opcua_fragment_multiple_tails, + &hf_opcua_fragment_too_long_fragment, + &hf_opcua_fragment_error, + &hf_opcua_fragment_count, + /* Reassembled in field */ + &hf_opcua_reassembled_in, + /* Reassembled length field */ + &hf_opcua_reassembled_length, + /* Reassembled data field */ + NULL, + /* Tag */ + "Message fragments" +}; + + +static reassembly_table opcua_reassembly_table; + +/** OpcUa Transport Message Types */ +enum MessageType +{ + MSG_HELLO = 0, + MSG_ACKNOWLEDGE, + MSG_ERROR, + MSG_REVERSEHELLO, + MSG_MESSAGE, + MSG_OPENSECURECHANNEL, + MSG_CLOSESECURECHANNEL, + MSG_INVALID +}; + +/** OpcUa Transport Message Type Names */ +static const char* g_szMessageTypes[] = +{ + "Hello message", + "Acknowledge message", + "Error message", + "Reverse Hello message", + "UA Secure Conversation Message", + "OpenSecureChannel message", + "CloseSecureChannel message", + "Invalid message" +}; + + + + +/** header length that is needed to compute + * the pdu length. + * @see get_opcua_message_len + */ +#define FRAME_HEADER_LEN 8 + +/** returns the length of an OpcUa message. + * This function reads the length information from + * the transport header. + */ +static guint get_opcua_message_len(packet_info *pinfo _U_, tvbuff_t *tvb, + int offset, void *data _U_) +{ + gint32 plen; + + /* the message length starts at offset 4 */ + plen = tvb_get_letohl(tvb, offset + 4); + + return plen; +} + +/** The OpcUa message dissector. + * This method dissects full OpcUa messages. + * It gets only called with reassembled data + * from tcp_dissect_pdus. + */ +static int dissect_opcua_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + FctParse pfctParse = NULL; + enum MessageType msgtype = MSG_INVALID; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "OpcUa"); + + /* parse message type */ + if (tvb_memeql(tvb, 0, (const guint8 * )"HEL", 3) == 0) + { + msgtype = MSG_HELLO; + pfctParse = parseHello; + } + else if (tvb_memeql(tvb, 0, (const guint8*)"ACK", 3) == 0) + { + msgtype = MSG_ACKNOWLEDGE; + pfctParse = parseAcknowledge; + } + else if (tvb_memeql(tvb, 0, (const guint8*)"ERR", 3) == 0) + { + msgtype = MSG_ERROR; + pfctParse = parseError; + } + else if (tvb_memeql(tvb, 0, (const guint8*)"RHE", 3) == 0) + { + msgtype = MSG_REVERSEHELLO; + pfctParse = parseReverseHello; + } + else if (tvb_memeql(tvb, 0, (const guint8*)"MSG", 3) == 0) + { + msgtype = MSG_MESSAGE; + pfctParse = parseMessage; + } + else if (tvb_memeql(tvb, 0, (const guint8*)"OPN", 3) == 0) + { + msgtype = MSG_OPENSECURECHANNEL; + pfctParse = parseOpenSecureChannel; + } + else if (tvb_memeql(tvb, 0, (const guint8*)"CLO", 3) == 0) + { + msgtype = MSG_CLOSESECURECHANNEL; + pfctParse = parseCloseSecureChannel; + } + else + { + msgtype = MSG_INVALID; + + /* Clear out stuff in the info column */ + col_set_str(pinfo->cinfo, COL_INFO, g_szMessageTypes[msgtype]); + + /* add empty item to make filtering by 'opcua' work */ + proto_tree_add_item(tree, proto_opcua, tvb, 0, -1, ENC_NA); + + return tvb_reported_length(tvb); + } + + /* Clear out stuff in the info column */ + col_set_str(pinfo->cinfo, COL_INFO, g_szMessageTypes[msgtype]); + + if (pfctParse) + { + gint offset = 0; + int iServiceId = -1; + tvbuff_t *next_tvb = tvb; + gboolean bParseService = TRUE; + gboolean bIsLastFragment = FALSE; + + /* we are being asked for details */ + proto_item *ti = NULL; + proto_tree *transport_tree = NULL; + + ti = proto_tree_add_item(tree, proto_opcua, tvb, 0, -1, ENC_NA); + transport_tree = proto_item_add_subtree(ti, ett_opcua_transport); + + /* MSG_MESSAGE might be fragmented, check for that */ + if (msgtype == MSG_MESSAGE) + { + guint8 chunkType = 0; + guint32 opcua_seqid = 0; + guint32 opcua_num = 0; + guint32 opcua_seqnum; + fragment_head *frag_msg = NULL; + fragment_item *frag_i = NULL; + + offset = 3; + + chunkType = tvb_get_guint8(tvb, offset); offset += 1; + + offset += 4; /* Message Size */ + offset += 4; /* SecureChannelId */ + offset += 4; /* Security Token Id */ + + opcua_num = tvb_get_letohl(tvb, offset); offset += 4; /* Security Sequence Number */ + opcua_seqid = tvb_get_letohl(tvb, offset); offset += 4; /* Security RequestId */ + + if (chunkType == 'A') + { + fragment_delete(&opcua_reassembly_table, pinfo, opcua_seqid, NULL); + + col_clear_fence(pinfo->cinfo, COL_INFO); + col_set_str(pinfo->cinfo, COL_INFO, "Abort message"); + + offset = 0; + (*pfctParse)(transport_tree, tvb, pinfo, &offset); + parseAbort(transport_tree, tvb, pinfo, &offset); + + return tvb_reported_length(tvb); + } + + /* check if tvb is part of a chunked message: + the UA protocol does not tell us that, so we look into + opcua_reassembly_table if the opcua_seqid belongs to a + chunked message */ + frag_msg = fragment_get(&opcua_reassembly_table, pinfo, opcua_seqid, NULL); + if (frag_msg == NULL) + { + frag_msg = fragment_get_reassembled_id(&opcua_reassembly_table, pinfo, opcua_seqid); + } + + if (frag_msg != NULL || chunkType != 'F') + { + gboolean bSaveFragmented = pinfo->fragmented; + gboolean bMoreFragments = TRUE; + tvbuff_t *new_tvb = NULL; + + pinfo->fragmented = TRUE; + + if (frag_msg == NULL) + { + /* first fragment */ + opcua_seqnum = 0; + } + else + { + /* the UA protocol does not number the chunks beginning from 0 but from a + arbitrary value, so we have to fake the numbers in the stored fragments. + this way Wireshark reassembles the message, as it expects the fragment + sequence numbers to start at 0 */ + for (frag_i = frag_msg->next; frag_i; frag_i = frag_i->next) {} + if (frag_i) { + opcua_seqnum = frag_i->offset + 1; + } else { + /* We should never have a fragment head with no fragment items, but + * just in case. + */ + opcua_seqnum = 0; + } + + if (chunkType == 'F') + { + bMoreFragments = FALSE; + } + } + + frag_msg = fragment_add_seq_check(&opcua_reassembly_table, + tvb, + offset, + pinfo, + opcua_seqid, /* ID for fragments belonging together */ + NULL, + opcua_seqnum, /* fragment sequence number */ + tvb_captured_length_remaining(tvb, offset), /* fragment length - to the end */ + bMoreFragments); /* More fragments? */ + + new_tvb = process_reassembled_data(tvb, + offset, + pinfo, + "Reassembled Message", + frag_msg, + &opcua_frag_items, + NULL, + transport_tree); + + if (new_tvb) + { + /* Reassembled */ + bIsLastFragment = TRUE; + } + else + { + /* Not last packet of reassembled UA message */ + col_append_fstr(pinfo->cinfo, COL_INFO, " (Message fragment %u)", opcua_num); + } + + if (new_tvb) + { + /* take it all */ + next_tvb = new_tvb; + } + else + { + /* only show transport header */ + bParseService = FALSE; + next_tvb = tvb_new_subset_remaining(tvb, 0); + } + + pinfo->fragmented = bSaveFragmented; + } + } + + offset = 0; + + /* call the transport message dissector */ + iServiceId = (*pfctParse)(transport_tree, tvb, pinfo, &offset); + + /* parse the service if not chunked or last chunk */ + if (msgtype == MSG_MESSAGE && bParseService) + { + if (bIsLastFragment != FALSE) + { + offset = 0; + } + iServiceId = parseService(transport_tree, next_tvb, pinfo, &offset); + } + + /* display the service type in addition to the message type */ + if (iServiceId != -1) + { + const gchar *szServiceName = val_to_str((guint32)iServiceId, g_requesttypes, "ServiceId %d"); + + if (bIsLastFragment == FALSE) + { + col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", g_szMessageTypes[msgtype], szServiceName); + } + else + { + col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s (Message Reassembled)", g_szMessageTypes[msgtype], szServiceName); + } + } + } + + return tvb_reported_length(tvb); +} + +/** The main OpcUa dissector functions. + * It uses tcp_dissect_pdus from packet-tcp.h + * to reassemble the TCP data. + */ +static int dissect_opcua(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + tcp_dissect_pdus(tvb, pinfo, tree, TRUE, FRAME_HEADER_LEN, + get_opcua_message_len, dissect_opcua_message, data); + return tvb_reported_length(tvb); +} + +/** plugin entry functions. + * This registers the OpcUa protocol. + */ +void proto_register_opcua(void) +{ + static hf_register_info hf[] = + { + /* id full name abbreviation type display strings bitmask blurb HFILL */ + {&hf_opcua_fragments, {"Message fragments", "opcua.fragments", FT_NONE, BASE_NONE, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_fragment, {"Message fragment", "opcua.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_fragment_overlap, {"Message fragment overlap", "opcua.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_fragment_overlap_conflicts, {"Message fragment overlapping with conflicting data", "opcua.fragment.overlap.conflicts", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_fragment_multiple_tails, {"Message has multiple tail fragments", "opcua.fragment.multiple_tails", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_fragment_too_long_fragment, {"Message fragment too long", "opcua.fragment.too_long_fragment", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_fragment_error, {"Message defragmentation error", "opcua.fragment.error", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_fragment_count, {"Message fragment count", "opcua.fragment.count", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_reassembled_in, {"Reassembled in", "opcua.reassembled.in", FT_FRAMENUM, BASE_NONE, NULL, 0x00, NULL, HFILL}}, + {&hf_opcua_reassembled_length, {"Reassembled length", "opcua.reassembled.length", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL}} + }; + + /** Setup protocol subtree array */ + static gint *ett[] = + { + &ett_opcua_extensionobject, + &ett_opcua_nodeid, + &ett_opcua_transport, + &ett_opcua_fragment, + &ett_opcua_fragments + }; + + proto_opcua = proto_register_protocol("OpcUa Binary Protocol", "OpcUa", "opcua"); + opcua_handle = register_dissector("opcua", dissect_opcua, proto_opcua); + + registerTransportLayerTypes(proto_opcua); + registerSecurityLayerTypes(proto_opcua); + registerApplicationLayerTypes(proto_opcua); + registerSimpleTypes(proto_opcua); + registerEnumTypes(proto_opcua); + registerComplexTypes(); + registerServiceTypes(); + registerFieldTypes(proto_opcua); + + proto_register_subtree_array(ett, array_length(ett)); + proto_register_field_array(proto_opcua, hf, array_length(hf)); + + reassembly_table_register(&opcua_reassembly_table, + &addresses_reassembly_table_functions); +} + +void proto_reg_handoff_opcua(void) +{ + dissector_add_uint_range_with_preference("tcp.port", OPCUA_PORT_RANGE, opcua_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/opcua/opcua_application_layer.c b/plugins/epan/opcua/opcua_application_layer.c new file mode 100644 index 00000000..688cd651 --- /dev/null +++ b/plugins/epan/opcua/opcua_application_layer.c @@ -0,0 +1,112 @@ +/****************************************************************************** +** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Application Layer Decoder. +** +** Author: Gerhard Gappmeier +******************************************************************************/ + +#include "config.h" + +#include +#include "opcua_application_layer.h" + +/** NodeId encoding mask table */ +static const value_string g_nodeidmasks[] = { + { 0x00, "Two byte encoded Numeric" }, + { 0x01, "Four byte encoded Numeric" }, + { 0x02, "Numeric of arbitrary length" }, + { 0x03, "String" }, + { 0x04, "GUID" }, + { 0x05, "Opaque" }, + { 0, NULL } +}; + +/** Service type table */ +extern const value_string g_requesttypes[]; + +static int hf_opcua_nodeid_encodingmask = -1; +static int hf_opcua_app_nsid = -1; +static int hf_opcua_app_numeric = -1; + +/** Register application layer types. */ +void registerApplicationLayerTypes(int proto) +{ + /** header field definitions */ + static hf_register_info hf[] = + { + /* id full name abbreviation type display strings bitmask blurb HFILL */ + {&hf_opcua_nodeid_encodingmask, {"NodeId EncodingMask", "opcua.servicenodeid.encodingmask", FT_UINT8, BASE_HEX, VALS(g_nodeidmasks), 0x0, NULL, HFILL}}, + {&hf_opcua_app_nsid, {"NodeId Namespace Index", "opcua.servicenodeid.nsid", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_app_numeric, {"NodeId Identifier Numeric", "opcua.servicenodeid.numeric", FT_UINT32, BASE_DEC, VALS(g_requesttypes), 0x0, NULL, HFILL}} + }; + + proto_register_field_array(proto, hf, array_length(hf)); +} + +/** Parses an OpcUa Service NodeId and returns the service type. + * In this cases the NodeId is always from type numeric and NSId = 0. + */ +int parseServiceNodeId(proto_tree *tree, tvbuff_t *tvb, gint *pOffset) +{ + gint iOffset = *pOffset; + guint8 EncodingMask; + guint32 Numeric = 0; + + EncodingMask = tvb_get_guint8(tvb, iOffset); + proto_tree_add_item(tree, hf_opcua_nodeid_encodingmask, tvb, iOffset, 1, ENC_LITTLE_ENDIAN); + iOffset++; + + switch(EncodingMask) + { + case 0x00: /* two byte node id */ + Numeric = tvb_get_guint8(tvb, iOffset); + proto_tree_add_item(tree, hf_opcua_app_numeric, tvb, iOffset, 1, ENC_LITTLE_ENDIAN); + iOffset+=1; + break; + case 0x01: /* four byte node id */ + proto_tree_add_item(tree, hf_opcua_app_nsid, tvb, iOffset, 1, ENC_LITTLE_ENDIAN); + iOffset+=1; + Numeric = tvb_get_letohs(tvb, iOffset); + proto_tree_add_item(tree, hf_opcua_app_numeric, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + iOffset+=2; + break; + case 0x02: /* numeric, that does not fit into four bytes */ + proto_tree_add_item(tree, hf_opcua_app_nsid, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + iOffset+=2; + Numeric = tvb_get_letohl(tvb, iOffset); + proto_tree_add_item(tree, hf_opcua_app_numeric, tvb, iOffset, 4, ENC_LITTLE_ENDIAN); + iOffset+=4; + break; + case 0x03: /* string */ + case 0x04: /* guid */ + case 0x05: /* opaque*/ + /* NOT USED */ + break; + }; + + *pOffset = iOffset; + + return Numeric; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/opcua/opcua_application_layer.h b/plugins/epan/opcua/opcua_application_layer.h new file mode 100644 index 00000000..c9b043e8 --- /dev/null +++ b/plugins/epan/opcua/opcua_application_layer.h @@ -0,0 +1,20 @@ +/****************************************************************************** +** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Application Layer Decoder. +** +** Author: Gerhard Gappmeier +******************************************************************************/ + +void registerApplicationLayerTypes(int proto); + +/* Ua type parsers */ +int parseServiceNodeId(proto_tree *tree, tvbuff_t *tvb, gint *pOffset); diff --git a/plugins/epan/opcua/opcua_complextypeparser.c b/plugins/epan/opcua/opcua_complextypeparser.c new file mode 100644 index 00000000..e37dd299 --- /dev/null +++ b/plugins/epan/opcua/opcua_complextypeparser.c @@ -0,0 +1,2264 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Complex Type Parser +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** +******************************************************************************/ + +#include "config.h" + +#include +#include "opcua_complextypeparser.h" +#include "opcua_enumparser.h" +#include "opcua_simpletypes.h" +#include "opcua_hfindeces.h" + +gint ett_opcua_TrustListDataType = -1; +gint ett_opcua_array_TrustListDataType = -1; +gint ett_opcua_Node = -1; +gint ett_opcua_array_Node = -1; +gint ett_opcua_InstanceNode = -1; +gint ett_opcua_array_InstanceNode = -1; +gint ett_opcua_TypeNode = -1; +gint ett_opcua_array_TypeNode = -1; +gint ett_opcua_ObjectNode = -1; +gint ett_opcua_array_ObjectNode = -1; +gint ett_opcua_ObjectTypeNode = -1; +gint ett_opcua_array_ObjectTypeNode = -1; +gint ett_opcua_VariableNode = -1; +gint ett_opcua_array_VariableNode = -1; +gint ett_opcua_VariableTypeNode = -1; +gint ett_opcua_array_VariableTypeNode = -1; +gint ett_opcua_ReferenceTypeNode = -1; +gint ett_opcua_array_ReferenceTypeNode = -1; +gint ett_opcua_MethodNode = -1; +gint ett_opcua_array_MethodNode = -1; +gint ett_opcua_ViewNode = -1; +gint ett_opcua_array_ViewNode = -1; +gint ett_opcua_DataTypeNode = -1; +gint ett_opcua_array_DataTypeNode = -1; +gint ett_opcua_ReferenceNode = -1; +gint ett_opcua_array_ReferenceNode = -1; +gint ett_opcua_Argument = -1; +gint ett_opcua_array_Argument = -1; +gint ett_opcua_EnumValueType = -1; +gint ett_opcua_array_EnumValueType = -1; +gint ett_opcua_OptionSet = -1; +gint ett_opcua_array_OptionSet = -1; +gint ett_opcua_TimeZoneDataType = -1; +gint ett_opcua_array_TimeZoneDataType = -1; +gint ett_opcua_ApplicationDescription = -1; +gint ett_opcua_array_ApplicationDescription = -1; +gint ett_opcua_RequestHeader = -1; +gint ett_opcua_array_RequestHeader = -1; +gint ett_opcua_ResponseHeader = -1; +gint ett_opcua_array_ResponseHeader = -1; +gint ett_opcua_ServerOnNetwork = -1; +gint ett_opcua_array_ServerOnNetwork = -1; +gint ett_opcua_UserTokenPolicy = -1; +gint ett_opcua_array_UserTokenPolicy = -1; +gint ett_opcua_EndpointDescription = -1; +gint ett_opcua_array_EndpointDescription = -1; +gint ett_opcua_RegisteredServer = -1; +gint ett_opcua_array_RegisteredServer = -1; +gint ett_opcua_MdnsDiscoveryConfiguration = -1; +gint ett_opcua_array_MdnsDiscoveryConfiguration = -1; +gint ett_opcua_ChannelSecurityToken = -1; +gint ett_opcua_array_ChannelSecurityToken = -1; +gint ett_opcua_SignedSoftwareCertificate = -1; +gint ett_opcua_array_SignedSoftwareCertificate = -1; +gint ett_opcua_SignatureData = -1; +gint ett_opcua_array_SignatureData = -1; +gint ett_opcua_UserIdentityToken = -1; +gint ett_opcua_array_UserIdentityToken = -1; +gint ett_opcua_AnonymousIdentityToken = -1; +gint ett_opcua_array_AnonymousIdentityToken = -1; +gint ett_opcua_UserNameIdentityToken = -1; +gint ett_opcua_array_UserNameIdentityToken = -1; +gint ett_opcua_X509IdentityToken = -1; +gint ett_opcua_array_X509IdentityToken = -1; +gint ett_opcua_KerberosIdentityToken = -1; +gint ett_opcua_array_KerberosIdentityToken = -1; +gint ett_opcua_IssuedIdentityToken = -1; +gint ett_opcua_array_IssuedIdentityToken = -1; +gint ett_opcua_NodeAttributes = -1; +gint ett_opcua_array_NodeAttributes = -1; +gint ett_opcua_ObjectAttributes = -1; +gint ett_opcua_array_ObjectAttributes = -1; +gint ett_opcua_VariableAttributes = -1; +gint ett_opcua_array_VariableAttributes = -1; +gint ett_opcua_MethodAttributes = -1; +gint ett_opcua_array_MethodAttributes = -1; +gint ett_opcua_ObjectTypeAttributes = -1; +gint ett_opcua_array_ObjectTypeAttributes = -1; +gint ett_opcua_VariableTypeAttributes = -1; +gint ett_opcua_array_VariableTypeAttributes = -1; +gint ett_opcua_ReferenceTypeAttributes = -1; +gint ett_opcua_array_ReferenceTypeAttributes = -1; +gint ett_opcua_DataTypeAttributes = -1; +gint ett_opcua_array_DataTypeAttributes = -1; +gint ett_opcua_ViewAttributes = -1; +gint ett_opcua_array_ViewAttributes = -1; +gint ett_opcua_AddNodesItem = -1; +gint ett_opcua_array_AddNodesItem = -1; +gint ett_opcua_AddNodesResult = -1; +gint ett_opcua_array_AddNodesResult = -1; +gint ett_opcua_AddReferencesItem = -1; +gint ett_opcua_array_AddReferencesItem = -1; +gint ett_opcua_DeleteNodesItem = -1; +gint ett_opcua_array_DeleteNodesItem = -1; +gint ett_opcua_DeleteReferencesItem = -1; +gint ett_opcua_array_DeleteReferencesItem = -1; +gint ett_opcua_ViewDescription = -1; +gint ett_opcua_array_ViewDescription = -1; +gint ett_opcua_BrowseDescription = -1; +gint ett_opcua_array_BrowseDescription = -1; +gint ett_opcua_ReferenceDescription = -1; +gint ett_opcua_array_ReferenceDescription = -1; +gint ett_opcua_BrowseResult = -1; +gint ett_opcua_array_BrowseResult = -1; +gint ett_opcua_RelativePathElement = -1; +gint ett_opcua_array_RelativePathElement = -1; +gint ett_opcua_RelativePath = -1; +gint ett_opcua_array_RelativePath = -1; +gint ett_opcua_BrowsePath = -1; +gint ett_opcua_array_BrowsePath = -1; +gint ett_opcua_BrowsePathTarget = -1; +gint ett_opcua_array_BrowsePathTarget = -1; +gint ett_opcua_BrowsePathResult = -1; +gint ett_opcua_array_BrowsePathResult = -1; +gint ett_opcua_EndpointConfiguration = -1; +gint ett_opcua_array_EndpointConfiguration = -1; +gint ett_opcua_SupportedProfile = -1; +gint ett_opcua_array_SupportedProfile = -1; +gint ett_opcua_SoftwareCertificate = -1; +gint ett_opcua_array_SoftwareCertificate = -1; +gint ett_opcua_QueryDataDescription = -1; +gint ett_opcua_array_QueryDataDescription = -1; +gint ett_opcua_NodeTypeDescription = -1; +gint ett_opcua_array_NodeTypeDescription = -1; +gint ett_opcua_QueryDataSet = -1; +gint ett_opcua_array_QueryDataSet = -1; +gint ett_opcua_NodeReference = -1; +gint ett_opcua_array_NodeReference = -1; +gint ett_opcua_ContentFilterElement = -1; +gint ett_opcua_array_ContentFilterElement = -1; +gint ett_opcua_ContentFilter = -1; +gint ett_opcua_array_ContentFilter = -1; +gint ett_opcua_ElementOperand = -1; +gint ett_opcua_array_ElementOperand = -1; +gint ett_opcua_LiteralOperand = -1; +gint ett_opcua_array_LiteralOperand = -1; +gint ett_opcua_AttributeOperand = -1; +gint ett_opcua_array_AttributeOperand = -1; +gint ett_opcua_SimpleAttributeOperand = -1; +gint ett_opcua_array_SimpleAttributeOperand = -1; +gint ett_opcua_ContentFilterElementResult = -1; +gint ett_opcua_array_ContentFilterElementResult = -1; +gint ett_opcua_ContentFilterResult = -1; +gint ett_opcua_array_ContentFilterResult = -1; +gint ett_opcua_ParsingResult = -1; +gint ett_opcua_array_ParsingResult = -1; +gint ett_opcua_ReadValueId = -1; +gint ett_opcua_array_ReadValueId = -1; +gint ett_opcua_HistoryReadValueId = -1; +gint ett_opcua_array_HistoryReadValueId = -1; +gint ett_opcua_HistoryReadResult = -1; +gint ett_opcua_array_HistoryReadResult = -1; +gint ett_opcua_ReadEventDetails = -1; +gint ett_opcua_array_ReadEventDetails = -1; +gint ett_opcua_ReadRawModifiedDetails = -1; +gint ett_opcua_array_ReadRawModifiedDetails = -1; +gint ett_opcua_ReadProcessedDetails = -1; +gint ett_opcua_array_ReadProcessedDetails = -1; +gint ett_opcua_ReadAtTimeDetails = -1; +gint ett_opcua_array_ReadAtTimeDetails = -1; +gint ett_opcua_HistoryData = -1; +gint ett_opcua_array_HistoryData = -1; +gint ett_opcua_ModificationInfo = -1; +gint ett_opcua_array_ModificationInfo = -1; +gint ett_opcua_HistoryModifiedData = -1; +gint ett_opcua_array_HistoryModifiedData = -1; +gint ett_opcua_HistoryEvent = -1; +gint ett_opcua_array_HistoryEvent = -1; +gint ett_opcua_WriteValue = -1; +gint ett_opcua_array_WriteValue = -1; +gint ett_opcua_HistoryUpdateDetails = -1; +gint ett_opcua_array_HistoryUpdateDetails = -1; +gint ett_opcua_UpdateDataDetails = -1; +gint ett_opcua_array_UpdateDataDetails = -1; +gint ett_opcua_UpdateStructureDataDetails = -1; +gint ett_opcua_array_UpdateStructureDataDetails = -1; +gint ett_opcua_UpdateEventDetails = -1; +gint ett_opcua_array_UpdateEventDetails = -1; +gint ett_opcua_DeleteRawModifiedDetails = -1; +gint ett_opcua_array_DeleteRawModifiedDetails = -1; +gint ett_opcua_DeleteAtTimeDetails = -1; +gint ett_opcua_array_DeleteAtTimeDetails = -1; +gint ett_opcua_DeleteEventDetails = -1; +gint ett_opcua_array_DeleteEventDetails = -1; +gint ett_opcua_HistoryUpdateResult = -1; +gint ett_opcua_array_HistoryUpdateResult = -1; +gint ett_opcua_CallMethodRequest = -1; +gint ett_opcua_array_CallMethodRequest = -1; +gint ett_opcua_CallMethodResult = -1; +gint ett_opcua_array_CallMethodResult = -1; +gint ett_opcua_DataChangeFilter = -1; +gint ett_opcua_array_DataChangeFilter = -1; +gint ett_opcua_EventFilter = -1; +gint ett_opcua_array_EventFilter = -1; +gint ett_opcua_AggregateConfiguration = -1; +gint ett_opcua_array_AggregateConfiguration = -1; +gint ett_opcua_AggregateFilter = -1; +gint ett_opcua_array_AggregateFilter = -1; +gint ett_opcua_EventFilterResult = -1; +gint ett_opcua_array_EventFilterResult = -1; +gint ett_opcua_AggregateFilterResult = -1; +gint ett_opcua_array_AggregateFilterResult = -1; +gint ett_opcua_MonitoringParameters = -1; +gint ett_opcua_array_MonitoringParameters = -1; +gint ett_opcua_MonitoredItemCreateRequest = -1; +gint ett_opcua_array_MonitoredItemCreateRequest = -1; +gint ett_opcua_MonitoredItemCreateResult = -1; +gint ett_opcua_array_MonitoredItemCreateResult = -1; +gint ett_opcua_MonitoredItemModifyRequest = -1; +gint ett_opcua_array_MonitoredItemModifyRequest = -1; +gint ett_opcua_MonitoredItemModifyResult = -1; +gint ett_opcua_array_MonitoredItemModifyResult = -1; +gint ett_opcua_NotificationMessage = -1; +gint ett_opcua_array_NotificationMessage = -1; +gint ett_opcua_DataChangeNotification = -1; +gint ett_opcua_array_DataChangeNotification = -1; +gint ett_opcua_MonitoredItemNotification = -1; +gint ett_opcua_array_MonitoredItemNotification = -1; +gint ett_opcua_EventNotificationList = -1; +gint ett_opcua_array_EventNotificationList = -1; +gint ett_opcua_EventFieldList = -1; +gint ett_opcua_array_EventFieldList = -1; +gint ett_opcua_HistoryEventFieldList = -1; +gint ett_opcua_array_HistoryEventFieldList = -1; +gint ett_opcua_StatusChangeNotification = -1; +gint ett_opcua_array_StatusChangeNotification = -1; +gint ett_opcua_SubscriptionAcknowledgement = -1; +gint ett_opcua_array_SubscriptionAcknowledgement = -1; +gint ett_opcua_TransferResult = -1; +gint ett_opcua_array_TransferResult = -1; +gint ett_opcua_ScalarTestType = -1; +gint ett_opcua_array_ScalarTestType = -1; +gint ett_opcua_ArrayTestType = -1; +gint ett_opcua_array_ArrayTestType = -1; +gint ett_opcua_CompositeTestType = -1; +gint ett_opcua_array_CompositeTestType = -1; +gint ett_opcua_BuildInfo = -1; +gint ett_opcua_array_BuildInfo = -1; +gint ett_opcua_RedundantServerDataType = -1; +gint ett_opcua_array_RedundantServerDataType = -1; +gint ett_opcua_EndpointUrlListDataType = -1; +gint ett_opcua_array_EndpointUrlListDataType = -1; +gint ett_opcua_NetworkGroupDataType = -1; +gint ett_opcua_array_NetworkGroupDataType = -1; +gint ett_opcua_SamplingIntervalDiagnosticsDataType = -1; +gint ett_opcua_array_SamplingIntervalDiagnosticsDataType = -1; +gint ett_opcua_ServerDiagnosticsSummaryDataType = -1; +gint ett_opcua_array_ServerDiagnosticsSummaryDataType = -1; +gint ett_opcua_ServerStatusDataType = -1; +gint ett_opcua_array_ServerStatusDataType = -1; +gint ett_opcua_SessionDiagnosticsDataType = -1; +gint ett_opcua_array_SessionDiagnosticsDataType = -1; +gint ett_opcua_SessionSecurityDiagnosticsDataType = -1; +gint ett_opcua_array_SessionSecurityDiagnosticsDataType = -1; +gint ett_opcua_ServiceCounterDataType = -1; +gint ett_opcua_array_ServiceCounterDataType = -1; +gint ett_opcua_StatusResult = -1; +gint ett_opcua_array_StatusResult = -1; +gint ett_opcua_SubscriptionDiagnosticsDataType = -1; +gint ett_opcua_array_SubscriptionDiagnosticsDataType = -1; +gint ett_opcua_ModelChangeStructureDataType = -1; +gint ett_opcua_array_ModelChangeStructureDataType = -1; +gint ett_opcua_SemanticChangeStructureDataType = -1; +gint ett_opcua_array_SemanticChangeStructureDataType = -1; +gint ett_opcua_Range = -1; +gint ett_opcua_array_Range = -1; +gint ett_opcua_EUInformation = -1; +gint ett_opcua_array_EUInformation = -1; +gint ett_opcua_ComplexNumberType = -1; +gint ett_opcua_array_ComplexNumberType = -1; +gint ett_opcua_DoubleComplexNumberType = -1; +gint ett_opcua_array_DoubleComplexNumberType = -1; +gint ett_opcua_AxisInformation = -1; +gint ett_opcua_array_AxisInformation = -1; +gint ett_opcua_XVType = -1; +gint ett_opcua_array_XVType = -1; +gint ett_opcua_ProgramDiagnosticDataType = -1; +gint ett_opcua_array_ProgramDiagnosticDataType = -1; +gint ett_opcua_Annotation = -1; +gint ett_opcua_array_Annotation = -1; + +void parseTrustListDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_TrustListDataType, &ti, "%s: TrustListDataType", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedLists); + /* Array length field ignored: NoOfTrustedCertificates */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "TrustedCertificates", "ByteString", hf_opcua_TrustedCertificates, parseByteString, ett_opcua_array_ByteString); + /* Array length field ignored: NoOfTrustedCrls */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "TrustedCrls", "ByteString", hf_opcua_TrustedCrls, parseByteString, ett_opcua_array_ByteString); + /* Array length field ignored: NoOfIssuerCertificates */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "IssuerCertificates", "ByteString", hf_opcua_IssuerCertificates, parseByteString, ett_opcua_array_ByteString); + /* Array length field ignored: NoOfIssuerCrls */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "IssuerCrls", "ByteString", hf_opcua_IssuerCrls, parseByteString, ett_opcua_array_ByteString); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_Node, &ti, "%s: Node", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseInstanceNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_InstanceNode, &ti, "%s: InstanceNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_TypeNode, &ti, "%s: TypeNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseObjectNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ObjectNode, &ti, "%s: ObjectNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_EventNotifier); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseObjectTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ObjectTypeNode, &ti, "%s: ObjectTypeNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsAbstract); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseVariableNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_VariableNode, &ti, "%s: VariableNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + parseVariant(subtree, tvb, pinfo, pOffset, "Value"); + parseNodeId(subtree, tvb, pinfo, pOffset, "DataType"); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ValueRank); + /* Array length field ignored: NoOfArrayDimensions */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ArrayDimensions", "UInt32", hf_opcua_ArrayDimensions, parseUInt32, ett_opcua_array_UInt32); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_AccessLevel); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_UserAccessLevel); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_MinimumSamplingInterval); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_Historizing); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseVariableTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_VariableTypeNode, &ti, "%s: VariableTypeNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + parseVariant(subtree, tvb, pinfo, pOffset, "Value"); + parseNodeId(subtree, tvb, pinfo, pOffset, "DataType"); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ValueRank); + /* Array length field ignored: NoOfArrayDimensions */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ArrayDimensions", "UInt32", hf_opcua_ArrayDimensions, parseUInt32, ett_opcua_array_UInt32); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsAbstract); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReferenceTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReferenceTypeNode, &ti, "%s: ReferenceTypeNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsAbstract); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_Symmetric); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "InverseName"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMethodNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MethodNode, &ti, "%s: MethodNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_Executable); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_UserExecutable); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseViewNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ViewNode, &ti, "%s: ViewNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_ContainsNoLoops); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_EventNotifier); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDataTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DataTypeNode, &ti, "%s: DataTypeNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceNode", parseReferenceNode, ett_opcua_array_ReferenceNode); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsAbstract); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReferenceNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReferenceNode, &ti, "%s: ReferenceNode", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "ReferenceTypeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsInverse); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "TargetId"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseArgument(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_Argument, &ti, "%s: Argument", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_Name); + parseNodeId(subtree, tvb, pinfo, pOffset, "DataType"); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ValueRank); + /* Array length field ignored: NoOfArrayDimensions */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ArrayDimensions", "UInt32", hf_opcua_ArrayDimensions, parseUInt32, ett_opcua_array_UInt32); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEnumValueType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EnumValueType, &ti, "%s: EnumValueType", szFieldName); + parseInt64(subtree, tvb, pinfo, pOffset, hf_opcua_Value); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseOptionSet(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_OptionSet, &ti, "%s: OptionSet", szFieldName); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_Value); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ValidBits); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTimeZoneDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_TimeZoneDataType, &ti, "%s: TimeZoneDataType", szFieldName); + parseInt16(subtree, tvb, pinfo, pOffset, hf_opcua_Offset); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_DaylightSavingInOffset); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseApplicationDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ApplicationDescription, &ti, "%s: ApplicationDescription", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ApplicationUri); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ProductUri); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "ApplicationName"); + parseApplicationType(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_GatewayServerUri); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_DiscoveryProfileUri); + /* Array length field ignored: NoOfDiscoveryUrls */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "DiscoveryUrls", "String", hf_opcua_DiscoveryUrls, parseString, ett_opcua_array_String); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRequestHeader(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + static int * const returnDiagnostics_mask[] = { + &hf_opcua_returnDiag_mask_sl_symbolicId, + &hf_opcua_returnDiag_mask_sl_localizedText, + &hf_opcua_returnDiag_mask_sl_additionalinfo, + &hf_opcua_returnDiag_mask_sl_innerstatuscode, + &hf_opcua_returnDiag_mask_sl_innerdiagnostics, + &hf_opcua_returnDiag_mask_ol_symbolicId, + &hf_opcua_returnDiag_mask_ol_localizedText, + &hf_opcua_returnDiag_mask_ol_additionalinfo, + &hf_opcua_returnDiag_mask_ol_innerstatuscode, + &hf_opcua_returnDiag_mask_ol_innerdiagnostics, + NULL}; + + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_RequestHeader, &ti, "%s: RequestHeader", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "AuthenticationToken"); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_Timestamp); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestHandle); + proto_tree_add_bitmask(subtree, tvb, *pOffset, hf_opcua_returnDiag, ett_opcua_returnDiagnostics, returnDiagnostics_mask, ENC_LITTLE_ENDIAN); *pOffset += 4; + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_AuditEntryId); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TimeoutHint); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "AdditionalHeader"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseResponseHeader(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ResponseHeader, &ti, "%s: ResponseHeader", szFieldName); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_Timestamp); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestHandle); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_ServiceResult); + parseDiagnosticInfo(subtree, tvb, pinfo, pOffset, "ServiceDiagnostics"); + /* Array length field ignored: NoOfStringTable */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "StringTable", "String", hf_opcua_StringTable, parseString, ett_opcua_array_String); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "AdditionalHeader"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseServerOnNetwork(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ServerOnNetwork, &ti, "%s: ServerOnNetwork", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RecordId); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_DiscoveryUrl); + /* Array length field ignored: NoOfServerCapabilities */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ServerCapabilities", "String", hf_opcua_ServerCapabilities, parseString, ett_opcua_array_String); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseUserTokenPolicy(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_UserTokenPolicy, &ti, "%s: UserTokenPolicy", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_PolicyId); + parseUserTokenType(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IssuedTokenType); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IssuerEndpointUrl); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_SecurityPolicyUri); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEndpointDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EndpointDescription, &ti, "%s: EndpointDescription", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_EndpointUrl); + parseApplicationDescription(subtree, tvb, pinfo, pOffset, "Server"); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerCertificate); + parseMessageSecurityMode(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_SecurityPolicyUri); + /* Array length field ignored: NoOfUserIdentityTokens */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "UserIdentityTokens", "UserTokenPolicy", parseUserTokenPolicy, ett_opcua_array_UserTokenPolicy); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_TransportProfileUri); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_SecurityLevel); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRegisteredServer(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_RegisteredServer, &ti, "%s: RegisteredServer", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerUri); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ProductUri); + /* Array length field ignored: NoOfServerNames */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ServerNames", "LocalizedText", parseLocalizedText, ett_opcua_array_LocalizedText); + parseApplicationType(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_GatewayServerUri); + /* Array length field ignored: NoOfDiscoveryUrls */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "DiscoveryUrls", "String", hf_opcua_DiscoveryUrls, parseString, ett_opcua_array_String); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_SemaphoreFilePath); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsOnline); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMdnsDiscoveryConfiguration(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MdnsDiscoveryConfiguration, &ti, "%s: MdnsDiscoveryConfiguration", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_MdnsServerName); + /* Array length field ignored: NoOfServerCapabilities */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ServerCapabilities", "String", hf_opcua_ServerCapabilities, parseString, ett_opcua_array_String); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseChannelSecurityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ChannelSecurityToken, &ti, "%s: ChannelSecurityToken", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ChannelId); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TokenId); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_CreatedAt); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedLifetime); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSignedSoftwareCertificate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SignedSoftwareCertificate, &ti, "%s: SignedSoftwareCertificate", szFieldName); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_CertificateData); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_Signature); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSignatureData(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SignatureData, &ti, "%s: SignatureData", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_Algorithm); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_Signature); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseUserIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_UserIdentityToken, &ti, "%s: UserIdentityToken", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_PolicyId); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAnonymousIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AnonymousIdentityToken, &ti, "%s: AnonymousIdentityToken", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_PolicyId); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseUserNameIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_UserNameIdentityToken, &ti, "%s: UserNameIdentityToken", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_PolicyId); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_UserName); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_Password); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_EncryptionAlgorithm); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseX509IdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_X509IdentityToken, &ti, "%s: X509IdentityToken", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_PolicyId); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_CertificateData); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseKerberosIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_KerberosIdentityToken, &ti, "%s: KerberosIdentityToken", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_PolicyId); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_TicketData); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseIssuedIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_IssuedIdentityToken, &ti, "%s: IssuedIdentityToken", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_PolicyId); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_TokenData); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_EncryptionAlgorithm); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseNodeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_NodeAttributes, &ti, "%s: NodeAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseObjectAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ObjectAttributes, &ti, "%s: ObjectAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_EventNotifier); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseVariableAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_VariableAttributes, &ti, "%s: VariableAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + parseVariant(subtree, tvb, pinfo, pOffset, "Value"); + parseNodeId(subtree, tvb, pinfo, pOffset, "DataType"); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ValueRank); + /* Array length field ignored: NoOfArrayDimensions */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ArrayDimensions", "UInt32", hf_opcua_ArrayDimensions, parseUInt32, ett_opcua_array_UInt32); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_AccessLevel); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_UserAccessLevel); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_MinimumSamplingInterval); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_Historizing); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMethodAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MethodAttributes, &ti, "%s: MethodAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_Executable); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_UserExecutable); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseObjectTypeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ObjectTypeAttributes, &ti, "%s: ObjectTypeAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsAbstract); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseVariableTypeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_VariableTypeAttributes, &ti, "%s: VariableTypeAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + parseVariant(subtree, tvb, pinfo, pOffset, "Value"); + parseNodeId(subtree, tvb, pinfo, pOffset, "DataType"); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ValueRank); + /* Array length field ignored: NoOfArrayDimensions */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ArrayDimensions", "UInt32", hf_opcua_ArrayDimensions, parseUInt32, ett_opcua_array_UInt32); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsAbstract); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReferenceTypeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReferenceTypeAttributes, &ti, "%s: ReferenceTypeAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsAbstract); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_Symmetric); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "InverseName"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDataTypeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DataTypeAttributes, &ti, "%s: DataTypeAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsAbstract); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseViewAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ViewAttributes, &ti, "%s: ViewAttributes", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SpecifiedAttributes); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_WriteMask); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UserWriteMask); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_ContainsNoLoops); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_EventNotifier); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAddNodesItem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AddNodesItem, &ti, "%s: AddNodesItem", szFieldName); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "ParentNodeId"); + parseNodeId(subtree, tvb, pinfo, pOffset, "ReferenceTypeId"); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "RequestedNewNodeId"); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "NodeAttributes"); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "TypeDefinition"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAddNodesResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AddNodesResult, &ti, "%s: AddNodesResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + parseNodeId(subtree, tvb, pinfo, pOffset, "AddedNodeId"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAddReferencesItem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AddReferencesItem, &ti, "%s: AddReferencesItem", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "SourceNodeId"); + parseNodeId(subtree, tvb, pinfo, pOffset, "ReferenceTypeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsForward); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_TargetServerUri); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "TargetNodeId"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteNodesItem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DeleteNodesItem, &ti, "%s: DeleteNodesItem", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_DeleteTargetReferences); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteReferencesItem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DeleteReferencesItem, &ti, "%s: DeleteReferencesItem", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "SourceNodeId"); + parseNodeId(subtree, tvb, pinfo, pOffset, "ReferenceTypeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsForward); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "TargetNodeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_DeleteBidirectional); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseViewDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ViewDescription, &ti, "%s: ViewDescription", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "ViewId"); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_Timestamp); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ViewVersion); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowseDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_BrowseDescription, &ti, "%s: BrowseDescription", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseBrowseDirection(subtree, tvb, pinfo, pOffset); + parseNodeId(subtree, tvb, pinfo, pOffset, "ReferenceTypeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IncludeSubtypes); + parseNodeClassMask(subtree, tvb, pinfo, pOffset); + parseResultMask(subtree, tvb, pinfo, pOffset); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReferenceDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReferenceDescription, &ti, "%s: ReferenceDescription", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "ReferenceTypeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsForward); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "BrowseName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseNodeClass(subtree, tvb, pinfo, pOffset); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "TypeDefinition"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowseResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_BrowseResult, &ti, "%s: BrowseResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ContinuationPoint); + /* Array length field ignored: NoOfReferences */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "References", "ReferenceDescription", parseReferenceDescription, ett_opcua_array_ReferenceDescription); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRelativePathElement(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_RelativePathElement, &ti, "%s: RelativePathElement", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "ReferenceTypeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsInverse); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IncludeSubtypes); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "TargetName"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRelativePath(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_RelativePath, &ti, "%s: RelativePath", szFieldName); + /* Array length field ignored: NoOfElements */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Elements", "RelativePathElement", parseRelativePathElement, ett_opcua_array_RelativePathElement); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowsePath(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_BrowsePath, &ti, "%s: BrowsePath", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "StartingNode"); + parseRelativePath(subtree, tvb, pinfo, pOffset, "RelativePath"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowsePathTarget(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_BrowsePathTarget, &ti, "%s: BrowsePathTarget", szFieldName); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "TargetId"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RemainingPathIndex); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowsePathResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_BrowsePathResult, &ti, "%s: BrowsePathResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + /* Array length field ignored: NoOfTargets */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Targets", "BrowsePathTarget", parseBrowsePathTarget, ett_opcua_array_BrowsePathTarget); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEndpointConfiguration(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EndpointConfiguration, &ti, "%s: EndpointConfiguration", szFieldName); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_OperationTimeout); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_UseBinaryEncoding); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxStringLength); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxByteStringLength); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxArrayLength); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxMessageSize); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxBufferSize); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ChannelLifetime); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SecurityTokenLifetime); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSupportedProfile(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SupportedProfile, &ti, "%s: SupportedProfile", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_OrganizationUri); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ProfileId); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ComplianceTool); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_ComplianceDate); + parseComplianceLevel(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfUnsupportedUnitIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "UnsupportedUnitIds", "String", hf_opcua_UnsupportedUnitIds, parseString, ett_opcua_array_String); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSoftwareCertificate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SoftwareCertificate, &ti, "%s: SoftwareCertificate", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ProductName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ProductUri); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_VendorName); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_VendorProductCertificate); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_SoftwareVersion); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_BuildNumber); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_BuildDate); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IssuedBy); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_IssueDate); + /* Array length field ignored: NoOfSupportedProfiles */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "SupportedProfiles", "SupportedProfile", parseSupportedProfile, ett_opcua_array_SupportedProfile); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseQueryDataDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_QueryDataDescription, &ti, "%s: QueryDataDescription", szFieldName); + parseRelativePath(subtree, tvb, pinfo, pOffset, "RelativePath"); + parseAttributeId(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IndexRange); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseNodeTypeDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_NodeTypeDescription, &ti, "%s: NodeTypeDescription", szFieldName); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "TypeDefinitionNode"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IncludeSubTypes); + /* Array length field ignored: NoOfDataToReturn */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DataToReturn", "QueryDataDescription", parseQueryDataDescription, ett_opcua_array_QueryDataDescription); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseQueryDataSet(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_QueryDataSet, &ti, "%s: QueryDataSet", szFieldName); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "TypeDefinitionNode"); + /* Array length field ignored: NoOfValues */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Values", "Variant", parseVariant, ett_opcua_array_Variant); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseNodeReference(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_NodeReference, &ti, "%s: NodeReference", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseNodeId(subtree, tvb, pinfo, pOffset, "ReferenceTypeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsForward); + /* Array length field ignored: NoOfReferencedNodeIds */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ReferencedNodeIds", "NodeId", parseNodeId, ett_opcua_array_NodeId); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseContentFilterElement(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ContentFilterElement, &ti, "%s: ContentFilterElement", szFieldName); + parseFilterOperator(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfFilterOperands */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "FilterOperands", "ExtensionObject", parseExtensionObject, ett_opcua_array_ExtensionObject); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseContentFilter(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ContentFilter, &ti, "%s: ContentFilter", szFieldName); + /* Array length field ignored: NoOfElements */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Elements", "ContentFilterElement", parseContentFilterElement, ett_opcua_array_ContentFilterElement); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseElementOperand(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ElementOperand, &ti, "%s: ElementOperand", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_Index); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseLiteralOperand(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_LiteralOperand, &ti, "%s: LiteralOperand", szFieldName); + parseVariant(subtree, tvb, pinfo, pOffset, "Value"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAttributeOperand(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AttributeOperand, &ti, "%s: AttributeOperand", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_Alias); + parseRelativePath(subtree, tvb, pinfo, pOffset, "BrowsePath"); + parseAttributeId(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IndexRange); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSimpleAttributeOperand(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SimpleAttributeOperand, &ti, "%s: SimpleAttributeOperand", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "TypeDefinitionId"); + /* Array length field ignored: NoOfBrowsePath */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "BrowsePath", "QualifiedName", parseQualifiedName, ett_opcua_array_QualifiedName); + parseAttributeId(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IndexRange); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseContentFilterElementResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ContentFilterElementResult, &ti, "%s: ContentFilterElementResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + /* Array length field ignored: NoOfOperandStatusCodes */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "OperandStatusCodes", "StatusCode", hf_opcua_OperandStatusCodes, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfOperandDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "OperandDiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseContentFilterResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ContentFilterResult, &ti, "%s: ContentFilterResult", szFieldName); + /* Array length field ignored: NoOfElementResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ElementResults", "ContentFilterElementResult", parseContentFilterElementResult, ett_opcua_array_ContentFilterElementResult); + /* Array length field ignored: NoOfElementDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ElementDiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseParsingResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ParsingResult, &ti, "%s: ParsingResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + /* Array length field ignored: NoOfDataStatusCodes */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "DataStatusCodes", "StatusCode", hf_opcua_DataStatusCodes, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDataDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DataDiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReadValueId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReadValueId, &ti, "%s: ReadValueId", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseAttributeId(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IndexRange); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "DataEncoding"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryReadValueId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_HistoryReadValueId, &ti, "%s: HistoryReadValueId", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IndexRange); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "DataEncoding"); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ContinuationPoint); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryReadResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_HistoryReadResult, &ti, "%s: HistoryReadResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ContinuationPoint); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "HistoryData"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReadEventDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReadEventDetails, &ti, "%s: ReadEventDetails", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_NumValuesPerNode); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_StartTime); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_EndTime); + parseEventFilter(subtree, tvb, pinfo, pOffset, "Filter"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReadRawModifiedDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReadRawModifiedDetails, &ti, "%s: ReadRawModifiedDetails", szFieldName); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsReadModified); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_StartTime); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_EndTime); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_NumValuesPerNode); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_ReturnBounds); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReadProcessedDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReadProcessedDetails, &ti, "%s: ReadProcessedDetails", szFieldName); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_StartTime); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_EndTime); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_ProcessingInterval); + /* Array length field ignored: NoOfAggregateType */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "AggregateType", "NodeId", parseNodeId, ett_opcua_array_NodeId); + parseAggregateConfiguration(subtree, tvb, pinfo, pOffset, "AggregateConfiguration"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReadAtTimeDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ReadAtTimeDetails, &ti, "%s: ReadAtTimeDetails", szFieldName); + /* Array length field ignored: NoOfReqTimes */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ReqTimes", "DateTime", hf_opcua_ReqTimes, parseDateTime, ett_opcua_array_DateTime); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_UseSimpleBounds); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryData(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_HistoryData, &ti, "%s: HistoryData", szFieldName); + /* Array length field ignored: NoOfDataValues */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DataValues", "DataValue", parseDataValue, ett_opcua_array_DataValue); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseModificationInfo(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ModificationInfo, &ti, "%s: ModificationInfo", szFieldName); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_ModificationTime); + parseHistoryUpdateType(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_UserName); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryModifiedData(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_HistoryModifiedData, &ti, "%s: HistoryModifiedData", szFieldName); + /* Array length field ignored: NoOfDataValues */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DataValues", "DataValue", parseDataValue, ett_opcua_array_DataValue); + /* Array length field ignored: NoOfModificationInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ModificationInfos", "ModificationInfo", parseModificationInfo, ett_opcua_array_ModificationInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryEvent(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_HistoryEvent, &ti, "%s: HistoryEvent", szFieldName); + /* Array length field ignored: NoOfEvents */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Events", "HistoryEventFieldList", parseHistoryEventFieldList, ett_opcua_array_HistoryEventFieldList); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseWriteValue(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_WriteValue, &ti, "%s: WriteValue", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseAttributeId(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_IndexRange); + parseDataValue(subtree, tvb, pinfo, pOffset, "Value"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryUpdateDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_HistoryUpdateDetails, &ti, "%s: HistoryUpdateDetails", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseUpdateDataDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_UpdateDataDetails, &ti, "%s: UpdateDataDetails", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parsePerformUpdateType(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfUpdateValues */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "UpdateValues", "DataValue", parseDataValue, ett_opcua_array_DataValue); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseUpdateStructureDataDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_UpdateStructureDataDetails, &ti, "%s: UpdateStructureDataDetails", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parsePerformUpdateType(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfUpdateValues */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "UpdateValues", "DataValue", parseDataValue, ett_opcua_array_DataValue); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseUpdateEventDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_UpdateEventDetails, &ti, "%s: UpdateEventDetails", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parsePerformUpdateType(subtree, tvb, pinfo, pOffset); + parseEventFilter(subtree, tvb, pinfo, pOffset, "Filter"); + /* Array length field ignored: NoOfEventData */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "EventData", "HistoryEventFieldList", parseHistoryEventFieldList, ett_opcua_array_HistoryEventFieldList); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteRawModifiedDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DeleteRawModifiedDetails, &ti, "%s: DeleteRawModifiedDetails", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_IsDeleteModified); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_StartTime); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_EndTime); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteAtTimeDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DeleteAtTimeDetails, &ti, "%s: DeleteAtTimeDetails", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + /* Array length field ignored: NoOfReqTimes */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ReqTimes", "DateTime", hf_opcua_ReqTimes, parseDateTime, ett_opcua_array_DateTime); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteEventDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DeleteEventDetails, &ti, "%s: DeleteEventDetails", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + /* Array length field ignored: NoOfEventIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "EventIds", "ByteString", hf_opcua_EventIds, parseByteString, ett_opcua_array_ByteString); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryUpdateResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_HistoryUpdateResult, &ti, "%s: HistoryUpdateResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + /* Array length field ignored: NoOfOperationResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "OperationResults", "StatusCode", hf_opcua_OperationResults, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCallMethodRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_CallMethodRequest, &ti, "%s: CallMethodRequest", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "ObjectId"); + parseNodeId(subtree, tvb, pinfo, pOffset, "MethodId"); + /* Array length field ignored: NoOfInputArguments */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "InputArguments", "Variant", parseVariant, ett_opcua_array_Variant); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCallMethodResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_CallMethodResult, &ti, "%s: CallMethodResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + /* Array length field ignored: NoOfInputArgumentResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "InputArgumentResults", "StatusCode", hf_opcua_InputArgumentResults, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfInputArgumentDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "InputArgumentDiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + /* Array length field ignored: NoOfOutputArguments */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "OutputArguments", "Variant", parseVariant, ett_opcua_array_Variant); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDataChangeFilter(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DataChangeFilter, &ti, "%s: DataChangeFilter", szFieldName); + parseDataChangeTrigger(subtree, tvb, pinfo, pOffset); + parseDeadbandType(subtree, tvb, pinfo, pOffset); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_DeadbandValue); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEventFilter(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EventFilter, &ti, "%s: EventFilter", szFieldName); + /* Array length field ignored: NoOfSelectClauses */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "SelectClauses", "SimpleAttributeOperand", parseSimpleAttributeOperand, ett_opcua_array_SimpleAttributeOperand); + parseContentFilter(subtree, tvb, pinfo, pOffset, "WhereClause"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAggregateConfiguration(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AggregateConfiguration, &ti, "%s: AggregateConfiguration", szFieldName); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_UseServerCapabilitiesDefaults); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_TreatUncertainAsBad); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_PercentDataBad); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_PercentDataGood); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_UseSlopedExtrapolation); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAggregateFilter(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AggregateFilter, &ti, "%s: AggregateFilter", szFieldName); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_StartTime); + parseNodeId(subtree, tvb, pinfo, pOffset, "AggregateType"); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_ProcessingInterval); + parseAggregateConfiguration(subtree, tvb, pinfo, pOffset, "AggregateConfiguration"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEventFilterResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EventFilterResult, &ti, "%s: EventFilterResult", szFieldName); + /* Array length field ignored: NoOfSelectClauseResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "SelectClauseResults", "StatusCode", hf_opcua_SelectClauseResults, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfSelectClauseDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "SelectClauseDiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + parseContentFilterResult(subtree, tvb, pinfo, pOffset, "WhereClauseResult"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAggregateFilterResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AggregateFilterResult, &ti, "%s: AggregateFilterResult", szFieldName); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedStartTime); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedProcessingInterval); + parseAggregateConfiguration(subtree, tvb, pinfo, pOffset, "RevisedAggregateConfiguration"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMonitoringParameters(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MonitoringParameters, &ti, "%s: MonitoringParameters", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ClientHandle); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_SamplingInterval); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "Filter"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_QueueSize); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_DiscardOldest); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMonitoredItemCreateRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MonitoredItemCreateRequest, &ti, "%s: MonitoredItemCreateRequest", szFieldName); + parseReadValueId(subtree, tvb, pinfo, pOffset, "ItemToMonitor"); + parseMonitoringMode(subtree, tvb, pinfo, pOffset); + parseMonitoringParameters(subtree, tvb, pinfo, pOffset, "RequestedParameters"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMonitoredItemCreateResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MonitoredItemCreateResult, &ti, "%s: MonitoredItemCreateResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MonitoredItemId); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedSamplingInterval); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedQueueSize); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "FilterResult"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMonitoredItemModifyRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MonitoredItemModifyRequest, &ti, "%s: MonitoredItemModifyRequest", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MonitoredItemId); + parseMonitoringParameters(subtree, tvb, pinfo, pOffset, "RequestedParameters"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMonitoredItemModifyResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MonitoredItemModifyResult, &ti, "%s: MonitoredItemModifyResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedSamplingInterval); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedQueueSize); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "FilterResult"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseNotificationMessage(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_NotificationMessage, &ti, "%s: NotificationMessage", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SequenceNumber); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_PublishTime); + /* Array length field ignored: NoOfNotificationData */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NotificationData", "ExtensionObject", parseExtensionObject, ett_opcua_array_ExtensionObject); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDataChangeNotification(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DataChangeNotification, &ti, "%s: DataChangeNotification", szFieldName); + /* Array length field ignored: NoOfMonitoredItems */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "MonitoredItems", "MonitoredItemNotification", parseMonitoredItemNotification, ett_opcua_array_MonitoredItemNotification); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseMonitoredItemNotification(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_MonitoredItemNotification, &ti, "%s: MonitoredItemNotification", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ClientHandle); + parseDataValue(subtree, tvb, pinfo, pOffset, "Value"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEventNotificationList(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EventNotificationList, &ti, "%s: EventNotificationList", szFieldName); + /* Array length field ignored: NoOfEvents */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Events", "EventFieldList", parseEventFieldList, ett_opcua_array_EventFieldList); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEventFieldList(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EventFieldList, &ti, "%s: EventFieldList", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ClientHandle); + /* Array length field ignored: NoOfEventFields */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "EventFields", "Variant", parseVariant, ett_opcua_array_Variant); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryEventFieldList(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_HistoryEventFieldList, &ti, "%s: HistoryEventFieldList", szFieldName); + /* Array length field ignored: NoOfEventFields */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "EventFields", "Variant", parseVariant, ett_opcua_array_Variant); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseStatusChangeNotification(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_StatusChangeNotification, &ti, "%s: StatusChangeNotification", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_Status); + parseDiagnosticInfo(subtree, tvb, pinfo, pOffset, "DiagnosticInfo"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSubscriptionAcknowledgement(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SubscriptionAcknowledgement, &ti, "%s: SubscriptionAcknowledgement", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SequenceNumber); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTransferResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_TransferResult, &ti, "%s: TransferResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + /* Array length field ignored: NoOfAvailableSequenceNumbers */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "AvailableSequenceNumbers", "UInt32", hf_opcua_AvailableSequenceNumbers, parseUInt32, ett_opcua_array_UInt32); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseScalarTestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ScalarTestType, &ti, "%s: ScalarTestType", szFieldName); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_Boolean); + parseSByte(subtree, tvb, pinfo, pOffset, hf_opcua_SByte); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_Byte); + parseInt16(subtree, tvb, pinfo, pOffset, hf_opcua_Int16); + parseUInt16(subtree, tvb, pinfo, pOffset, hf_opcua_UInt16); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_Int32); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UInt32); + parseInt64(subtree, tvb, pinfo, pOffset, hf_opcua_Int64); + parseUInt64(subtree, tvb, pinfo, pOffset, hf_opcua_UInt64); + parseFloat(subtree, tvb, pinfo, pOffset, hf_opcua_Float); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_Double); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_String); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_DateTime); + parseGuid(subtree, tvb, pinfo, pOffset, hf_opcua_Guid); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ByteString); + parseXmlElement(subtree, tvb, pinfo, pOffset, hf_opcua_XmlElement); + parseNodeId(subtree, tvb, pinfo, pOffset, "NodeId"); + parseExpandedNodeId(subtree, tvb, pinfo, pOffset, "ExpandedNodeId"); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + parseDiagnosticInfo(subtree, tvb, pinfo, pOffset, "DiagnosticInfo"); + parseQualifiedName(subtree, tvb, pinfo, pOffset, "QualifiedName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "LocalizedText"); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "ExtensionObject"); + parseDataValue(subtree, tvb, pinfo, pOffset, "DataValue"); + parseEnumeratedTestType(subtree, tvb, pinfo, pOffset); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseArrayTestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ArrayTestType, &ti, "%s: ArrayTestType", szFieldName); + /* Array length field ignored: NoOfBooleans */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Booleans", "Boolean", hf_opcua_Booleans, parseBoolean, ett_opcua_array_Boolean); + /* Array length field ignored: NoOfSBytes */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "SBytes", "SByte", hf_opcua_SBytes, parseSByte, ett_opcua_array_SByte); + /* Array length field ignored: NoOfInt16s */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Int16s", "Int16", hf_opcua_Int16s, parseInt16, ett_opcua_array_Int16); + /* Array length field ignored: NoOfUInt16s */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "UInt16s", "UInt16", hf_opcua_UInt16s, parseUInt16, ett_opcua_array_UInt16); + /* Array length field ignored: NoOfInt32s */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Int32s", "Int32", hf_opcua_Int32s, parseInt32, ett_opcua_array_Int32); + /* Array length field ignored: NoOfUInt32s */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "UInt32s", "UInt32", hf_opcua_UInt32s, parseUInt32, ett_opcua_array_UInt32); + /* Array length field ignored: NoOfInt64s */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Int64s", "Int64", hf_opcua_Int64s, parseInt64, ett_opcua_array_Int64); + /* Array length field ignored: NoOfUInt64s */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "UInt64s", "UInt64", hf_opcua_UInt64s, parseUInt64, ett_opcua_array_UInt64); + /* Array length field ignored: NoOfFloats */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Floats", "Float", hf_opcua_Floats, parseFloat, ett_opcua_array_Float); + /* Array length field ignored: NoOfDoubles */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Doubles", "Double", hf_opcua_Doubles, parseDouble, ett_opcua_array_Double); + /* Array length field ignored: NoOfStrings */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Strings", "String", hf_opcua_Strings, parseString, ett_opcua_array_String); + /* Array length field ignored: NoOfDateTimes */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "DateTimes", "DateTime", hf_opcua_DateTimes, parseDateTime, ett_opcua_array_DateTime); + /* Array length field ignored: NoOfGuids */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Guids", "Guid", hf_opcua_Guids, parseGuid, ett_opcua_array_Guid); + /* Array length field ignored: NoOfByteStrings */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ByteStrings", "ByteString", hf_opcua_ByteStrings, parseByteString, ett_opcua_array_ByteString); + /* Array length field ignored: NoOfXmlElements */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "XmlElements", "XmlElement", hf_opcua_XmlElements, parseXmlElement, ett_opcua_array_XmlElement); + /* Array length field ignored: NoOfNodeIds */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodeIds", "NodeId", parseNodeId, ett_opcua_array_NodeId); + /* Array length field ignored: NoOfExpandedNodeIds */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ExpandedNodeIds", "ExpandedNodeId", parseExpandedNodeId, ett_opcua_array_ExpandedNodeId); + /* Array length field ignored: NoOfStatusCodes */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "StatusCodes", "StatusCode", hf_opcua_StatusCodes, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + /* Array length field ignored: NoOfQualifiedNames */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "QualifiedNames", "QualifiedName", parseQualifiedName, ett_opcua_array_QualifiedName); + /* Array length field ignored: NoOfLocalizedTexts */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "LocalizedTexts", "LocalizedText", parseLocalizedText, ett_opcua_array_LocalizedText); + /* Array length field ignored: NoOfExtensionObjects */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ExtensionObjects", "ExtensionObject", parseExtensionObject, ett_opcua_array_ExtensionObject); + /* Array length field ignored: NoOfDataValues */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DataValues", "DataValue", parseDataValue, ett_opcua_array_DataValue); + /* Array length field ignored: NoOfVariants */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Variants", "Variant", parseVariant, ett_opcua_array_Variant); + /* Array length field ignored: NoOfEnumeratedValues */ + parseArrayEnum(subtree, tvb, pinfo, pOffset, "EnumeratedValues", "EnumeratedTestType", parseEnumeratedTestType, ett_opcua_array_EnumeratedTestType); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCompositeTestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_CompositeTestType, &ti, "%s: CompositeTestType", szFieldName); + parseScalarTestType(subtree, tvb, pinfo, pOffset, "Field1"); + parseArrayTestType(subtree, tvb, pinfo, pOffset, "Field2"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBuildInfo(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_BuildInfo, &ti, "%s: BuildInfo", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ProductUri); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ManufacturerName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ProductName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_SoftwareVersion); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_BuildNumber); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_BuildDate); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRedundantServerDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_RedundantServerDataType, &ti, "%s: RedundantServerDataType", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerId); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_ServiceLevel); + parseServerState(subtree, tvb, pinfo, pOffset); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEndpointUrlListDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EndpointUrlListDataType, &ti, "%s: EndpointUrlListDataType", szFieldName); + /* Array length field ignored: NoOfEndpointUrlList */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "EndpointUrlList", "String", hf_opcua_EndpointUrlList, parseString, ett_opcua_array_String); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseNetworkGroupDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_NetworkGroupDataType, &ti, "%s: NetworkGroupDataType", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerUri); + /* Array length field ignored: NoOfNetworkPaths */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NetworkPaths", "EndpointUrlListDataType", parseEndpointUrlListDataType, ett_opcua_array_EndpointUrlListDataType); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSamplingIntervalDiagnosticsDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SamplingIntervalDiagnosticsDataType, &ti, "%s: SamplingIntervalDiagnosticsDataType", szFieldName); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_SamplingInterval); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MonitoredItemCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxMonitoredItemCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_DisabledMonitoredItemCount); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseServerDiagnosticsSummaryDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ServerDiagnosticsSummaryDataType, &ti, "%s: ServerDiagnosticsSummaryDataType", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ServerViewCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CurrentSessionCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CumulatedSessionCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SecurityRejectedSessionCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RejectedSessionCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SessionTimeoutCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SessionAbortCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CurrentSubscriptionCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CumulatedSubscriptionCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_PublishingIntervalCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SecurityRejectedRequestsCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RejectedRequestsCount); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseServerStatusDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ServerStatusDataType, &ti, "%s: ServerStatusDataType", szFieldName); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_StartTime); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_CurrentTime); + parseServerState(subtree, tvb, pinfo, pOffset); + parseBuildInfo(subtree, tvb, pinfo, pOffset, "BuildInfo"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SecondsTillShutdown); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "ShutdownReason"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSessionDiagnosticsDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SessionDiagnosticsDataType, &ti, "%s: SessionDiagnosticsDataType", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "SessionId"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_SessionName); + parseApplicationDescription(subtree, tvb, pinfo, pOffset, "ClientDescription"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerUri); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_EndpointUrl); + /* Array length field ignored: NoOfLocaleIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "LocaleIds", "String", hf_opcua_LocaleIds, parseString, ett_opcua_array_String); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_ActualSessionTimeout); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxResponseMessageSize); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_ClientConnectionTime); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_ClientLastContactTime); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CurrentSubscriptionsCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CurrentMonitoredItemsCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CurrentPublishRequestsInQueue); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "TotalRequestCount"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UnauthorizedRequestCount); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "ReadCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "HistoryReadCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "WriteCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "HistoryUpdateCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "CallCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "CreateMonitoredItemsCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "ModifyMonitoredItemsCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "SetMonitoringModeCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "SetTriggeringCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "DeleteMonitoredItemsCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "CreateSubscriptionCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "ModifySubscriptionCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "SetPublishingModeCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "PublishCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "RepublishCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "TransferSubscriptionsCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "DeleteSubscriptionsCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "AddNodesCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "AddReferencesCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "DeleteNodesCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "DeleteReferencesCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "BrowseCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "BrowseNextCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "TranslateBrowsePathsToNodeIdsCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "QueryFirstCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "QueryNextCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "RegisterNodesCount"); + parseServiceCounterDataType(subtree, tvb, pinfo, pOffset, "UnregisterNodesCount"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSessionSecurityDiagnosticsDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SessionSecurityDiagnosticsDataType, &ti, "%s: SessionSecurityDiagnosticsDataType", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "SessionId"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ClientUserIdOfSession); + /* Array length field ignored: NoOfClientUserIdHistory */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ClientUserIdHistory", "String", hf_opcua_ClientUserIdHistory, parseString, ett_opcua_array_String); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_AuthenticationMechanism); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_Encoding); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_TransportProtocol); + parseMessageSecurityMode(subtree, tvb, pinfo, pOffset); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_SecurityPolicyUri); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ClientCertificate); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseServiceCounterDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ServiceCounterDataType, &ti, "%s: ServiceCounterDataType", szFieldName); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TotalCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ErrorCount); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseStatusResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_StatusResult, &ti, "%s: StatusResult", szFieldName); + parseStatusCode(subtree, tvb, pinfo, pOffset, hf_opcua_StatusCode); + parseDiagnosticInfo(subtree, tvb, pinfo, pOffset, "DiagnosticInfo"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSubscriptionDiagnosticsDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SubscriptionDiagnosticsDataType, &ti, "%s: SubscriptionDiagnosticsDataType", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "SessionId"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_Priority); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_PublishingInterval); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxKeepAliveCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxLifetimeCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxNotificationsPerPublish); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_PublishingEnabled); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ModifyCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_EnableCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_DisableCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RepublishRequestCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RepublishMessageRequestCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RepublishMessageCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TransferRequestCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TransferredToAltClientCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TransferredToSameClientCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_PublishRequestCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_DataChangeNotificationsCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_EventNotificationsCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_NotificationsCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_LatePublishRequestCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CurrentKeepAliveCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CurrentLifetimeCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UnacknowledgedMessageCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_DiscardedMessageCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MonitoredItemCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_DisabledMonitoredItemCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MonitoringQueueOverflowCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_NextSequenceNumber); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_EventQueueOverFlowCount); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseModelChangeStructureDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ModelChangeStructureDataType, &ti, "%s: ModelChangeStructureDataType", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "Affected"); + parseNodeId(subtree, tvb, pinfo, pOffset, "AffectedType"); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_Verb); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSemanticChangeStructureDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_SemanticChangeStructureDataType, &ti, "%s: SemanticChangeStructureDataType", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "Affected"); + parseNodeId(subtree, tvb, pinfo, pOffset, "AffectedType"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRange(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_Range, &ti, "%s: Range", szFieldName); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_Low); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_High); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseEUInformation(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_EUInformation, &ti, "%s: EUInformation", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_NamespaceUri); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_UnitId); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "DisplayName"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Description"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseComplexNumberType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ComplexNumberType, &ti, "%s: ComplexNumberType", szFieldName); + parseFloat(subtree, tvb, pinfo, pOffset, hf_opcua_Real); + parseFloat(subtree, tvb, pinfo, pOffset, hf_opcua_Imaginary); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDoubleComplexNumberType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_DoubleComplexNumberType, &ti, "%s: DoubleComplexNumberType", szFieldName); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_Real); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_Imaginary); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAxisInformation(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_AxisInformation, &ti, "%s: AxisInformation", szFieldName); + parseEUInformation(subtree, tvb, pinfo, pOffset, "EngineeringUnits"); + parseRange(subtree, tvb, pinfo, pOffset, "EURange"); + parseLocalizedText(subtree, tvb, pinfo, pOffset, "Title"); + parseAxisScaleEnumeration(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfAxisSteps */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "AxisSteps", "Double", hf_opcua_AxisSteps, parseDouble, ett_opcua_array_Double); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseXVType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_XVType, &ti, "%s: XVType", szFieldName); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_X); + parseFloat(subtree, tvb, pinfo, pOffset, hf_opcua_Value); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseProgramDiagnosticDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_ProgramDiagnosticDataType, &ti, "%s: ProgramDiagnosticDataType", szFieldName); + parseNodeId(subtree, tvb, pinfo, pOffset, "CreateSessionId"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_CreateClientName); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_InvocationCreationTime); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_LastTransitionTime); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_LastMethodCall); + parseNodeId(subtree, tvb, pinfo, pOffset, "LastMethodSessionId"); + /* Array length field ignored: NoOfLastMethodInputArguments */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "LastMethodInputArguments", "Argument", parseArgument, ett_opcua_array_Argument); + /* Array length field ignored: NoOfLastMethodOutputArguments */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "LastMethodOutputArguments", "Argument", parseArgument, ett_opcua_array_Argument); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_LastMethodCallTime); + parseStatusResult(subtree, tvb, pinfo, pOffset, "LastMethodReturnStatus"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAnnotation(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_Annotation, &ti, "%s: Annotation", szFieldName); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_Message); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_UserName); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_AnnotationTime); + proto_item_set_end(ti, tvb, *pOffset); +} + +/** Setup protocol subtree array */ +static gint *ett[] = +{ + &ett_opcua_TrustListDataType, + &ett_opcua_array_TrustListDataType, + &ett_opcua_Node, + &ett_opcua_array_Node, + &ett_opcua_InstanceNode, + &ett_opcua_array_InstanceNode, + &ett_opcua_TypeNode, + &ett_opcua_array_TypeNode, + &ett_opcua_ObjectNode, + &ett_opcua_array_ObjectNode, + &ett_opcua_ObjectTypeNode, + &ett_opcua_array_ObjectTypeNode, + &ett_opcua_VariableNode, + &ett_opcua_array_VariableNode, + &ett_opcua_VariableTypeNode, + &ett_opcua_array_VariableTypeNode, + &ett_opcua_ReferenceTypeNode, + &ett_opcua_array_ReferenceTypeNode, + &ett_opcua_MethodNode, + &ett_opcua_array_MethodNode, + &ett_opcua_ViewNode, + &ett_opcua_array_ViewNode, + &ett_opcua_DataTypeNode, + &ett_opcua_array_DataTypeNode, + &ett_opcua_ReferenceNode, + &ett_opcua_array_ReferenceNode, + &ett_opcua_Argument, + &ett_opcua_array_Argument, + &ett_opcua_EnumValueType, + &ett_opcua_array_EnumValueType, + &ett_opcua_OptionSet, + &ett_opcua_array_OptionSet, + &ett_opcua_TimeZoneDataType, + &ett_opcua_array_TimeZoneDataType, + &ett_opcua_ApplicationDescription, + &ett_opcua_array_ApplicationDescription, + &ett_opcua_RequestHeader, + &ett_opcua_array_RequestHeader, + &ett_opcua_ResponseHeader, + &ett_opcua_array_ResponseHeader, + &ett_opcua_ServerOnNetwork, + &ett_opcua_array_ServerOnNetwork, + &ett_opcua_UserTokenPolicy, + &ett_opcua_array_UserTokenPolicy, + &ett_opcua_EndpointDescription, + &ett_opcua_array_EndpointDescription, + &ett_opcua_RegisteredServer, + &ett_opcua_array_RegisteredServer, + &ett_opcua_MdnsDiscoveryConfiguration, + &ett_opcua_array_MdnsDiscoveryConfiguration, + &ett_opcua_ChannelSecurityToken, + &ett_opcua_array_ChannelSecurityToken, + &ett_opcua_SignedSoftwareCertificate, + &ett_opcua_array_SignedSoftwareCertificate, + &ett_opcua_SignatureData, + &ett_opcua_array_SignatureData, + &ett_opcua_UserIdentityToken, + &ett_opcua_array_UserIdentityToken, + &ett_opcua_AnonymousIdentityToken, + &ett_opcua_array_AnonymousIdentityToken, + &ett_opcua_UserNameIdentityToken, + &ett_opcua_array_UserNameIdentityToken, + &ett_opcua_X509IdentityToken, + &ett_opcua_array_X509IdentityToken, + &ett_opcua_KerberosIdentityToken, + &ett_opcua_array_KerberosIdentityToken, + &ett_opcua_IssuedIdentityToken, + &ett_opcua_array_IssuedIdentityToken, + &ett_opcua_NodeAttributes, + &ett_opcua_array_NodeAttributes, + &ett_opcua_ObjectAttributes, + &ett_opcua_array_ObjectAttributes, + &ett_opcua_VariableAttributes, + &ett_opcua_array_VariableAttributes, + &ett_opcua_MethodAttributes, + &ett_opcua_array_MethodAttributes, + &ett_opcua_ObjectTypeAttributes, + &ett_opcua_array_ObjectTypeAttributes, + &ett_opcua_VariableTypeAttributes, + &ett_opcua_array_VariableTypeAttributes, + &ett_opcua_ReferenceTypeAttributes, + &ett_opcua_array_ReferenceTypeAttributes, + &ett_opcua_DataTypeAttributes, + &ett_opcua_array_DataTypeAttributes, + &ett_opcua_ViewAttributes, + &ett_opcua_array_ViewAttributes, + &ett_opcua_AddNodesItem, + &ett_opcua_array_AddNodesItem, + &ett_opcua_AddNodesResult, + &ett_opcua_array_AddNodesResult, + &ett_opcua_AddReferencesItem, + &ett_opcua_array_AddReferencesItem, + &ett_opcua_DeleteNodesItem, + &ett_opcua_array_DeleteNodesItem, + &ett_opcua_DeleteReferencesItem, + &ett_opcua_array_DeleteReferencesItem, + &ett_opcua_ViewDescription, + &ett_opcua_array_ViewDescription, + &ett_opcua_BrowseDescription, + &ett_opcua_array_BrowseDescription, + &ett_opcua_ReferenceDescription, + &ett_opcua_array_ReferenceDescription, + &ett_opcua_BrowseResult, + &ett_opcua_array_BrowseResult, + &ett_opcua_RelativePathElement, + &ett_opcua_array_RelativePathElement, + &ett_opcua_RelativePath, + &ett_opcua_array_RelativePath, + &ett_opcua_BrowsePath, + &ett_opcua_array_BrowsePath, + &ett_opcua_BrowsePathTarget, + &ett_opcua_array_BrowsePathTarget, + &ett_opcua_BrowsePathResult, + &ett_opcua_array_BrowsePathResult, + &ett_opcua_EndpointConfiguration, + &ett_opcua_array_EndpointConfiguration, + &ett_opcua_SupportedProfile, + &ett_opcua_array_SupportedProfile, + &ett_opcua_SoftwareCertificate, + &ett_opcua_array_SoftwareCertificate, + &ett_opcua_QueryDataDescription, + &ett_opcua_array_QueryDataDescription, + &ett_opcua_NodeTypeDescription, + &ett_opcua_array_NodeTypeDescription, + &ett_opcua_QueryDataSet, + &ett_opcua_array_QueryDataSet, + &ett_opcua_NodeReference, + &ett_opcua_array_NodeReference, + &ett_opcua_ContentFilterElement, + &ett_opcua_array_ContentFilterElement, + &ett_opcua_ContentFilter, + &ett_opcua_array_ContentFilter, + &ett_opcua_ElementOperand, + &ett_opcua_array_ElementOperand, + &ett_opcua_LiteralOperand, + &ett_opcua_array_LiteralOperand, + &ett_opcua_AttributeOperand, + &ett_opcua_array_AttributeOperand, + &ett_opcua_SimpleAttributeOperand, + &ett_opcua_array_SimpleAttributeOperand, + &ett_opcua_ContentFilterElementResult, + &ett_opcua_array_ContentFilterElementResult, + &ett_opcua_ContentFilterResult, + &ett_opcua_array_ContentFilterResult, + &ett_opcua_ParsingResult, + &ett_opcua_array_ParsingResult, + &ett_opcua_ReadValueId, + &ett_opcua_array_ReadValueId, + &ett_opcua_HistoryReadValueId, + &ett_opcua_array_HistoryReadValueId, + &ett_opcua_HistoryReadResult, + &ett_opcua_array_HistoryReadResult, + &ett_opcua_ReadEventDetails, + &ett_opcua_array_ReadEventDetails, + &ett_opcua_ReadRawModifiedDetails, + &ett_opcua_array_ReadRawModifiedDetails, + &ett_opcua_ReadProcessedDetails, + &ett_opcua_array_ReadProcessedDetails, + &ett_opcua_ReadAtTimeDetails, + &ett_opcua_array_ReadAtTimeDetails, + &ett_opcua_HistoryData, + &ett_opcua_array_HistoryData, + &ett_opcua_ModificationInfo, + &ett_opcua_array_ModificationInfo, + &ett_opcua_HistoryModifiedData, + &ett_opcua_array_HistoryModifiedData, + &ett_opcua_HistoryEvent, + &ett_opcua_array_HistoryEvent, + &ett_opcua_WriteValue, + &ett_opcua_array_WriteValue, + &ett_opcua_HistoryUpdateDetails, + &ett_opcua_array_HistoryUpdateDetails, + &ett_opcua_UpdateDataDetails, + &ett_opcua_array_UpdateDataDetails, + &ett_opcua_UpdateStructureDataDetails, + &ett_opcua_array_UpdateStructureDataDetails, + &ett_opcua_UpdateEventDetails, + &ett_opcua_array_UpdateEventDetails, + &ett_opcua_DeleteRawModifiedDetails, + &ett_opcua_array_DeleteRawModifiedDetails, + &ett_opcua_DeleteAtTimeDetails, + &ett_opcua_array_DeleteAtTimeDetails, + &ett_opcua_DeleteEventDetails, + &ett_opcua_array_DeleteEventDetails, + &ett_opcua_HistoryUpdateResult, + &ett_opcua_array_HistoryUpdateResult, + &ett_opcua_CallMethodRequest, + &ett_opcua_array_CallMethodRequest, + &ett_opcua_CallMethodResult, + &ett_opcua_array_CallMethodResult, + &ett_opcua_DataChangeFilter, + &ett_opcua_array_DataChangeFilter, + &ett_opcua_EventFilter, + &ett_opcua_array_EventFilter, + &ett_opcua_AggregateConfiguration, + &ett_opcua_array_AggregateConfiguration, + &ett_opcua_AggregateFilter, + &ett_opcua_array_AggregateFilter, + &ett_opcua_EventFilterResult, + &ett_opcua_array_EventFilterResult, + &ett_opcua_AggregateFilterResult, + &ett_opcua_array_AggregateFilterResult, + &ett_opcua_MonitoringParameters, + &ett_opcua_array_MonitoringParameters, + &ett_opcua_MonitoredItemCreateRequest, + &ett_opcua_array_MonitoredItemCreateRequest, + &ett_opcua_MonitoredItemCreateResult, + &ett_opcua_array_MonitoredItemCreateResult, + &ett_opcua_MonitoredItemModifyRequest, + &ett_opcua_array_MonitoredItemModifyRequest, + &ett_opcua_MonitoredItemModifyResult, + &ett_opcua_array_MonitoredItemModifyResult, + &ett_opcua_NotificationMessage, + &ett_opcua_array_NotificationMessage, + &ett_opcua_DataChangeNotification, + &ett_opcua_array_DataChangeNotification, + &ett_opcua_MonitoredItemNotification, + &ett_opcua_array_MonitoredItemNotification, + &ett_opcua_EventNotificationList, + &ett_opcua_array_EventNotificationList, + &ett_opcua_EventFieldList, + &ett_opcua_array_EventFieldList, + &ett_opcua_HistoryEventFieldList, + &ett_opcua_array_HistoryEventFieldList, + &ett_opcua_StatusChangeNotification, + &ett_opcua_array_StatusChangeNotification, + &ett_opcua_SubscriptionAcknowledgement, + &ett_opcua_array_SubscriptionAcknowledgement, + &ett_opcua_TransferResult, + &ett_opcua_array_TransferResult, + &ett_opcua_ScalarTestType, + &ett_opcua_array_ScalarTestType, + &ett_opcua_ArrayTestType, + &ett_opcua_array_ArrayTestType, + &ett_opcua_CompositeTestType, + &ett_opcua_array_CompositeTestType, + &ett_opcua_BuildInfo, + &ett_opcua_array_BuildInfo, + &ett_opcua_RedundantServerDataType, + &ett_opcua_array_RedundantServerDataType, + &ett_opcua_EndpointUrlListDataType, + &ett_opcua_array_EndpointUrlListDataType, + &ett_opcua_NetworkGroupDataType, + &ett_opcua_array_NetworkGroupDataType, + &ett_opcua_SamplingIntervalDiagnosticsDataType, + &ett_opcua_array_SamplingIntervalDiagnosticsDataType, + &ett_opcua_ServerDiagnosticsSummaryDataType, + &ett_opcua_array_ServerDiagnosticsSummaryDataType, + &ett_opcua_ServerStatusDataType, + &ett_opcua_array_ServerStatusDataType, + &ett_opcua_SessionDiagnosticsDataType, + &ett_opcua_array_SessionDiagnosticsDataType, + &ett_opcua_SessionSecurityDiagnosticsDataType, + &ett_opcua_array_SessionSecurityDiagnosticsDataType, + &ett_opcua_ServiceCounterDataType, + &ett_opcua_array_ServiceCounterDataType, + &ett_opcua_StatusResult, + &ett_opcua_array_StatusResult, + &ett_opcua_SubscriptionDiagnosticsDataType, + &ett_opcua_array_SubscriptionDiagnosticsDataType, + &ett_opcua_ModelChangeStructureDataType, + &ett_opcua_array_ModelChangeStructureDataType, + &ett_opcua_SemanticChangeStructureDataType, + &ett_opcua_array_SemanticChangeStructureDataType, + &ett_opcua_Range, + &ett_opcua_array_Range, + &ett_opcua_EUInformation, + &ett_opcua_array_EUInformation, + &ett_opcua_ComplexNumberType, + &ett_opcua_array_ComplexNumberType, + &ett_opcua_DoubleComplexNumberType, + &ett_opcua_array_DoubleComplexNumberType, + &ett_opcua_AxisInformation, + &ett_opcua_array_AxisInformation, + &ett_opcua_XVType, + &ett_opcua_array_XVType, + &ett_opcua_ProgramDiagnosticDataType, + &ett_opcua_array_ProgramDiagnosticDataType, + &ett_opcua_Annotation, + &ett_opcua_array_Annotation, +}; + +void registerComplexTypes(void) +{ + proto_register_subtree_array(ett, array_length(ett)); +} + diff --git a/plugins/epan/opcua/opcua_complextypeparser.h b/plugins/epan/opcua/opcua_complextypeparser.h new file mode 100644 index 00000000..48ef060f --- /dev/null +++ b/plugins/epan/opcua/opcua_complextypeparser.h @@ -0,0 +1,445 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Complex Type Parser +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** XXX - well, except that you may have to. See the README. +** +******************************************************************************/ + +#include +#include + +extern gint ett_opcua_TrustListDataType; +extern gint ett_opcua_array_TrustListDataType; +extern gint ett_opcua_Node; +extern gint ett_opcua_array_Node; +extern gint ett_opcua_InstanceNode; +extern gint ett_opcua_array_InstanceNode; +extern gint ett_opcua_TypeNode; +extern gint ett_opcua_array_TypeNode; +extern gint ett_opcua_ObjectNode; +extern gint ett_opcua_array_ObjectNode; +extern gint ett_opcua_ObjectTypeNode; +extern gint ett_opcua_array_ObjectTypeNode; +extern gint ett_opcua_VariableNode; +extern gint ett_opcua_array_VariableNode; +extern gint ett_opcua_VariableTypeNode; +extern gint ett_opcua_array_VariableTypeNode; +extern gint ett_opcua_ReferenceTypeNode; +extern gint ett_opcua_array_ReferenceTypeNode; +extern gint ett_opcua_MethodNode; +extern gint ett_opcua_array_MethodNode; +extern gint ett_opcua_ViewNode; +extern gint ett_opcua_array_ViewNode; +extern gint ett_opcua_DataTypeNode; +extern gint ett_opcua_array_DataTypeNode; +extern gint ett_opcua_ReferenceNode; +extern gint ett_opcua_array_ReferenceNode; +extern gint ett_opcua_Argument; +extern gint ett_opcua_array_Argument; +extern gint ett_opcua_EnumValueType; +extern gint ett_opcua_array_EnumValueType; +extern gint ett_opcua_OptionSet; +extern gint ett_opcua_array_OptionSet; +extern gint ett_opcua_TimeZoneDataType; +extern gint ett_opcua_array_TimeZoneDataType; +extern gint ett_opcua_ApplicationDescription; +extern gint ett_opcua_array_ApplicationDescription; +extern gint ett_opcua_RequestHeader; +extern gint ett_opcua_array_RequestHeader; +extern gint ett_opcua_ResponseHeader; +extern gint ett_opcua_array_ResponseHeader; +extern gint ett_opcua_ServerOnNetwork; +extern gint ett_opcua_array_ServerOnNetwork; +extern gint ett_opcua_UserTokenPolicy; +extern gint ett_opcua_array_UserTokenPolicy; +extern gint ett_opcua_EndpointDescription; +extern gint ett_opcua_array_EndpointDescription; +extern gint ett_opcua_RegisteredServer; +extern gint ett_opcua_array_RegisteredServer; +extern gint ett_opcua_MdnsDiscoveryConfiguration; +extern gint ett_opcua_array_MdnsDiscoveryConfiguration; +extern gint ett_opcua_ChannelSecurityToken; +extern gint ett_opcua_array_ChannelSecurityToken; +extern gint ett_opcua_SignedSoftwareCertificate; +extern gint ett_opcua_array_SignedSoftwareCertificate; +extern gint ett_opcua_SignatureData; +extern gint ett_opcua_array_SignatureData; +extern gint ett_opcua_UserIdentityToken; +extern gint ett_opcua_array_UserIdentityToken; +extern gint ett_opcua_AnonymousIdentityToken; +extern gint ett_opcua_array_AnonymousIdentityToken; +extern gint ett_opcua_UserNameIdentityToken; +extern gint ett_opcua_array_UserNameIdentityToken; +extern gint ett_opcua_X509IdentityToken; +extern gint ett_opcua_array_X509IdentityToken; +extern gint ett_opcua_KerberosIdentityToken; +extern gint ett_opcua_array_KerberosIdentityToken; +extern gint ett_opcua_IssuedIdentityToken; +extern gint ett_opcua_array_IssuedIdentityToken; +extern gint ett_opcua_NodeAttributes; +extern gint ett_opcua_array_NodeAttributes; +extern gint ett_opcua_ObjectAttributes; +extern gint ett_opcua_array_ObjectAttributes; +extern gint ett_opcua_VariableAttributes; +extern gint ett_opcua_array_VariableAttributes; +extern gint ett_opcua_MethodAttributes; +extern gint ett_opcua_array_MethodAttributes; +extern gint ett_opcua_ObjectTypeAttributes; +extern gint ett_opcua_array_ObjectTypeAttributes; +extern gint ett_opcua_VariableTypeAttributes; +extern gint ett_opcua_array_VariableTypeAttributes; +extern gint ett_opcua_ReferenceTypeAttributes; +extern gint ett_opcua_array_ReferenceTypeAttributes; +extern gint ett_opcua_DataTypeAttributes; +extern gint ett_opcua_array_DataTypeAttributes; +extern gint ett_opcua_ViewAttributes; +extern gint ett_opcua_array_ViewAttributes; +extern gint ett_opcua_AddNodesItem; +extern gint ett_opcua_array_AddNodesItem; +extern gint ett_opcua_AddNodesResult; +extern gint ett_opcua_array_AddNodesResult; +extern gint ett_opcua_AddReferencesItem; +extern gint ett_opcua_array_AddReferencesItem; +extern gint ett_opcua_DeleteNodesItem; +extern gint ett_opcua_array_DeleteNodesItem; +extern gint ett_opcua_DeleteReferencesItem; +extern gint ett_opcua_array_DeleteReferencesItem; +extern gint ett_opcua_ViewDescription; +extern gint ett_opcua_array_ViewDescription; +extern gint ett_opcua_BrowseDescription; +extern gint ett_opcua_array_BrowseDescription; +extern gint ett_opcua_ReferenceDescription; +extern gint ett_opcua_array_ReferenceDescription; +extern gint ett_opcua_BrowseResult; +extern gint ett_opcua_array_BrowseResult; +extern gint ett_opcua_RelativePathElement; +extern gint ett_opcua_array_RelativePathElement; +extern gint ett_opcua_RelativePath; +extern gint ett_opcua_array_RelativePath; +extern gint ett_opcua_BrowsePath; +extern gint ett_opcua_array_BrowsePath; +extern gint ett_opcua_BrowsePathTarget; +extern gint ett_opcua_array_BrowsePathTarget; +extern gint ett_opcua_BrowsePathResult; +extern gint ett_opcua_array_BrowsePathResult; +extern gint ett_opcua_EndpointConfiguration; +extern gint ett_opcua_array_EndpointConfiguration; +extern gint ett_opcua_SupportedProfile; +extern gint ett_opcua_array_SupportedProfile; +extern gint ett_opcua_SoftwareCertificate; +extern gint ett_opcua_array_SoftwareCertificate; +extern gint ett_opcua_QueryDataDescription; +extern gint ett_opcua_array_QueryDataDescription; +extern gint ett_opcua_NodeTypeDescription; +extern gint ett_opcua_array_NodeTypeDescription; +extern gint ett_opcua_QueryDataSet; +extern gint ett_opcua_array_QueryDataSet; +extern gint ett_opcua_NodeReference; +extern gint ett_opcua_array_NodeReference; +extern gint ett_opcua_ContentFilterElement; +extern gint ett_opcua_array_ContentFilterElement; +extern gint ett_opcua_ContentFilter; +extern gint ett_opcua_array_ContentFilter; +extern gint ett_opcua_ElementOperand; +extern gint ett_opcua_array_ElementOperand; +extern gint ett_opcua_LiteralOperand; +extern gint ett_opcua_array_LiteralOperand; +extern gint ett_opcua_AttributeOperand; +extern gint ett_opcua_array_AttributeOperand; +extern gint ett_opcua_SimpleAttributeOperand; +extern gint ett_opcua_array_SimpleAttributeOperand; +extern gint ett_opcua_ContentFilterElementResult; +extern gint ett_opcua_array_ContentFilterElementResult; +extern gint ett_opcua_ContentFilterResult; +extern gint ett_opcua_array_ContentFilterResult; +extern gint ett_opcua_ParsingResult; +extern gint ett_opcua_array_ParsingResult; +extern gint ett_opcua_ReadValueId; +extern gint ett_opcua_array_ReadValueId; +extern gint ett_opcua_HistoryReadValueId; +extern gint ett_opcua_array_HistoryReadValueId; +extern gint ett_opcua_HistoryReadResult; +extern gint ett_opcua_array_HistoryReadResult; +extern gint ett_opcua_ReadEventDetails; +extern gint ett_opcua_array_ReadEventDetails; +extern gint ett_opcua_ReadRawModifiedDetails; +extern gint ett_opcua_array_ReadRawModifiedDetails; +extern gint ett_opcua_ReadProcessedDetails; +extern gint ett_opcua_array_ReadProcessedDetails; +extern gint ett_opcua_ReadAtTimeDetails; +extern gint ett_opcua_array_ReadAtTimeDetails; +extern gint ett_opcua_HistoryData; +extern gint ett_opcua_array_HistoryData; +extern gint ett_opcua_ModificationInfo; +extern gint ett_opcua_array_ModificationInfo; +extern gint ett_opcua_HistoryModifiedData; +extern gint ett_opcua_array_HistoryModifiedData; +extern gint ett_opcua_HistoryEvent; +extern gint ett_opcua_array_HistoryEvent; +extern gint ett_opcua_WriteValue; +extern gint ett_opcua_array_WriteValue; +extern gint ett_opcua_HistoryUpdateDetails; +extern gint ett_opcua_array_HistoryUpdateDetails; +extern gint ett_opcua_UpdateDataDetails; +extern gint ett_opcua_array_UpdateDataDetails; +extern gint ett_opcua_UpdateStructureDataDetails; +extern gint ett_opcua_array_UpdateStructureDataDetails; +extern gint ett_opcua_UpdateEventDetails; +extern gint ett_opcua_array_UpdateEventDetails; +extern gint ett_opcua_DeleteRawModifiedDetails; +extern gint ett_opcua_array_DeleteRawModifiedDetails; +extern gint ett_opcua_DeleteAtTimeDetails; +extern gint ett_opcua_array_DeleteAtTimeDetails; +extern gint ett_opcua_DeleteEventDetails; +extern gint ett_opcua_array_DeleteEventDetails; +extern gint ett_opcua_HistoryUpdateResult; +extern gint ett_opcua_array_HistoryUpdateResult; +extern gint ett_opcua_CallMethodRequest; +extern gint ett_opcua_array_CallMethodRequest; +extern gint ett_opcua_CallMethodResult; +extern gint ett_opcua_array_CallMethodResult; +extern gint ett_opcua_DataChangeFilter; +extern gint ett_opcua_array_DataChangeFilter; +extern gint ett_opcua_EventFilter; +extern gint ett_opcua_array_EventFilter; +extern gint ett_opcua_AggregateConfiguration; +extern gint ett_opcua_array_AggregateConfiguration; +extern gint ett_opcua_AggregateFilter; +extern gint ett_opcua_array_AggregateFilter; +extern gint ett_opcua_EventFilterResult; +extern gint ett_opcua_array_EventFilterResult; +extern gint ett_opcua_AggregateFilterResult; +extern gint ett_opcua_array_AggregateFilterResult; +extern gint ett_opcua_MonitoringParameters; +extern gint ett_opcua_array_MonitoringParameters; +extern gint ett_opcua_MonitoredItemCreateRequest; +extern gint ett_opcua_array_MonitoredItemCreateRequest; +extern gint ett_opcua_MonitoredItemCreateResult; +extern gint ett_opcua_array_MonitoredItemCreateResult; +extern gint ett_opcua_MonitoredItemModifyRequest; +extern gint ett_opcua_array_MonitoredItemModifyRequest; +extern gint ett_opcua_MonitoredItemModifyResult; +extern gint ett_opcua_array_MonitoredItemModifyResult; +extern gint ett_opcua_NotificationMessage; +extern gint ett_opcua_array_NotificationMessage; +extern gint ett_opcua_DataChangeNotification; +extern gint ett_opcua_array_DataChangeNotification; +extern gint ett_opcua_MonitoredItemNotification; +extern gint ett_opcua_array_MonitoredItemNotification; +extern gint ett_opcua_EventNotificationList; +extern gint ett_opcua_array_EventNotificationList; +extern gint ett_opcua_EventFieldList; +extern gint ett_opcua_array_EventFieldList; +extern gint ett_opcua_HistoryEventFieldList; +extern gint ett_opcua_array_HistoryEventFieldList; +extern gint ett_opcua_StatusChangeNotification; +extern gint ett_opcua_array_StatusChangeNotification; +extern gint ett_opcua_SubscriptionAcknowledgement; +extern gint ett_opcua_array_SubscriptionAcknowledgement; +extern gint ett_opcua_TransferResult; +extern gint ett_opcua_array_TransferResult; +extern gint ett_opcua_ScalarTestType; +extern gint ett_opcua_array_ScalarTestType; +extern gint ett_opcua_ArrayTestType; +extern gint ett_opcua_array_ArrayTestType; +extern gint ett_opcua_CompositeTestType; +extern gint ett_opcua_array_CompositeTestType; +extern gint ett_opcua_BuildInfo; +extern gint ett_opcua_array_BuildInfo; +extern gint ett_opcua_RedundantServerDataType; +extern gint ett_opcua_array_RedundantServerDataType; +extern gint ett_opcua_EndpointUrlListDataType; +extern gint ett_opcua_array_EndpointUrlListDataType; +extern gint ett_opcua_NetworkGroupDataType; +extern gint ett_opcua_array_NetworkGroupDataType; +extern gint ett_opcua_SamplingIntervalDiagnosticsDataType; +extern gint ett_opcua_array_SamplingIntervalDiagnosticsDataType; +extern gint ett_opcua_ServerDiagnosticsSummaryDataType; +extern gint ett_opcua_array_ServerDiagnosticsSummaryDataType; +extern gint ett_opcua_ServerStatusDataType; +extern gint ett_opcua_array_ServerStatusDataType; +extern gint ett_opcua_SessionDiagnosticsDataType; +extern gint ett_opcua_array_SessionDiagnosticsDataType; +extern gint ett_opcua_SessionSecurityDiagnosticsDataType; +extern gint ett_opcua_array_SessionSecurityDiagnosticsDataType; +extern gint ett_opcua_ServiceCounterDataType; +extern gint ett_opcua_array_ServiceCounterDataType; +extern gint ett_opcua_StatusResult; +extern gint ett_opcua_array_StatusResult; +extern gint ett_opcua_SubscriptionDiagnosticsDataType; +extern gint ett_opcua_array_SubscriptionDiagnosticsDataType; +extern gint ett_opcua_ModelChangeStructureDataType; +extern gint ett_opcua_array_ModelChangeStructureDataType; +extern gint ett_opcua_SemanticChangeStructureDataType; +extern gint ett_opcua_array_SemanticChangeStructureDataType; +extern gint ett_opcua_Range; +extern gint ett_opcua_array_Range; +extern gint ett_opcua_EUInformation; +extern gint ett_opcua_array_EUInformation; +extern gint ett_opcua_ComplexNumberType; +extern gint ett_opcua_array_ComplexNumberType; +extern gint ett_opcua_DoubleComplexNumberType; +extern gint ett_opcua_array_DoubleComplexNumberType; +extern gint ett_opcua_AxisInformation; +extern gint ett_opcua_array_AxisInformation; +extern gint ett_opcua_XVType; +extern gint ett_opcua_array_XVType; +extern gint ett_opcua_ProgramDiagnosticDataType; +extern gint ett_opcua_array_ProgramDiagnosticDataType; +extern gint ett_opcua_Annotation; +extern gint ett_opcua_array_Annotation; + +void parseTrustListDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseInstanceNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseObjectNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseObjectTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseVariableNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseVariableTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReferenceTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMethodNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseViewNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDataTypeNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReferenceNode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseArgument(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEnumValueType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseOptionSet(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseTimeZoneDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseApplicationDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseRequestHeader(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseResponseHeader(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseServerOnNetwork(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseUserTokenPolicy(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEndpointDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseRegisteredServer(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMdnsDiscoveryConfiguration(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseChannelSecurityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSignedSoftwareCertificate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSignatureData(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseUserIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAnonymousIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseUserNameIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseX509IdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseKerberosIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseIssuedIdentityToken(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseNodeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseObjectAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseVariableAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMethodAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseObjectTypeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseVariableTypeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReferenceTypeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDataTypeAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseViewAttributes(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAddNodesItem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAddNodesResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAddReferencesItem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDeleteNodesItem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDeleteReferencesItem(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseViewDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseBrowseDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReferenceDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseBrowseResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseRelativePathElement(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseRelativePath(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseBrowsePath(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseBrowsePathTarget(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseBrowsePathResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEndpointConfiguration(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSupportedProfile(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSoftwareCertificate(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseQueryDataDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseNodeTypeDescription(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseQueryDataSet(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseNodeReference(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseContentFilterElement(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseContentFilter(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseElementOperand(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseLiteralOperand(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAttributeOperand(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSimpleAttributeOperand(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseContentFilterElementResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseContentFilterResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseParsingResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReadValueId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseHistoryReadValueId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseHistoryReadResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReadEventDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReadRawModifiedDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReadProcessedDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseReadAtTimeDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseHistoryData(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseModificationInfo(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseHistoryModifiedData(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseHistoryEvent(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseWriteValue(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseHistoryUpdateDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseUpdateDataDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseUpdateStructureDataDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseUpdateEventDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDeleteRawModifiedDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDeleteAtTimeDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDeleteEventDetails(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseHistoryUpdateResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseCallMethodRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseCallMethodResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDataChangeFilter(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEventFilter(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAggregateConfiguration(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAggregateFilter(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEventFilterResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAggregateFilterResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMonitoringParameters(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMonitoredItemCreateRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMonitoredItemCreateResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMonitoredItemModifyRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMonitoredItemModifyResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseNotificationMessage(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDataChangeNotification(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseMonitoredItemNotification(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEventNotificationList(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEventFieldList(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseHistoryEventFieldList(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseStatusChangeNotification(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSubscriptionAcknowledgement(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseTransferResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseScalarTestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseArrayTestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseCompositeTestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseBuildInfo(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseRedundantServerDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEndpointUrlListDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseNetworkGroupDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSamplingIntervalDiagnosticsDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseServerDiagnosticsSummaryDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseServerStatusDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSessionDiagnosticsDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSessionSecurityDiagnosticsDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseServiceCounterDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseStatusResult(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSubscriptionDiagnosticsDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseModelChangeStructureDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseSemanticChangeStructureDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseRange(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseEUInformation(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseComplexNumberType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDoubleComplexNumberType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAxisInformation(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseXVType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseProgramDiagnosticDataType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseAnnotation(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); + +void registerComplexTypes(void); diff --git a/plugins/epan/opcua/opcua_enumparser.c b/plugins/epan/opcua/opcua_enumparser.c new file mode 100644 index 00000000..0a93376e --- /dev/null +++ b/plugins/epan/opcua/opcua_enumparser.c @@ -0,0 +1,675 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Enum Type Parser +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** +******************************************************************************/ + +#include "config.h" + +#include + +#include "opcua_enumparser.h" + +gint ett_opcua_array_NodeIdType = -1; +gint ett_opcua_array_NamingRuleType = -1; +gint ett_opcua_array_OpenFileMode = -1; +gint ett_opcua_array_TrustListMasks = -1; +gint ett_opcua_array_IdType = -1; +gint ett_opcua_array_NodeClass = -1; +gint ett_opcua_array_ApplicationType = -1; +gint ett_opcua_array_MessageSecurityMode = -1; +gint ett_opcua_array_UserTokenType = -1; +gint ett_opcua_array_SecurityTokenRequestType = -1; +gint ett_opcua_array_NodeAttributesMask = -1; +gint ett_opcua_array_AttributeWriteMask = -1; +gint ett_opcua_array_BrowseDirection = -1; +gint ett_opcua_array_BrowseResultMask = -1; +gint ett_opcua_array_ComplianceLevel = -1; +gint ett_opcua_array_FilterOperator = -1; +gint ett_opcua_array_TimestampsToReturn = -1; +gint ett_opcua_array_HistoryUpdateType = -1; +gint ett_opcua_array_PerformUpdateType = -1; +gint ett_opcua_array_MonitoringMode = -1; +gint ett_opcua_array_DataChangeTrigger = -1; +gint ett_opcua_array_DeadbandType = -1; +gint ett_opcua_array_EnumeratedTestType = -1; +gint ett_opcua_array_RedundancySupport = -1; +gint ett_opcua_array_ServerState = -1; +gint ett_opcua_array_ModelChangeStructureVerbMask = -1; +gint ett_opcua_array_AxisScaleEnumeration = -1; +gint ett_opcua_array_ExceptionDeviationFormat = -1; + +/** NodeIdType enum table */ +static const value_string g_NodeIdTypeTable[] = { + { 0, "TwoByte" }, + { 1, "FourByte" }, + { 2, "Numeric" }, + { 3, "String" }, + { 4, "Guid" }, + { 5, "ByteString" }, + { 0, NULL } +}; +static int hf_opcua_NodeIdType = -1; + +void parseNodeIdType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_NodeIdType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** NamingRuleType enum table */ +static const value_string g_NamingRuleTypeTable[] = { + { 1, "Mandatory" }, + { 2, "Optional" }, + { 3, "Constraint" }, + { 0, NULL } +}; +static int hf_opcua_NamingRuleType = -1; + +void parseNamingRuleType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_NamingRuleType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** OpenFileMode enum table */ +static const value_string g_OpenFileModeTable[] = { + { 1, "Read" }, + { 2, "Write" }, + { 4, "EraseExisting" }, + { 8, "Append" }, + { 0, NULL } +}; +static int hf_opcua_OpenFileMode = -1; + +void parseOpenFileMode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_OpenFileMode, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** TrustListMasks enum table */ +static const value_string g_TrustListMasksTable[] = { + { 0, "None" }, + { 1, "TrustedCertificates" }, + { 2, "TrustedCrls" }, + { 4, "IssuerCertificates" }, + { 8, "IssuerCrls" }, + { 15, "All" }, + { 0, NULL } +}; +static int hf_opcua_TrustListMasks = -1; + +void parseTrustListMasks(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_TrustListMasks, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** IdType enum table */ +static const value_string g_IdTypeTable[] = { + { 0, "Numeric" }, + { 1, "String" }, + { 2, "Guid" }, + { 3, "Opaque" }, + { 0, NULL } +}; +static int hf_opcua_IdType = -1; + +void parseIdType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_IdType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** NodeClass enum table */ +static const value_string g_NodeClassTable[] = { + { 0, "Unspecified" }, + { 1, "Object" }, + { 2, "Variable" }, + { 4, "Method" }, + { 8, "ObjectType" }, + { 16, "VariableType" }, + { 32, "ReferenceType" }, + { 64, "DataType" }, + { 128, "View" }, + { 0, NULL } +}; +static int hf_opcua_NodeClass = -1; + +void parseNodeClass(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_NodeClass, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** ApplicationType enum table */ +static const value_string g_ApplicationTypeTable[] = { + { 0, "Server" }, + { 1, "Client" }, + { 2, "ClientAndServer" }, + { 3, "DiscoveryServer" }, + { 0, NULL } +}; +static int hf_opcua_ApplicationType = -1; + +void parseApplicationType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_ApplicationType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** MessageSecurityMode enum table */ +static const value_string g_MessageSecurityModeTable[] = { + { 0, "Invalid" }, + { 1, "None" }, + { 2, "Sign" }, + { 3, "SignAndEncrypt" }, + { 0, NULL } +}; +static int hf_opcua_MessageSecurityMode = -1; + +void parseMessageSecurityMode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_MessageSecurityMode, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** UserTokenType enum table */ +static const value_string g_UserTokenTypeTable[] = { + { 0, "Anonymous" }, + { 1, "UserName" }, + { 2, "Certificate" }, + { 3, "IssuedToken" }, + { 4, "Kerberos" }, + { 0, NULL } +}; +static int hf_opcua_UserTokenType = -1; + +void parseUserTokenType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_UserTokenType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** SecurityTokenRequestType enum table */ +static const value_string g_SecurityTokenRequestTypeTable[] = { + { 0, "Issue" }, + { 1, "Renew" }, + { 0, NULL } +}; +static int hf_opcua_SecurityTokenRequestType = -1; + +void parseSecurityTokenRequestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_SecurityTokenRequestType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** NodeAttributesMask enum table */ +static const value_string g_NodeAttributesMaskTable[] = { + { 0, "None" }, + { 1, "AccessLevel" }, + { 2, "ArrayDimensions" }, + { 4, "BrowseName" }, + { 8, "ContainsNoLoops" }, + { 16, "DataType" }, + { 32, "Description" }, + { 64, "DisplayName" }, + { 128, "EventNotifier" }, + { 256, "Executable" }, + { 512, "Historizing" }, + { 1024, "InverseName" }, + { 2048, "IsAbstract" }, + { 4096, "MinimumSamplingInterval" }, + { 8192, "NodeClass" }, + { 16384, "NodeId" }, + { 32768, "Symmetric" }, + { 65536, "UserAccessLevel" }, + { 131072, "UserExecutable" }, + { 262144, "UserWriteMask" }, + { 524288, "ValueRank" }, + { 1048576, "WriteMask" }, + { 2097152, "Value" }, + { 4194303, "All" }, + { 1335396, "BaseNode" }, + { 1335524, "Object" }, + { 1337444, "ObjectTypeOrDataType" }, + { 4026999, "Variable" }, + { 3958902, "VariableType" }, + { 1466724, "Method" }, + { 1371236, "ReferenceType" }, + { 1335532, "View" }, + { 0, NULL } +}; +static int hf_opcua_NodeAttributesMask = -1; + +void parseNodeAttributesMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_NodeAttributesMask, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** AttributeWriteMask enum table */ +static const value_string g_AttributeWriteMaskTable[] = { + { 0, "None" }, + { 1, "AccessLevel" }, + { 2, "ArrayDimensions" }, + { 4, "BrowseName" }, + { 8, "ContainsNoLoops" }, + { 16, "DataType" }, + { 32, "Description" }, + { 64, "DisplayName" }, + { 128, "EventNotifier" }, + { 256, "Executable" }, + { 512, "Historizing" }, + { 1024, "InverseName" }, + { 2048, "IsAbstract" }, + { 4096, "MinimumSamplingInterval" }, + { 8192, "NodeClass" }, + { 16384, "NodeId" }, + { 32768, "Symmetric" }, + { 65536, "UserAccessLevel" }, + { 131072, "UserExecutable" }, + { 262144, "UserWriteMask" }, + { 524288, "ValueRank" }, + { 1048576, "WriteMask" }, + { 2097152, "ValueForVariableType" }, + { 4194304, "DataTypeDefinition" }, + { 8388608, "RolePermissions" }, + { 16777216, "AccessRestrictions" }, + { 33554432, "AccessLevelEx" }, + { 0, NULL } +}; +static int hf_opcua_AttributeWriteMask = -1; + +void parseAttributeWriteMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_AttributeWriteMask, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** BrowseDirection enum table */ +static const value_string g_BrowseDirectionTable[] = { + { 0, "Forward" }, + { 1, "Inverse" }, + { 2, "Both" }, + { 3, "Invalid" }, + { 0, NULL } +}; +static int hf_opcua_BrowseDirection = -1; + +void parseBrowseDirection(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_BrowseDirection, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} + +/** ComplianceLevel enum table */ +static const value_string g_ComplianceLevelTable[] = { + { 0, "Untested" }, + { 1, "Partial" }, + { 2, "SelfTested" }, + { 3, "Certified" }, + { 0, NULL } +}; +static int hf_opcua_ComplianceLevel = -1; + +void parseComplianceLevel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_ComplianceLevel, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** FilterOperator enum table */ +static const value_string g_FilterOperatorTable[] = { + { 0, "Equals" }, + { 1, "IsNull" }, + { 2, "GreaterThan" }, + { 3, "LessThan" }, + { 4, "GreaterThanOrEqual" }, + { 5, "LessThanOrEqual" }, + { 6, "Like" }, + { 7, "Not" }, + { 8, "Between" }, + { 9, "InList" }, + { 10, "And" }, + { 11, "Or" }, + { 12, "Cast" }, + { 13, "InView" }, + { 14, "OfType" }, + { 15, "RelatedTo" }, + { 16, "BitwiseAnd" }, + { 17, "BitwiseOr" }, + { 0, NULL } +}; +static int hf_opcua_FilterOperator = -1; + +void parseFilterOperator(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_FilterOperator, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** TimestampsToReturn enum table */ +static const value_string g_TimestampsToReturnTable[] = { + { 0, "Source" }, + { 1, "Server" }, + { 2, "Both" }, + { 3, "Neither" }, + { 4, "Invalid" }, + { 0, NULL } +}; +static int hf_opcua_TimestampsToReturn = -1; + +void parseTimestampsToReturn(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_TimestampsToReturn, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** HistoryUpdateType enum table */ +static const value_string g_HistoryUpdateTypeTable[] = { + { 1, "Insert" }, + { 2, "Replace" }, + { 3, "Update" }, + { 4, "Delete" }, + { 0, NULL } +}; +static int hf_opcua_HistoryUpdateType = -1; + +void parseHistoryUpdateType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_HistoryUpdateType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** PerformUpdateType enum table */ +static const value_string g_PerformUpdateTypeTable[] = { + { 1, "Insert" }, + { 2, "Replace" }, + { 3, "Update" }, + { 4, "Remove" }, + { 0, NULL } +}; +static int hf_opcua_PerformUpdateType = -1; + +void parsePerformUpdateType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_PerformUpdateType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** MonitoringMode enum table */ +static const value_string g_MonitoringModeTable[] = { + { 0, "Disabled" }, + { 1, "Sampling" }, + { 2, "Reporting" }, + { 0, NULL } +}; +static int hf_opcua_MonitoringMode = -1; + +void parseMonitoringMode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_MonitoringMode, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** DataChangeTrigger enum table */ +static const value_string g_DataChangeTriggerTable[] = { + { 0, "Status" }, + { 1, "StatusValue" }, + { 2, "StatusValueTimestamp" }, + { 0, NULL } +}; +static int hf_opcua_DataChangeTrigger = -1; + +void parseDataChangeTrigger(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_DataChangeTrigger, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** DeadbandType enum table */ +static const value_string g_DeadbandTypeTable[] = { + { 0, "None" }, + { 1, "Absolute" }, + { 2, "Percent" }, + { 0, NULL } +}; +static int hf_opcua_DeadbandType = -1; + +void parseDeadbandType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_DeadbandType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** EnumeratedTestType enum table */ +static const value_string g_EnumeratedTestTypeTable[] = { + { 1, "Red" }, + { 4, "Yellow" }, + { 5, "Green" }, + { 0, NULL } +}; +static int hf_opcua_EnumeratedTestType = -1; + +void parseEnumeratedTestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_EnumeratedTestType, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** RedundancySupport enum table */ +static const value_string g_RedundancySupportTable[] = { + { 0, "None" }, + { 1, "Cold" }, + { 2, "Warm" }, + { 3, "Hot" }, + { 4, "Transparent" }, + { 5, "HotAndMirrored" }, + { 0, NULL } +}; +static int hf_opcua_RedundancySupport = -1; + +void parseRedundancySupport(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_RedundancySupport, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** ServerState enum table */ +static const value_string g_ServerStateTable[] = { + { 0, "Running" }, + { 1, "Failed" }, + { 2, "NoConfiguration" }, + { 3, "Suspended" }, + { 4, "Shutdown" }, + { 5, "Test" }, + { 6, "CommunicationFault" }, + { 7, "Unknown" }, + { 0, NULL } +}; +static int hf_opcua_ServerState = -1; + +void parseServerState(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_ServerState, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** ModelChangeStructureVerbMask enum table */ +static const value_string g_ModelChangeStructureVerbMaskTable[] = { + { 1, "NodeAdded" }, + { 2, "NodeDeleted" }, + { 4, "ReferenceAdded" }, + { 8, "ReferenceDeleted" }, + { 16, "DataTypeChanged" }, + { 0, NULL } +}; +static int hf_opcua_ModelChangeStructureVerbMask = -1; + +void parseModelChangeStructureVerbMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_ModelChangeStructureVerbMask, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** AxisScaleEnumeration enum table */ +static const value_string g_AxisScaleEnumerationTable[] = { + { 0, "Linear" }, + { 1, "Log" }, + { 2, "Ln" }, + { 0, NULL } +}; +static int hf_opcua_AxisScaleEnumeration = -1; + +void parseAxisScaleEnumeration(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_AxisScaleEnumeration, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** ExceptionDeviationFormat enum table */ +static const value_string g_ExceptionDeviationFormatTable[] = { + { 0, "AbsoluteValue" }, + { 1, "PercentOfValue" }, + { 2, "PercentOfRange" }, + { 3, "PercentOfEURange" }, + { 4, "Unknown" }, + { 0, NULL } +}; +static int hf_opcua_ExceptionDeviationFormat = -1; + +void parseExceptionDeviationFormat(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_ExceptionDeviationFormat, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} +/** AttributeId enum table */ +static const value_string g_AttributeIdTable[] = { + {1, "NodeId"}, + {2, "NodeClass"}, + {3, "BrowseName"}, + {4, "DisplayName"}, + {5, "Description"}, + {6, "WriteMask"}, + {7, "UserWriteMask"}, + {8, "IsAbstract"}, + {9, "Symmetric"}, + {10, "InverseName"}, + {11, "ContainsNoLoops"}, + {12, "EventNotifier"}, + {13, "Value"}, + {14, "DataType"}, + {15, "ValueRank"}, + {16, "ArrayDimensions"}, + {17, "AccessLevel"}, + {18, "UserAccessLevel"}, + {19, "MinimumSamplingInterval"}, + {20, "Historizing"}, + {21, "Executable"}, + {22, "UserExecutable"}, + {23, "DataTypeDefinition"}, + {24, "RolePermissions"}, + {25, "UserRolePermissions"}, + {26, "AccessRestrictions"}, + {27, "AccessLevelEx"}, + {0, NULL} +}; +static int hf_opcua_AttributeId = -1; + +void parseAttributeId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_AttributeId, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset += 4; +} + +/** Setup enum subtree array */ +static gint *ett[] = +{ + &ett_opcua_array_NodeIdType, + &ett_opcua_array_NamingRuleType, + &ett_opcua_array_OpenFileMode, + &ett_opcua_array_TrustListMasks, + &ett_opcua_array_IdType, + &ett_opcua_array_NodeClass, + &ett_opcua_array_ApplicationType, + &ett_opcua_array_MessageSecurityMode, + &ett_opcua_array_UserTokenType, + &ett_opcua_array_SecurityTokenRequestType, + &ett_opcua_array_NodeAttributesMask, + &ett_opcua_array_AttributeWriteMask, + &ett_opcua_array_BrowseDirection, + &ett_opcua_array_BrowseResultMask, + &ett_opcua_array_ComplianceLevel, + &ett_opcua_array_FilterOperator, + &ett_opcua_array_TimestampsToReturn, + &ett_opcua_array_HistoryUpdateType, + &ett_opcua_array_PerformUpdateType, + &ett_opcua_array_MonitoringMode, + &ett_opcua_array_DataChangeTrigger, + &ett_opcua_array_DeadbandType, + &ett_opcua_array_EnumeratedTestType, + &ett_opcua_array_RedundancySupport, + &ett_opcua_array_ServerState, + &ett_opcua_array_ModelChangeStructureVerbMask, + &ett_opcua_array_AxisScaleEnumeration, + &ett_opcua_array_ExceptionDeviationFormat, +}; + +/** Register enum types. */ +void registerEnumTypes(int proto) +{ + /** header field definitions */ + static hf_register_info hf[] = + { + { &hf_opcua_NodeIdType, + { "NodeIdType", "opcua.NodeIdType", FT_UINT32, BASE_HEX, VALS(g_NodeIdTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_NamingRuleType, + { "NamingRuleType", "opcua.NamingRuleType", FT_UINT32, BASE_HEX, VALS(g_NamingRuleTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_OpenFileMode, + { "OpenFileMode", "opcua.OpenFileMode", FT_UINT32, BASE_HEX, VALS(g_OpenFileModeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_TrustListMasks, + { "TrustListMasks", "opcua.TrustListMasks", FT_UINT32, BASE_HEX, VALS(g_TrustListMasksTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_IdType, + { "IdType", "opcua.IdType", FT_UINT32, BASE_HEX, VALS(g_IdTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_NodeClass, + { "NodeClass", "opcua.NodeClass", FT_UINT32, BASE_HEX, VALS(g_NodeClassTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_ApplicationType, + { "ApplicationType", "opcua.ApplicationType", FT_UINT32, BASE_HEX, VALS(g_ApplicationTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_MessageSecurityMode, + { "MessageSecurityMode", "opcua.MessageSecurityMode", FT_UINT32, BASE_HEX, VALS(g_MessageSecurityModeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_UserTokenType, + { "UserTokenType", "opcua.UserTokenType", FT_UINT32, BASE_HEX, VALS(g_UserTokenTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_SecurityTokenRequestType, + { "SecurityTokenRequestType", "opcua.SecurityTokenRequestType", FT_UINT32, BASE_HEX, VALS(g_SecurityTokenRequestTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_NodeAttributesMask, + { "NodeAttributesMask", "opcua.NodeAttributesMask", FT_UINT32, BASE_HEX, VALS(g_NodeAttributesMaskTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_AttributeWriteMask, + { "AttributeWriteMask", "opcua.AttributeWriteMask", FT_UINT32, BASE_HEX, VALS(g_AttributeWriteMaskTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_BrowseDirection, + { "BrowseDirection", "opcua.BrowseDirection", FT_UINT32, BASE_HEX, VALS(g_BrowseDirectionTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_ComplianceLevel, + { "ComplianceLevel", "opcua.ComplianceLevel", FT_UINT32, BASE_HEX, VALS(g_ComplianceLevelTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_FilterOperator, + { "FilterOperator", "opcua.FilterOperator", FT_UINT32, BASE_HEX, VALS(g_FilterOperatorTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_TimestampsToReturn, + { "TimestampsToReturn", "opcua.TimestampsToReturn", FT_UINT32, BASE_HEX, VALS(g_TimestampsToReturnTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_HistoryUpdateType, + { "HistoryUpdateType", "opcua.HistoryUpdateType", FT_UINT32, BASE_HEX, VALS(g_HistoryUpdateTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_PerformUpdateType, + { "PerformUpdateType", "opcua.PerformUpdateType", FT_UINT32, BASE_HEX, VALS(g_PerformUpdateTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_MonitoringMode, + { "MonitoringMode", "opcua.MonitoringMode", FT_UINT32, BASE_HEX, VALS(g_MonitoringModeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_DataChangeTrigger, + { "DataChangeTrigger", "opcua.DataChangeTrigger", FT_UINT32, BASE_HEX, VALS(g_DataChangeTriggerTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_DeadbandType, + { "DeadbandType", "opcua.DeadbandType", FT_UINT32, BASE_HEX, VALS(g_DeadbandTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_EnumeratedTestType, + { "EnumeratedTestType", "opcua.EnumeratedTestType", FT_UINT32, BASE_HEX, VALS(g_EnumeratedTestTypeTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_RedundancySupport, + { "RedundancySupport", "opcua.RedundancySupport", FT_UINT32, BASE_HEX, VALS(g_RedundancySupportTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_ServerState, + { "ServerState", "opcua.ServerState", FT_UINT32, BASE_HEX, VALS(g_ServerStateTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_ModelChangeStructureVerbMask, + { "ModelChangeStructureVerbMask", "opcua.ModelChangeStructureVerbMask", FT_UINT32, BASE_HEX, VALS(g_ModelChangeStructureVerbMaskTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_AxisScaleEnumeration, + { "AxisScaleEnumeration", "opcua.AxisScaleEnumeration", FT_UINT32, BASE_HEX, VALS(g_AxisScaleEnumerationTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_ExceptionDeviationFormat, + { "ExceptionDeviationFormat", "opcua.ExceptionDeviationFormat", FT_UINT32, BASE_HEX, VALS(g_ExceptionDeviationFormatTable), 0x0, NULL, HFILL } + }, + { &hf_opcua_AttributeId, + { "AttributeId", "opcua.AttributeId", FT_UINT32, BASE_HEX, VALS(g_AttributeIdTable), 0x0, NULL, HFILL } + }, + }; + + proto_register_field_array(proto, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + diff --git a/plugins/epan/opcua/opcua_enumparser.h b/plugins/epan/opcua/opcua_enumparser.h new file mode 100644 index 00000000..c52aa9a3 --- /dev/null +++ b/plugins/epan/opcua/opcua_enumparser.h @@ -0,0 +1,81 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Enum Type Parser +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** XXX - well, except that you may have to. See the README. +** +******************************************************************************/ + +#include +#include + +extern gint ett_opcua_array_NodeIdType; +extern gint ett_opcua_array_NamingRuleType; +extern gint ett_opcua_array_OpenFileMode; +extern gint ett_opcua_array_TrustListMasks; +extern gint ett_opcua_array_IdType; +extern gint ett_opcua_array_NodeClass; +extern gint ett_opcua_array_ApplicationType; +extern gint ett_opcua_array_MessageSecurityMode; +extern gint ett_opcua_array_UserTokenType; +extern gint ett_opcua_array_SecurityTokenRequestType; +extern gint ett_opcua_array_NodeAttributesMask; +extern gint ett_opcua_array_AttributeWriteMask; +extern gint ett_opcua_array_BrowseDirection; +extern gint ett_opcua_array_BrowseResultMask; +extern gint ett_opcua_array_ComplianceLevel; +extern gint ett_opcua_array_FilterOperator; +extern gint ett_opcua_array_TimestampsToReturn; +extern gint ett_opcua_array_HistoryUpdateType; +extern gint ett_opcua_array_PerformUpdateType; +extern gint ett_opcua_array_MonitoringMode; +extern gint ett_opcua_array_DataChangeTrigger; +extern gint ett_opcua_array_DeadbandType; +extern gint ett_opcua_array_EnumeratedTestType; +extern gint ett_opcua_array_RedundancySupport; +extern gint ett_opcua_array_ServerState; +extern gint ett_opcua_array_ModelChangeStructureVerbMask; +extern gint ett_opcua_array_AxisScaleEnumeration; +extern gint ett_opcua_array_ExceptionDeviationFormat; +extern gint ett_opcua_array_AttributeId; + +void parseNodeIdType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseNamingRuleType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseOpenFileMode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTrustListMasks(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseIdType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseNodeClass(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseApplicationType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseMessageSecurityMode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseUserTokenType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseSecurityTokenRequestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseNodeAttributesMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseAttributeWriteMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseBrowseDirection(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseComplianceLevel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseFilterOperator(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTimestampsToReturn(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseHistoryUpdateType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parsePerformUpdateType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseMonitoringMode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDataChangeTrigger(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeadbandType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseEnumeratedTestType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRedundancySupport(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseServerState(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseModelChangeStructureVerbMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseAxisScaleEnumeration(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseExceptionDeviationFormat(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseAttributeId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void registerEnumTypes(int proto); diff --git a/plugins/epan/opcua/opcua_extensionobjectids.h b/plugins/epan/opcua/opcua_extensionobjectids.h new file mode 100644 index 00000000..321a74df --- /dev/null +++ b/plugins/epan/opcua/opcua_extensionobjectids.h @@ -0,0 +1,159 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Extension Object IDs +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** +******************************************************************************/ + +#define OpcUaId_TrustListDataType_Encoding_DefaultBinary 12680 +#define OpcUaId_Node_Encoding_DefaultBinary 260 +#define OpcUaId_InstanceNode_Encoding_DefaultBinary 11889 +#define OpcUaId_TypeNode_Encoding_DefaultBinary 11890 +#define OpcUaId_ObjectNode_Encoding_DefaultBinary 263 +#define OpcUaId_ObjectTypeNode_Encoding_DefaultBinary 266 +#define OpcUaId_VariableNode_Encoding_DefaultBinary 269 +#define OpcUaId_VariableTypeNode_Encoding_DefaultBinary 272 +#define OpcUaId_ReferenceTypeNode_Encoding_DefaultBinary 275 +#define OpcUaId_MethodNode_Encoding_DefaultBinary 278 +#define OpcUaId_ViewNode_Encoding_DefaultBinary 281 +#define OpcUaId_DataTypeNode_Encoding_DefaultBinary 284 +#define OpcUaId_ReferenceNode_Encoding_DefaultBinary 287 +#define OpcUaId_Argument_Encoding_DefaultBinary 298 +#define OpcUaId_EnumValueType_Encoding_DefaultBinary 8251 +#define OpcUaId_OptionSet_Encoding_DefaultBinary 12765 +#define OpcUaId_TimeZoneDataType_Encoding_DefaultBinary 8917 +#define OpcUaId_ApplicationDescription_Encoding_DefaultBinary 310 +#define OpcUaId_RequestHeader_Encoding_DefaultBinary 391 +#define OpcUaId_ResponseHeader_Encoding_DefaultBinary 394 +#define OpcUaId_ServerOnNetwork_Encoding_DefaultBinary 12207 +#define OpcUaId_UserTokenPolicy_Encoding_DefaultBinary 306 +#define OpcUaId_EndpointDescription_Encoding_DefaultBinary 314 +#define OpcUaId_RegisteredServer_Encoding_DefaultBinary 434 +#define OpcUaId_MdnsDiscoveryConfiguration_Encoding_DefaultBinary 12901 +#define OpcUaId_ChannelSecurityToken_Encoding_DefaultBinary 443 +#define OpcUaId_SignedSoftwareCertificate_Encoding_DefaultBinary 346 +#define OpcUaId_SignatureData_Encoding_DefaultBinary 458 +#define OpcUaId_UserIdentityToken_Encoding_DefaultBinary 318 +#define OpcUaId_AnonymousIdentityToken_Encoding_DefaultBinary 321 +#define OpcUaId_UserNameIdentityToken_Encoding_DefaultBinary 324 +#define OpcUaId_X509IdentityToken_Encoding_DefaultBinary 327 +#define OpcUaId_KerberosIdentityToken_Encoding_DefaultBinary 12509 +#define OpcUaId_IssuedIdentityToken_Encoding_DefaultBinary 940 +#define OpcUaId_NodeAttributes_Encoding_DefaultBinary 351 +#define OpcUaId_ObjectAttributes_Encoding_DefaultBinary 354 +#define OpcUaId_VariableAttributes_Encoding_DefaultBinary 357 +#define OpcUaId_MethodAttributes_Encoding_DefaultBinary 360 +#define OpcUaId_ObjectTypeAttributes_Encoding_DefaultBinary 363 +#define OpcUaId_VariableTypeAttributes_Encoding_DefaultBinary 366 +#define OpcUaId_ReferenceTypeAttributes_Encoding_DefaultBinary 369 +#define OpcUaId_DataTypeAttributes_Encoding_DefaultBinary 372 +#define OpcUaId_ViewAttributes_Encoding_DefaultBinary 375 +#define OpcUaId_AddNodesItem_Encoding_DefaultBinary 378 +#define OpcUaId_AddNodesResult_Encoding_DefaultBinary 485 +#define OpcUaId_AddReferencesItem_Encoding_DefaultBinary 381 +#define OpcUaId_DeleteNodesItem_Encoding_DefaultBinary 384 +#define OpcUaId_DeleteReferencesItem_Encoding_DefaultBinary 387 +#define OpcUaId_ViewDescription_Encoding_DefaultBinary 513 +#define OpcUaId_BrowseDescription_Encoding_DefaultBinary 516 +#define OpcUaId_ReferenceDescription_Encoding_DefaultBinary 520 +#define OpcUaId_BrowseResult_Encoding_DefaultBinary 524 +#define OpcUaId_RelativePathElement_Encoding_DefaultBinary 539 +#define OpcUaId_RelativePath_Encoding_DefaultBinary 542 +#define OpcUaId_BrowsePath_Encoding_DefaultBinary 545 +#define OpcUaId_BrowsePathTarget_Encoding_DefaultBinary 548 +#define OpcUaId_BrowsePathResult_Encoding_DefaultBinary 551 +#define OpcUaId_EndpointConfiguration_Encoding_DefaultBinary 333 +#define OpcUaId_SupportedProfile_Encoding_DefaultBinary 337 +#define OpcUaId_SoftwareCertificate_Encoding_DefaultBinary 343 +#define OpcUaId_QueryDataDescription_Encoding_DefaultBinary 572 +#define OpcUaId_NodeTypeDescription_Encoding_DefaultBinary 575 +#define OpcUaId_QueryDataSet_Encoding_DefaultBinary 579 +#define OpcUaId_NodeReference_Encoding_DefaultBinary 582 +#define OpcUaId_ContentFilterElement_Encoding_DefaultBinary 585 +#define OpcUaId_ContentFilter_Encoding_DefaultBinary 588 +#define OpcUaId_ElementOperand_Encoding_DefaultBinary 594 +#define OpcUaId_LiteralOperand_Encoding_DefaultBinary 597 +#define OpcUaId_AttributeOperand_Encoding_DefaultBinary 600 +#define OpcUaId_SimpleAttributeOperand_Encoding_DefaultBinary 603 +#define OpcUaId_ContentFilterElementResult_Encoding_DefaultBinary 606 +#define OpcUaId_ContentFilterResult_Encoding_DefaultBinary 609 +#define OpcUaId_ParsingResult_Encoding_DefaultBinary 612 +#define OpcUaId_ReadValueId_Encoding_DefaultBinary 628 +#define OpcUaId_HistoryReadValueId_Encoding_DefaultBinary 637 +#define OpcUaId_HistoryReadResult_Encoding_DefaultBinary 640 +#define OpcUaId_ReadEventDetails_Encoding_DefaultBinary 646 +#define OpcUaId_ReadRawModifiedDetails_Encoding_DefaultBinary 649 +#define OpcUaId_ReadProcessedDetails_Encoding_DefaultBinary 652 +#define OpcUaId_ReadAtTimeDetails_Encoding_DefaultBinary 655 +#define OpcUaId_HistoryData_Encoding_DefaultBinary 658 +#define OpcUaId_ModificationInfo_Encoding_DefaultBinary 11226 +#define OpcUaId_HistoryModifiedData_Encoding_DefaultBinary 11227 +#define OpcUaId_HistoryEvent_Encoding_DefaultBinary 661 +#define OpcUaId_WriteValue_Encoding_DefaultBinary 670 +#define OpcUaId_HistoryUpdateDetails_Encoding_DefaultBinary 679 +#define OpcUaId_UpdateDataDetails_Encoding_DefaultBinary 682 +#define OpcUaId_UpdateStructureDataDetails_Encoding_DefaultBinary 11300 +#define OpcUaId_UpdateEventDetails_Encoding_DefaultBinary 685 +#define OpcUaId_DeleteRawModifiedDetails_Encoding_DefaultBinary 688 +#define OpcUaId_DeleteAtTimeDetails_Encoding_DefaultBinary 691 +#define OpcUaId_DeleteEventDetails_Encoding_DefaultBinary 694 +#define OpcUaId_HistoryUpdateResult_Encoding_DefaultBinary 697 +#define OpcUaId_CallMethodRequest_Encoding_DefaultBinary 706 +#define OpcUaId_CallMethodResult_Encoding_DefaultBinary 709 +#define OpcUaId_DataChangeFilter_Encoding_DefaultBinary 724 +#define OpcUaId_EventFilter_Encoding_DefaultBinary 727 +#define OpcUaId_AggregateConfiguration_Encoding_DefaultBinary 950 +#define OpcUaId_AggregateFilter_Encoding_DefaultBinary 730 +#define OpcUaId_EventFilterResult_Encoding_DefaultBinary 736 +#define OpcUaId_AggregateFilterResult_Encoding_DefaultBinary 739 +#define OpcUaId_MonitoringParameters_Encoding_DefaultBinary 742 +#define OpcUaId_MonitoredItemCreateRequest_Encoding_DefaultBinary 745 +#define OpcUaId_MonitoredItemCreateResult_Encoding_DefaultBinary 748 +#define OpcUaId_MonitoredItemModifyRequest_Encoding_DefaultBinary 757 +#define OpcUaId_MonitoredItemModifyResult_Encoding_DefaultBinary 760 +#define OpcUaId_NotificationMessage_Encoding_DefaultBinary 805 +#define OpcUaId_DataChangeNotification_Encoding_DefaultBinary 811 +#define OpcUaId_MonitoredItemNotification_Encoding_DefaultBinary 808 +#define OpcUaId_EventNotificationList_Encoding_DefaultBinary 916 +#define OpcUaId_EventFieldList_Encoding_DefaultBinary 919 +#define OpcUaId_HistoryEventFieldList_Encoding_DefaultBinary 922 +#define OpcUaId_StatusChangeNotification_Encoding_DefaultBinary 820 +#define OpcUaId_SubscriptionAcknowledgement_Encoding_DefaultBinary 823 +#define OpcUaId_TransferResult_Encoding_DefaultBinary 838 +#define OpcUaId_ScalarTestType_Encoding_DefaultBinary 401 +#define OpcUaId_ArrayTestType_Encoding_DefaultBinary 404 +#define OpcUaId_CompositeTestType_Encoding_DefaultBinary 407 +#define OpcUaId_BuildInfo_Encoding_DefaultBinary 340 +#define OpcUaId_RedundantServerDataType_Encoding_DefaultBinary 855 +#define OpcUaId_EndpointUrlListDataType_Encoding_DefaultBinary 11957 +#define OpcUaId_NetworkGroupDataType_Encoding_DefaultBinary 11958 +#define OpcUaId_SamplingIntervalDiagnosticsDataType_Encoding_DefaultBinary 858 +#define OpcUaId_ServerDiagnosticsSummaryDataType_Encoding_DefaultBinary 861 +#define OpcUaId_ServerStatusDataType_Encoding_DefaultBinary 864 +#define OpcUaId_SessionDiagnosticsDataType_Encoding_DefaultBinary 867 +#define OpcUaId_SessionSecurityDiagnosticsDataType_Encoding_DefaultBinary 870 +#define OpcUaId_ServiceCounterDataType_Encoding_DefaultBinary 873 +#define OpcUaId_StatusResult_Encoding_DefaultBinary 301 +#define OpcUaId_SubscriptionDiagnosticsDataType_Encoding_DefaultBinary 876 +#define OpcUaId_ModelChangeStructureDataType_Encoding_DefaultBinary 879 +#define OpcUaId_SemanticChangeStructureDataType_Encoding_DefaultBinary 899 +#define OpcUaId_Range_Encoding_DefaultBinary 886 +#define OpcUaId_EUInformation_Encoding_DefaultBinary 889 +#define OpcUaId_ComplexNumberType_Encoding_DefaultBinary 12181 +#define OpcUaId_DoubleComplexNumberType_Encoding_DefaultBinary 12182 +#define OpcUaId_AxisInformation_Encoding_DefaultBinary 12089 +#define OpcUaId_XVType_Encoding_DefaultBinary 12090 +#define OpcUaId_ProgramDiagnosticDataType_Encoding_DefaultBinary 896 +#define OpcUaId_Annotation_Encoding_DefaultBinary 893 + diff --git a/plugins/epan/opcua/opcua_extensionobjecttable.c b/plugins/epan/opcua/opcua_extensionobjecttable.c new file mode 100644 index 00000000..2b9ae3c9 --- /dev/null +++ b/plugins/epan/opcua/opcua_extensionobjecttable.c @@ -0,0 +1,215 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: Service table and service dispatcher. +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** XXX - well, except that you may have to. See the README. +** +******************************************************************************/ + +#include "config.h" + +#include +#include "opcua_simpletypes.h" +#include "opcua_complextypeparser.h" +#include "opcua_extensionobjectids.h" +#include "opcua_hfindeces.h" + +ExtensionObjectParserEntry g_arExtensionObjectParserTable[] = { + { OpcUaId_TrustListDataType_Encoding_DefaultBinary, parseTrustListDataType, "TrustListDataType" }, + { OpcUaId_Node_Encoding_DefaultBinary, parseNode, "Node" }, + { OpcUaId_InstanceNode_Encoding_DefaultBinary, parseInstanceNode, "InstanceNode" }, + { OpcUaId_TypeNode_Encoding_DefaultBinary, parseTypeNode, "TypeNode" }, + { OpcUaId_ObjectNode_Encoding_DefaultBinary, parseObjectNode, "ObjectNode" }, + { OpcUaId_ObjectTypeNode_Encoding_DefaultBinary, parseObjectTypeNode, "ObjectTypeNode" }, + { OpcUaId_VariableNode_Encoding_DefaultBinary, parseVariableNode, "VariableNode" }, + { OpcUaId_VariableTypeNode_Encoding_DefaultBinary, parseVariableTypeNode, "VariableTypeNode" }, + { OpcUaId_ReferenceTypeNode_Encoding_DefaultBinary, parseReferenceTypeNode, "ReferenceTypeNode" }, + { OpcUaId_MethodNode_Encoding_DefaultBinary, parseMethodNode, "MethodNode" }, + { OpcUaId_ViewNode_Encoding_DefaultBinary, parseViewNode, "ViewNode" }, + { OpcUaId_DataTypeNode_Encoding_DefaultBinary, parseDataTypeNode, "DataTypeNode" }, + { OpcUaId_ReferenceNode_Encoding_DefaultBinary, parseReferenceNode, "ReferenceNode" }, + { OpcUaId_Argument_Encoding_DefaultBinary, parseArgument, "Argument" }, + { OpcUaId_EnumValueType_Encoding_DefaultBinary, parseEnumValueType, "EnumValueType" }, + { OpcUaId_OptionSet_Encoding_DefaultBinary, parseOptionSet, "OptionSet" }, + { OpcUaId_TimeZoneDataType_Encoding_DefaultBinary, parseTimeZoneDataType, "TimeZoneDataType" }, + { OpcUaId_ApplicationDescription_Encoding_DefaultBinary, parseApplicationDescription, "ApplicationDescription" }, + { OpcUaId_RequestHeader_Encoding_DefaultBinary, parseRequestHeader, "RequestHeader" }, + { OpcUaId_ResponseHeader_Encoding_DefaultBinary, parseResponseHeader, "ResponseHeader" }, + { OpcUaId_ServerOnNetwork_Encoding_DefaultBinary, parseServerOnNetwork, "ServerOnNetwork" }, + { OpcUaId_UserTokenPolicy_Encoding_DefaultBinary, parseUserTokenPolicy, "UserTokenPolicy" }, + { OpcUaId_EndpointDescription_Encoding_DefaultBinary, parseEndpointDescription, "EndpointDescription" }, + { OpcUaId_RegisteredServer_Encoding_DefaultBinary, parseRegisteredServer, "RegisteredServer" }, + { OpcUaId_MdnsDiscoveryConfiguration_Encoding_DefaultBinary, parseMdnsDiscoveryConfiguration, "MdnsDiscoveryConfiguration" }, + { OpcUaId_ChannelSecurityToken_Encoding_DefaultBinary, parseChannelSecurityToken, "ChannelSecurityToken" }, + { OpcUaId_SignedSoftwareCertificate_Encoding_DefaultBinary, parseSignedSoftwareCertificate, "SignedSoftwareCertificate" }, + { OpcUaId_SignatureData_Encoding_DefaultBinary, parseSignatureData, "SignatureData" }, + { OpcUaId_UserIdentityToken_Encoding_DefaultBinary, parseUserIdentityToken, "UserIdentityToken" }, + { OpcUaId_AnonymousIdentityToken_Encoding_DefaultBinary, parseAnonymousIdentityToken, "AnonymousIdentityToken" }, + { OpcUaId_UserNameIdentityToken_Encoding_DefaultBinary, parseUserNameIdentityToken, "UserNameIdentityToken" }, + { OpcUaId_X509IdentityToken_Encoding_DefaultBinary, parseX509IdentityToken, "X509IdentityToken" }, + { OpcUaId_KerberosIdentityToken_Encoding_DefaultBinary, parseKerberosIdentityToken, "KerberosIdentityToken" }, + { OpcUaId_IssuedIdentityToken_Encoding_DefaultBinary, parseIssuedIdentityToken, "IssuedIdentityToken" }, + { OpcUaId_NodeAttributes_Encoding_DefaultBinary, parseNodeAttributes, "NodeAttributes" }, + { OpcUaId_ObjectAttributes_Encoding_DefaultBinary, parseObjectAttributes, "ObjectAttributes" }, + { OpcUaId_VariableAttributes_Encoding_DefaultBinary, parseVariableAttributes, "VariableAttributes" }, + { OpcUaId_MethodAttributes_Encoding_DefaultBinary, parseMethodAttributes, "MethodAttributes" }, + { OpcUaId_ObjectTypeAttributes_Encoding_DefaultBinary, parseObjectTypeAttributes, "ObjectTypeAttributes" }, + { OpcUaId_VariableTypeAttributes_Encoding_DefaultBinary, parseVariableTypeAttributes, "VariableTypeAttributes" }, + { OpcUaId_ReferenceTypeAttributes_Encoding_DefaultBinary, parseReferenceTypeAttributes, "ReferenceTypeAttributes" }, + { OpcUaId_DataTypeAttributes_Encoding_DefaultBinary, parseDataTypeAttributes, "DataTypeAttributes" }, + { OpcUaId_ViewAttributes_Encoding_DefaultBinary, parseViewAttributes, "ViewAttributes" }, + { OpcUaId_AddNodesItem_Encoding_DefaultBinary, parseAddNodesItem, "AddNodesItem" }, + { OpcUaId_AddNodesResult_Encoding_DefaultBinary, parseAddNodesResult, "AddNodesResult" }, + { OpcUaId_AddReferencesItem_Encoding_DefaultBinary, parseAddReferencesItem, "AddReferencesItem" }, + { OpcUaId_DeleteNodesItem_Encoding_DefaultBinary, parseDeleteNodesItem, "DeleteNodesItem" }, + { OpcUaId_DeleteReferencesItem_Encoding_DefaultBinary, parseDeleteReferencesItem, "DeleteReferencesItem" }, + { OpcUaId_ViewDescription_Encoding_DefaultBinary, parseViewDescription, "ViewDescription" }, + { OpcUaId_BrowseDescription_Encoding_DefaultBinary, parseBrowseDescription, "BrowseDescription" }, + { OpcUaId_ReferenceDescription_Encoding_DefaultBinary, parseReferenceDescription, "ReferenceDescription" }, + { OpcUaId_BrowseResult_Encoding_DefaultBinary, parseBrowseResult, "BrowseResult" }, + { OpcUaId_RelativePathElement_Encoding_DefaultBinary, parseRelativePathElement, "RelativePathElement" }, + { OpcUaId_RelativePath_Encoding_DefaultBinary, parseRelativePath, "RelativePath" }, + { OpcUaId_BrowsePath_Encoding_DefaultBinary, parseBrowsePath, "BrowsePath" }, + { OpcUaId_BrowsePathTarget_Encoding_DefaultBinary, parseBrowsePathTarget, "BrowsePathTarget" }, + { OpcUaId_BrowsePathResult_Encoding_DefaultBinary, parseBrowsePathResult, "BrowsePathResult" }, + { OpcUaId_EndpointConfiguration_Encoding_DefaultBinary, parseEndpointConfiguration, "EndpointConfiguration" }, + { OpcUaId_SupportedProfile_Encoding_DefaultBinary, parseSupportedProfile, "SupportedProfile" }, + { OpcUaId_SoftwareCertificate_Encoding_DefaultBinary, parseSoftwareCertificate, "SoftwareCertificate" }, + { OpcUaId_QueryDataDescription_Encoding_DefaultBinary, parseQueryDataDescription, "QueryDataDescription" }, + { OpcUaId_NodeTypeDescription_Encoding_DefaultBinary, parseNodeTypeDescription, "NodeTypeDescription" }, + { OpcUaId_QueryDataSet_Encoding_DefaultBinary, parseQueryDataSet, "QueryDataSet" }, + { OpcUaId_NodeReference_Encoding_DefaultBinary, parseNodeReference, "NodeReference" }, + { OpcUaId_ContentFilterElement_Encoding_DefaultBinary, parseContentFilterElement, "ContentFilterElement" }, + { OpcUaId_ContentFilter_Encoding_DefaultBinary, parseContentFilter, "ContentFilter" }, + { OpcUaId_ElementOperand_Encoding_DefaultBinary, parseElementOperand, "ElementOperand" }, + { OpcUaId_LiteralOperand_Encoding_DefaultBinary, parseLiteralOperand, "LiteralOperand" }, + { OpcUaId_AttributeOperand_Encoding_DefaultBinary, parseAttributeOperand, "AttributeOperand" }, + { OpcUaId_SimpleAttributeOperand_Encoding_DefaultBinary, parseSimpleAttributeOperand, "SimpleAttributeOperand" }, + { OpcUaId_ContentFilterElementResult_Encoding_DefaultBinary, parseContentFilterElementResult, "ContentFilterElementResult" }, + { OpcUaId_ContentFilterResult_Encoding_DefaultBinary, parseContentFilterResult, "ContentFilterResult" }, + { OpcUaId_ParsingResult_Encoding_DefaultBinary, parseParsingResult, "ParsingResult" }, + { OpcUaId_ReadValueId_Encoding_DefaultBinary, parseReadValueId, "ReadValueId" }, + { OpcUaId_HistoryReadValueId_Encoding_DefaultBinary, parseHistoryReadValueId, "HistoryReadValueId" }, + { OpcUaId_HistoryReadResult_Encoding_DefaultBinary, parseHistoryReadResult, "HistoryReadResult" }, + { OpcUaId_ReadEventDetails_Encoding_DefaultBinary, parseReadEventDetails, "ReadEventDetails" }, + { OpcUaId_ReadRawModifiedDetails_Encoding_DefaultBinary, parseReadRawModifiedDetails, "ReadRawModifiedDetails" }, + { OpcUaId_ReadProcessedDetails_Encoding_DefaultBinary, parseReadProcessedDetails, "ReadProcessedDetails" }, + { OpcUaId_ReadAtTimeDetails_Encoding_DefaultBinary, parseReadAtTimeDetails, "ReadAtTimeDetails" }, + { OpcUaId_HistoryData_Encoding_DefaultBinary, parseHistoryData, "HistoryData" }, + { OpcUaId_ModificationInfo_Encoding_DefaultBinary, parseModificationInfo, "ModificationInfo" }, + { OpcUaId_HistoryModifiedData_Encoding_DefaultBinary, parseHistoryModifiedData, "HistoryModifiedData" }, + { OpcUaId_HistoryEvent_Encoding_DefaultBinary, parseHistoryEvent, "HistoryEvent" }, + { OpcUaId_WriteValue_Encoding_DefaultBinary, parseWriteValue, "WriteValue" }, + { OpcUaId_HistoryUpdateDetails_Encoding_DefaultBinary, parseHistoryUpdateDetails, "HistoryUpdateDetails" }, + { OpcUaId_UpdateDataDetails_Encoding_DefaultBinary, parseUpdateDataDetails, "UpdateDataDetails" }, + { OpcUaId_UpdateStructureDataDetails_Encoding_DefaultBinary, parseUpdateStructureDataDetails, "UpdateStructureDataDetails" }, + { OpcUaId_UpdateEventDetails_Encoding_DefaultBinary, parseUpdateEventDetails, "UpdateEventDetails" }, + { OpcUaId_DeleteRawModifiedDetails_Encoding_DefaultBinary, parseDeleteRawModifiedDetails, "DeleteRawModifiedDetails" }, + { OpcUaId_DeleteAtTimeDetails_Encoding_DefaultBinary, parseDeleteAtTimeDetails, "DeleteAtTimeDetails" }, + { OpcUaId_DeleteEventDetails_Encoding_DefaultBinary, parseDeleteEventDetails, "DeleteEventDetails" }, + { OpcUaId_HistoryUpdateResult_Encoding_DefaultBinary, parseHistoryUpdateResult, "HistoryUpdateResult" }, + { OpcUaId_CallMethodRequest_Encoding_DefaultBinary, parseCallMethodRequest, "CallMethodRequest" }, + { OpcUaId_CallMethodResult_Encoding_DefaultBinary, parseCallMethodResult, "CallMethodResult" }, + { OpcUaId_DataChangeFilter_Encoding_DefaultBinary, parseDataChangeFilter, "DataChangeFilter" }, + { OpcUaId_EventFilter_Encoding_DefaultBinary, parseEventFilter, "EventFilter" }, + { OpcUaId_AggregateConfiguration_Encoding_DefaultBinary, parseAggregateConfiguration, "AggregateConfiguration" }, + { OpcUaId_AggregateFilter_Encoding_DefaultBinary, parseAggregateFilter, "AggregateFilter" }, + { OpcUaId_EventFilterResult_Encoding_DefaultBinary, parseEventFilterResult, "EventFilterResult" }, + { OpcUaId_AggregateFilterResult_Encoding_DefaultBinary, parseAggregateFilterResult, "AggregateFilterResult" }, + { OpcUaId_MonitoringParameters_Encoding_DefaultBinary, parseMonitoringParameters, "MonitoringParameters" }, + { OpcUaId_MonitoredItemCreateRequest_Encoding_DefaultBinary, parseMonitoredItemCreateRequest, "MonitoredItemCreateRequest" }, + { OpcUaId_MonitoredItemCreateResult_Encoding_DefaultBinary, parseMonitoredItemCreateResult, "MonitoredItemCreateResult" }, + { OpcUaId_MonitoredItemModifyRequest_Encoding_DefaultBinary, parseMonitoredItemModifyRequest, "MonitoredItemModifyRequest" }, + { OpcUaId_MonitoredItemModifyResult_Encoding_DefaultBinary, parseMonitoredItemModifyResult, "MonitoredItemModifyResult" }, + { OpcUaId_NotificationMessage_Encoding_DefaultBinary, parseNotificationMessage, "NotificationMessage" }, + { OpcUaId_DataChangeNotification_Encoding_DefaultBinary, parseDataChangeNotification, "DataChangeNotification" }, + { OpcUaId_MonitoredItemNotification_Encoding_DefaultBinary, parseMonitoredItemNotification, "MonitoredItemNotification" }, + { OpcUaId_EventNotificationList_Encoding_DefaultBinary, parseEventNotificationList, "EventNotificationList" }, + { OpcUaId_EventFieldList_Encoding_DefaultBinary, parseEventFieldList, "EventFieldList" }, + { OpcUaId_HistoryEventFieldList_Encoding_DefaultBinary, parseHistoryEventFieldList, "HistoryEventFieldList" }, + { OpcUaId_StatusChangeNotification_Encoding_DefaultBinary, parseStatusChangeNotification, "StatusChangeNotification" }, + { OpcUaId_SubscriptionAcknowledgement_Encoding_DefaultBinary, parseSubscriptionAcknowledgement, "SubscriptionAcknowledgement" }, + { OpcUaId_TransferResult_Encoding_DefaultBinary, parseTransferResult, "TransferResult" }, + { OpcUaId_ScalarTestType_Encoding_DefaultBinary, parseScalarTestType, "ScalarTestType" }, + { OpcUaId_ArrayTestType_Encoding_DefaultBinary, parseArrayTestType, "ArrayTestType" }, + { OpcUaId_CompositeTestType_Encoding_DefaultBinary, parseCompositeTestType, "CompositeTestType" }, + { OpcUaId_BuildInfo_Encoding_DefaultBinary, parseBuildInfo, "BuildInfo" }, + { OpcUaId_RedundantServerDataType_Encoding_DefaultBinary, parseRedundantServerDataType, "RedundantServerDataType" }, + { OpcUaId_EndpointUrlListDataType_Encoding_DefaultBinary, parseEndpointUrlListDataType, "EndpointUrlListDataType" }, + { OpcUaId_NetworkGroupDataType_Encoding_DefaultBinary, parseNetworkGroupDataType, "NetworkGroupDataType" }, + { OpcUaId_SamplingIntervalDiagnosticsDataType_Encoding_DefaultBinary, parseSamplingIntervalDiagnosticsDataType, "SamplingIntervalDiagnosticsDataType" }, + { OpcUaId_ServerDiagnosticsSummaryDataType_Encoding_DefaultBinary, parseServerDiagnosticsSummaryDataType, "ServerDiagnosticsSummaryDataType" }, + { OpcUaId_ServerStatusDataType_Encoding_DefaultBinary, parseServerStatusDataType, "ServerStatusDataType" }, + { OpcUaId_SessionDiagnosticsDataType_Encoding_DefaultBinary, parseSessionDiagnosticsDataType, "SessionDiagnosticsDataType" }, + { OpcUaId_SessionSecurityDiagnosticsDataType_Encoding_DefaultBinary, parseSessionSecurityDiagnosticsDataType, "SessionSecurityDiagnosticsDataType" }, + { OpcUaId_ServiceCounterDataType_Encoding_DefaultBinary, parseServiceCounterDataType, "ServiceCounterDataType" }, + { OpcUaId_StatusResult_Encoding_DefaultBinary, parseStatusResult, "StatusResult" }, + { OpcUaId_SubscriptionDiagnosticsDataType_Encoding_DefaultBinary, parseSubscriptionDiagnosticsDataType, "SubscriptionDiagnosticsDataType" }, + { OpcUaId_ModelChangeStructureDataType_Encoding_DefaultBinary, parseModelChangeStructureDataType, "ModelChangeStructureDataType" }, + { OpcUaId_SemanticChangeStructureDataType_Encoding_DefaultBinary, parseSemanticChangeStructureDataType, "SemanticChangeStructureDataType" }, + { OpcUaId_Range_Encoding_DefaultBinary, parseRange, "Range" }, + { OpcUaId_EUInformation_Encoding_DefaultBinary, parseEUInformation, "EUInformation" }, + { OpcUaId_ComplexNumberType_Encoding_DefaultBinary, parseComplexNumberType, "ComplexNumberType" }, + { OpcUaId_DoubleComplexNumberType_Encoding_DefaultBinary, parseDoubleComplexNumberType, "DoubleComplexNumberType" }, + { OpcUaId_AxisInformation_Encoding_DefaultBinary, parseAxisInformation, "AxisInformation" }, + { OpcUaId_XVType_Encoding_DefaultBinary, parseXVType, "XVType" }, + { OpcUaId_ProgramDiagnosticDataType_Encoding_DefaultBinary, parseProgramDiagnosticDataType, "ProgramDiagnosticDataType" }, + { OpcUaId_Annotation_Encoding_DefaultBinary, parseAnnotation, "Annotation" }, +}; +const int g_NumTypes = sizeof(g_arExtensionObjectParserTable) / sizeof(ExtensionObjectParserEntry); + +/** Dispatch all extension objects to a special parser function. */ +void dispatchExtensionObjectType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int TypeId) +{ + gint iOffset = *pOffset; + int indx = 0; + int bFound = 0; + gint32 iLen = 0; + + /* get the length of the body */ + iLen = tvb_get_letohl(tvb, iOffset); + iOffset += 4; + + while (indx < g_NumTypes) + { + if (g_arExtensionObjectParserTable[indx].iRequestId == TypeId) + { + bFound = 1; + (*g_arExtensionObjectParserTable[indx].pParser)(tree, tvb, pinfo, &iOffset, g_arExtensionObjectParserTable[indx].typeName); + break; + } + indx++; + } + + /* display contained object as ByteString if unknown type */ + if (bFound == 0) + { + if (iLen == -1) + { + proto_tree_add_bytes_format_value(tree, hf_opcua_ByteString, tvb, *pOffset, 4, NULL, "[OpcUa Null ByteString]"); + } + else if (iLen >= 0) + { + proto_tree_add_item(tree, hf_opcua_ByteString, tvb, iOffset, iLen, ENC_NA); + iOffset += iLen; /* eat the whole bytestring */ + } + else + { + proto_tree_add_bytes_format_value(tree, hf_opcua_ByteString, tvb, *pOffset, 4, NULL, "[Invalid ByteString] Invalid length: %d", iLen); + } + } + + *pOffset = iOffset; +} + diff --git a/plugins/epan/opcua/opcua_hfindeces.c b/plugins/epan/opcua/opcua_hfindeces.c new file mode 100644 index 00000000..255927f9 --- /dev/null +++ b/plugins/epan/opcua/opcua_hfindeces.c @@ -0,0 +1,630 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: This file contains protocol field handles. +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** +******************************************************************************/ + +#include "config.h" + +#include + +#include "opcua_hfindeces.h" + +int hf_opcua_AccessLevel = -1; +int hf_opcua_ActualSessionTimeout = -1; +int hf_opcua_AddResults = -1; +int hf_opcua_Algorithm = -1; +int hf_opcua_Alias = -1; +int hf_opcua_AnnotationTime = -1; +int hf_opcua_ApplicationUri = -1; +int hf_opcua_ArrayDimensions = -1; +int hf_opcua_AuditEntryId = -1; +int hf_opcua_AuthenticationMechanism = -1; +int hf_opcua_AvailableSequenceNumbers = -1; +int hf_opcua_AxisSteps = -1; +int hf_opcua_Boolean = -1; +int hf_opcua_Booleans = -1; +int hf_opcua_BuildDate = -1; +int hf_opcua_BuildNumber = -1; +int hf_opcua_Byte = -1; +int hf_opcua_ByteString = -1; +int hf_opcua_ByteStrings = -1; +int hf_opcua_CancelCount = -1; +int hf_opcua_CertificateData = -1; +int hf_opcua_ChannelId = -1; +int hf_opcua_ChannelLifetime = -1; +int hf_opcua_ClientCertificate = -1; +int hf_opcua_ClientConnectionTime = -1; +int hf_opcua_ClientHandle = -1; +int hf_opcua_ClientLastContactTime = -1; +int hf_opcua_ClientNonce = -1; +int hf_opcua_ClientProtocolVersion = -1; +int hf_opcua_ClientUserIdHistory = -1; +int hf_opcua_ClientUserIdOfSession = -1; +int hf_opcua_ComplianceDate = -1; +int hf_opcua_ComplianceTool = -1; +int hf_opcua_ConfigurationResults = -1; +int hf_opcua_ContainsNoLoops = -1; +int hf_opcua_ContinuationPoint = -1; +int hf_opcua_ContinuationPoints = -1; +int hf_opcua_CreateClientName = -1; +int hf_opcua_CreatedAt = -1; +int hf_opcua_CumulatedSessionCount = -1; +int hf_opcua_CumulatedSubscriptionCount = -1; +int hf_opcua_CurrentKeepAliveCount = -1; +int hf_opcua_CurrentLifetimeCount = -1; +int hf_opcua_CurrentMonitoredItemsCount = -1; +int hf_opcua_CurrentPublishRequestsInQueue = -1; +int hf_opcua_CurrentSessionCount = -1; +int hf_opcua_CurrentSubscriptionCount = -1; +int hf_opcua_CurrentSubscriptionsCount = -1; +int hf_opcua_CurrentTime = -1; +int hf_opcua_DataChangeNotificationsCount = -1; +int hf_opcua_DataStatusCodes = -1; +int hf_opcua_DateTime = -1; +int hf_opcua_DateTimes = -1; +int hf_opcua_DaylightSavingInOffset = -1; +int hf_opcua_DeadbandType = -1; +int hf_opcua_DeadbandValue = -1; +int hf_opcua_DeleteBidirectional = -1; +int hf_opcua_DeleteSubscriptions = -1; +int hf_opcua_DeleteTargetReferences = -1; +int hf_opcua_DisableCount = -1; +int hf_opcua_DisabledMonitoredItemCount = -1; +int hf_opcua_DiscardOldest = -1; +int hf_opcua_DiscardedMessageCount = -1; +int hf_opcua_DiscoveryProfileUri = -1; +int hf_opcua_DiscoveryUrl = -1; +int hf_opcua_DiscoveryUrls = -1; +int hf_opcua_Double = -1; +int hf_opcua_Doubles = -1; +int hf_opcua_EnableCount = -1; +int hf_opcua_Encoding = -1; +int hf_opcua_EncryptionAlgorithm = -1; +int hf_opcua_EndTime = -1; +int hf_opcua_EndpointUrl = -1; +int hf_opcua_EndpointUrlList = -1; +int hf_opcua_ErrorCount = -1; +int hf_opcua_EventIds = -1; +int hf_opcua_EventNotificationsCount = -1; +int hf_opcua_EventNotifier = -1; +int hf_opcua_EventQueueOverFlowCount = -1; +int hf_opcua_Executable = -1; +int hf_opcua_Float = -1; +int hf_opcua_Floats = -1; +int hf_opcua_GatewayServerUri = -1; +int hf_opcua_Guid = -1; +int hf_opcua_Guids = -1; +int hf_opcua_High = -1; +int hf_opcua_Historizing = -1; +int hf_opcua_Imaginary = -1; +int hf_opcua_IncludeSubTypes = -1; +int hf_opcua_IncludeSubtypes = -1; +int hf_opcua_Index = -1; +int hf_opcua_IndexRange = -1; +int hf_opcua_InputArgumentResults = -1; +int hf_opcua_Int16 = -1; +int hf_opcua_Int16s = -1; +int hf_opcua_Int32 = -1; +int hf_opcua_Int32s = -1; +int hf_opcua_Int64 = -1; +int hf_opcua_Int64s = -1; +int hf_opcua_InvocationCreationTime = -1; +int hf_opcua_IsAbstract = -1; +int hf_opcua_IsDeleteModified = -1; +int hf_opcua_IsForward = -1; +int hf_opcua_IsInverse = -1; +int hf_opcua_IsOnline = -1; +int hf_opcua_IsReadModified = -1; +int hf_opcua_IssueDate = -1; +int hf_opcua_IssuedBy = -1; +int hf_opcua_IssuedTokenType = -1; +int hf_opcua_IssuerCertificates = -1; +int hf_opcua_IssuerCrls = -1; +int hf_opcua_IssuerEndpointUrl = -1; +int hf_opcua_Iteration = -1; +int hf_opcua_LastCounterResetTime = -1; +int hf_opcua_LastMethodCall = -1; +int hf_opcua_LastMethodCallTime = -1; +int hf_opcua_LastTransitionTime = -1; +int hf_opcua_LatePublishRequestCount = -1; +int hf_opcua_LinksToAdd = -1; +int hf_opcua_LinksToRemove = -1; +int hf_opcua_LocaleIds = -1; +int hf_opcua_Low = -1; +int hf_opcua_ManufacturerName = -1; +int hf_opcua_MaxAge = -1; +int hf_opcua_MaxArrayLength = -1; +int hf_opcua_MaxBufferSize = -1; +int hf_opcua_MaxByteStringLength = -1; +int hf_opcua_MaxDataSetsToReturn = -1; +int hf_opcua_MaxKeepAliveCount = -1; +int hf_opcua_MaxLifetimeCount = -1; +int hf_opcua_MaxMessageSize = -1; +int hf_opcua_MaxMonitoredItemCount = -1; +int hf_opcua_MaxNotificationsPerPublish = -1; +int hf_opcua_MaxRecordsToReturn = -1; +int hf_opcua_MaxReferencesToReturn = -1; +int hf_opcua_MaxRequestMessageSize = -1; +int hf_opcua_MaxResponseMessageSize = -1; +int hf_opcua_MaxStringLength = -1; +int hf_opcua_MdnsServerName = -1; +int hf_opcua_Message = -1; +int hf_opcua_MinimumSamplingInterval = -1; +int hf_opcua_ModificationTime = -1; +int hf_opcua_ModifyCount = -1; +int hf_opcua_MonitoredItemCount = -1; +int hf_opcua_MonitoredItemId = -1; +int hf_opcua_MonitoredItemIds = -1; +int hf_opcua_MonitoringQueueOverflowCount = -1; +int hf_opcua_MoreNotifications = -1; +int hf_opcua_Name = -1; +int hf_opcua_NamespaceUri = -1; +int hf_opcua_NextSequenceNumber = -1; +int hf_opcua_NotificationsCount = -1; +int hf_opcua_NumValuesPerNode = -1; +int hf_opcua_Offset = -1; +int hf_opcua_OperandStatusCodes = -1; +int hf_opcua_OperationResults = -1; +int hf_opcua_OperationTimeout = -1; +int hf_opcua_OrganizationUri = -1; +int hf_opcua_Password = -1; +int hf_opcua_PercentDataBad = -1; +int hf_opcua_PercentDataGood = -1; +int hf_opcua_PolicyId = -1; +int hf_opcua_Priority = -1; +int hf_opcua_ProcessingInterval = -1; +int hf_opcua_ProductName = -1; +int hf_opcua_ProductUri = -1; +int hf_opcua_ProfileId = -1; +int hf_opcua_ProfileUris = -1; +int hf_opcua_PublishRequestCount = -1; +int hf_opcua_PublishTime = -1; +int hf_opcua_PublishingEnabled = -1; +int hf_opcua_PublishingInterval = -1; +int hf_opcua_PublishingIntervalCount = -1; +int hf_opcua_QueueSize = -1; +int hf_opcua_Real = -1; +int hf_opcua_RecordId = -1; +int hf_opcua_RejectedRequestsCount = -1; +int hf_opcua_RejectedSessionCount = -1; +int hf_opcua_ReleaseContinuationPoint = -1; +int hf_opcua_ReleaseContinuationPoints = -1; +int hf_opcua_RemainingPathIndex = -1; +int hf_opcua_RemoveResults = -1; +int hf_opcua_RepublishMessageCount = -1; +int hf_opcua_RepublishMessageRequestCount = -1; +int hf_opcua_RepublishRequestCount = -1; +int hf_opcua_ReqTimes = -1; +int hf_opcua_RequestHandle = -1; +int hf_opcua_RequestedLifetime = -1; +int hf_opcua_RequestedLifetimeCount = -1; +int hf_opcua_RequestedMaxKeepAliveCount = -1; +int hf_opcua_RequestedMaxReferencesPerNode = -1; +int hf_opcua_RequestedPublishingInterval = -1; +int hf_opcua_RequestedSessionTimeout = -1; +int hf_opcua_Results = -1; +int hf_opcua_RetransmitSequenceNumber = -1; +int hf_opcua_ReturnBounds = -1; +int hf_opcua_ReturnDiagnostics = -1; +int hf_opcua_RevisedContinuationPoint = -1; +int hf_opcua_RevisedLifetime = -1; +int hf_opcua_RevisedLifetimeCount = -1; +int hf_opcua_RevisedMaxKeepAliveCount = -1; +int hf_opcua_RevisedProcessingInterval = -1; +int hf_opcua_RevisedPublishingInterval = -1; +int hf_opcua_RevisedQueueSize = -1; +int hf_opcua_RevisedSamplingInterval = -1; +int hf_opcua_RevisedSessionTimeout = -1; +int hf_opcua_RevisedStartTime = -1; +int hf_opcua_SByte = -1; +int hf_opcua_SBytes = -1; +int hf_opcua_SamplingInterval = -1; +int hf_opcua_SecondsTillShutdown = -1; +int hf_opcua_SecurityLevel = -1; +int hf_opcua_SecurityPolicyUri = -1; +int hf_opcua_SecurityRejectedRequestsCount = -1; +int hf_opcua_SecurityRejectedSessionCount = -1; +int hf_opcua_SecurityTokenLifetime = -1; +int hf_opcua_SelectClauseResults = -1; +int hf_opcua_SemaphoreFilePath = -1; +int hf_opcua_SendInitialValues = -1; +int hf_opcua_SequenceNumber = -1; +int hf_opcua_ServerCapabilities = -1; +int hf_opcua_ServerCapabilityFilter = -1; +int hf_opcua_ServerCertificate = -1; +int hf_opcua_ServerId = -1; +int hf_opcua_ServerName = -1; +int hf_opcua_ServerNonce = -1; +int hf_opcua_ServerProtocolVersion = -1; +int hf_opcua_ServerUri = -1; +int hf_opcua_ServerUris = -1; +int hf_opcua_ServerViewCount = -1; +int hf_opcua_ServiceLevel = -1; +int hf_opcua_ServiceResult = -1; +int hf_opcua_SessionAbortCount = -1; +int hf_opcua_SessionName = -1; +int hf_opcua_SessionTimeoutCount = -1; +int hf_opcua_Signature = -1; +int hf_opcua_SoftwareVersion = -1; +int hf_opcua_SpecifiedAttributes = -1; +int hf_opcua_SpecifiedLists = -1; +int hf_opcua_StartTime = -1; +int hf_opcua_StartingRecordId = -1; +int hf_opcua_Status = -1; +int hf_opcua_StatusCode = -1; +int hf_opcua_StatusCodes = -1; +int hf_opcua_String = -1; +int hf_opcua_StringTable = -1; +int hf_opcua_Strings = -1; +int hf_opcua_SubscriptionId = -1; +int hf_opcua_SubscriptionIds = -1; +int hf_opcua_Symmetric = -1; +int hf_opcua_TargetServerUri = -1; +int hf_opcua_TestId = -1; +int hf_opcua_TicketData = -1; +int hf_opcua_TimeoutHint = -1; +int hf_opcua_Timestamp = -1; +int hf_opcua_TokenData = -1; +int hf_opcua_TokenId = -1; +int hf_opcua_TotalCount = -1; +int hf_opcua_TransferRequestCount = -1; +int hf_opcua_TransferredToAltClientCount = -1; +int hf_opcua_TransferredToSameClientCount = -1; +int hf_opcua_TransportProfileUri = -1; +int hf_opcua_TransportProtocol = -1; +int hf_opcua_TreatUncertainAsBad = -1; +int hf_opcua_TriggeringItemId = -1; +int hf_opcua_TrustedCertificates = -1; +int hf_opcua_TrustedCrls = -1; +int hf_opcua_UInt16 = -1; +int hf_opcua_UInt16s = -1; +int hf_opcua_UInt32 = -1; +int hf_opcua_UInt32s = -1; +int hf_opcua_UInt64 = -1; +int hf_opcua_UInt64s = -1; +int hf_opcua_UnacknowledgedMessageCount = -1; +int hf_opcua_UnauthorizedRequestCount = -1; +int hf_opcua_UnitId = -1; +int hf_opcua_UnsupportedUnitIds = -1; +int hf_opcua_UseBinaryEncoding = -1; +int hf_opcua_UseServerCapabilitiesDefaults = -1; +int hf_opcua_UseSimpleBounds = -1; +int hf_opcua_UseSlopedExtrapolation = -1; +int hf_opcua_UserAccessLevel = -1; +int hf_opcua_UserExecutable = -1; +int hf_opcua_UserName = -1; +int hf_opcua_UserWriteMask = -1; +int hf_opcua_ValidBits = -1; +int hf_opcua_Value = -1; +int hf_opcua_ValueRank = -1; +int hf_opcua_VendorName = -1; +int hf_opcua_VendorProductCertificate = -1; +int hf_opcua_Verb = -1; +int hf_opcua_ViewVersion = -1; +int hf_opcua_WriteMask = -1; +int hf_opcua_X = -1; +int hf_opcua_XmlElement = -1; +int hf_opcua_XmlElements = -1; + +/** Register field types. */ +void registerFieldTypes(int proto) +{ + /** header field definitions */ + static hf_register_info hf[] = + { + { &hf_opcua_AccessLevel, { "AccessLevel", "opcua.AccessLevel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ActualSessionTimeout, { "ActualSessionTimeout", "opcua.ActualSessionTimeout", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_AddResults, { "AddResults", "opcua.AddResults", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Algorithm, { "Algorithm", "opcua.Algorithm", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Alias, { "Alias", "opcua.Alias", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_AnnotationTime, { "AnnotationTime", "opcua.AnnotationTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ApplicationUri, { "ApplicationUri", "opcua.ApplicationUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ArrayDimensions, { "ArrayDimensions", "opcua.ArrayDimensions", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_AuditEntryId, { "AuditEntryId", "opcua.AuditEntryId", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_AuthenticationMechanism, { "AuthenticationMechanism", "opcua.AuthenticationMechanism", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_AvailableSequenceNumbers, { "AvailableSequenceNumbers", "opcua.AvailableSequenceNumbers", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_AxisSteps, { "AxisSteps", "opcua.AxisSteps", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Boolean, { "Boolean", "opcua.Boolean", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Booleans, { "Booleans", "opcua.Booleans", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_BuildDate, { "BuildDate", "opcua.BuildDate", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_BuildNumber, { "BuildNumber", "opcua.BuildNumber", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Byte, { "Byte", "opcua.Byte", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ByteString, { "ByteString", "opcua.ByteString", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ByteStrings, { "ByteStrings", "opcua.ByteStrings", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CancelCount, { "CancelCount", "opcua.CancelCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CertificateData, { "CertificateData", "opcua.CertificateData", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ChannelId, { "ChannelId", "opcua.ChannelId", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ChannelLifetime, { "ChannelLifetime", "opcua.ChannelLifetime", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ClientCertificate, { "ClientCertificate", "opcua.ClientCertificate", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ClientConnectionTime, { "ClientConnectionTime", "opcua.ClientConnectionTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ClientHandle, { "ClientHandle", "opcua.ClientHandle", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ClientLastContactTime, { "ClientLastContactTime", "opcua.ClientLastContactTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ClientNonce, { "ClientNonce", "opcua.ClientNonce", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ClientProtocolVersion, { "ClientProtocolVersion", "opcua.ClientProtocolVersion", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ClientUserIdHistory, { "ClientUserIdHistory", "opcua.ClientUserIdHistory", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ClientUserIdOfSession, { "ClientUserIdOfSession", "opcua.ClientUserIdOfSession", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ComplianceDate, { "ComplianceDate", "opcua.ComplianceDate", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ComplianceTool, { "ComplianceTool", "opcua.ComplianceTool", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ConfigurationResults, { "ConfigurationResults", "opcua.ConfigurationResults", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ContainsNoLoops, { "ContainsNoLoops", "opcua.ContainsNoLoops", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ContinuationPoint, { "ContinuationPoint", "opcua.ContinuationPoint", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ContinuationPoints, { "ContinuationPoints", "opcua.ContinuationPoints", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CreateClientName, { "CreateClientName", "opcua.CreateClientName", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CreatedAt, { "CreatedAt", "opcua.CreatedAt", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CumulatedSessionCount, { "CumulatedSessionCount", "opcua.CumulatedSessionCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CumulatedSubscriptionCount, { "CumulatedSubscriptionCount", "opcua.CumulatedSubscriptionCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CurrentKeepAliveCount, { "CurrentKeepAliveCount", "opcua.CurrentKeepAliveCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CurrentLifetimeCount, { "CurrentLifetimeCount", "opcua.CurrentLifetimeCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CurrentMonitoredItemsCount, { "CurrentMonitoredItemsCount", "opcua.CurrentMonitoredItemsCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CurrentPublishRequestsInQueue, { "CurrentPublishRequestsInQueue", "opcua.CurrentPublishRequestsInQueue", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CurrentSessionCount, { "CurrentSessionCount", "opcua.CurrentSessionCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CurrentSubscriptionCount, { "CurrentSubscriptionCount", "opcua.CurrentSubscriptionCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CurrentSubscriptionsCount, { "CurrentSubscriptionsCount", "opcua.CurrentSubscriptionsCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_CurrentTime, { "CurrentTime", "opcua.CurrentTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DataChangeNotificationsCount, { "DataChangeNotificationsCount", "opcua.DataChangeNotificationsCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DataStatusCodes, { "DataStatusCodes", "opcua.DataStatusCodes", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DateTime, { "DateTime", "opcua.DateTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DateTimes, { "DateTimes", "opcua.DateTimes", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DaylightSavingInOffset, { "DaylightSavingInOffset", "opcua.DaylightSavingInOffset", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DeadbandType, { "DeadbandType", "opcua.DeadbandType", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DeadbandValue, { "DeadbandValue", "opcua.DeadbandValue", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DeleteBidirectional, { "DeleteBidirectional", "opcua.DeleteBidirectional", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DeleteSubscriptions, { "DeleteSubscriptions", "opcua.DeleteSubscriptions", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DeleteTargetReferences, { "DeleteTargetReferences", "opcua.DeleteTargetReferences", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DisableCount, { "DisableCount", "opcua.DisableCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DisabledMonitoredItemCount, { "DisabledMonitoredItemCount", "opcua.DisabledMonitoredItemCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DiscardOldest, { "DiscardOldest", "opcua.DiscardOldest", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DiscardedMessageCount, { "DiscardedMessageCount", "opcua.DiscardedMessageCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DiscoveryProfileUri, { "DiscoveryProfileUri", "opcua.DiscoveryProfileUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DiscoveryUrl, { "DiscoveryUrl", "opcua.DiscoveryUrl", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_DiscoveryUrls, { "DiscoveryUrls", "opcua.DiscoveryUrls", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Double, { "Double", "opcua.Double", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Doubles, { "Doubles", "opcua.Doubles", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EnableCount, { "EnableCount", "opcua.EnableCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Encoding, { "Encoding", "opcua.Encoding", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EncryptionAlgorithm, { "EncryptionAlgorithm", "opcua.EncryptionAlgorithm", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EndTime, { "EndTime", "opcua.EndTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EndpointUrl, { "EndpointUrl", "opcua.EndpointUrl", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EndpointUrlList, { "EndpointUrlList", "opcua.EndpointUrlList", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ErrorCount, { "ErrorCount", "opcua.ErrorCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EventIds, { "EventIds", "opcua.EventIds", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EventNotificationsCount, { "EventNotificationsCount", "opcua.EventNotificationsCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EventNotifier, { "EventNotifier", "opcua.EventNotifier", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_EventQueueOverFlowCount, { "EventQueueOverFlowCount", "opcua.EventQueueOverFlowCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Executable, { "Executable", "opcua.Executable", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Float, { "Float", "opcua.Float", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Floats, { "Floats", "opcua.Floats", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_GatewayServerUri, { "GatewayServerUri", "opcua.GatewayServerUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Guid, { "Guid", "opcua.Guid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Guids, { "Guids", "opcua.Guids", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_High, { "High", "opcua.High", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Historizing, { "Historizing", "opcua.Historizing", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Imaginary, { "Imaginary", "opcua.Imaginary", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IncludeSubTypes, { "IncludeSubTypes", "opcua.IncludeSubTypes", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IncludeSubtypes, { "IncludeSubtypes", "opcua.IncludeSubtypes", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Index, { "Index", "opcua.Index", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IndexRange, { "IndexRange", "opcua.IndexRange", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_InputArgumentResults, { "InputArgumentResults", "opcua.InputArgumentResults", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Int16, { "Int16", "opcua.Int16", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Int16s, { "Int16s", "opcua.Int16s", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Int32, { "Int32", "opcua.Int32", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Int32s, { "Int32s", "opcua.Int32s", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Int64, { "Int64", "opcua.Int64", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Int64s, { "Int64s", "opcua.Int64s", FT_INT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_InvocationCreationTime, { "InvocationCreationTime", "opcua.InvocationCreationTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IsAbstract, { "IsAbstract", "opcua.IsAbstract", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IsDeleteModified, { "IsDeleteModified", "opcua.IsDeleteModified", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IsForward, { "IsForward", "opcua.IsForward", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IsInverse, { "IsInverse", "opcua.IsInverse", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IsOnline, { "IsOnline", "opcua.IsOnline", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IsReadModified, { "IsReadModified", "opcua.IsReadModified", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IssueDate, { "IssueDate", "opcua.IssueDate", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IssuedBy, { "IssuedBy", "opcua.IssuedBy", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IssuedTokenType, { "IssuedTokenType", "opcua.IssuedTokenType", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IssuerCertificates, { "IssuerCertificates", "opcua.IssuerCertificates", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IssuerCrls, { "IssuerCrls", "opcua.IssuerCrls", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_IssuerEndpointUrl, { "IssuerEndpointUrl", "opcua.IssuerEndpointUrl", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Iteration, { "Iteration", "opcua.Iteration", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_LastCounterResetTime, { "LastCounterResetTime", "opcua.LastCounterResetTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_LastMethodCall, { "LastMethodCall", "opcua.LastMethodCall", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_LastMethodCallTime, { "LastMethodCallTime", "opcua.LastMethodCallTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_LastTransitionTime, { "LastTransitionTime", "opcua.LastTransitionTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_LatePublishRequestCount, { "LatePublishRequestCount", "opcua.LatePublishRequestCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_LinksToAdd, { "LinksToAdd", "opcua.LinksToAdd", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_LinksToRemove, { "LinksToRemove", "opcua.LinksToRemove", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_LocaleIds, { "LocaleIds", "opcua.LocaleIds", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Low, { "Low", "opcua.Low", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ManufacturerName, { "ManufacturerName", "opcua.ManufacturerName", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxAge, { "MaxAge", "opcua.MaxAge", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxArrayLength, { "MaxArrayLength", "opcua.MaxArrayLength", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxBufferSize, { "MaxBufferSize", "opcua.MaxBufferSize", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxByteStringLength, { "MaxByteStringLength", "opcua.MaxByteStringLength", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxDataSetsToReturn, { "MaxDataSetsToReturn", "opcua.MaxDataSetsToReturn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxKeepAliveCount, { "MaxKeepAliveCount", "opcua.MaxKeepAliveCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxLifetimeCount, { "MaxLifetimeCount", "opcua.MaxLifetimeCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxMessageSize, { "MaxMessageSize", "opcua.MaxMessageSize", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxMonitoredItemCount, { "MaxMonitoredItemCount", "opcua.MaxMonitoredItemCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxNotificationsPerPublish, { "MaxNotificationsPerPublish", "opcua.MaxNotificationsPerPublish", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxRecordsToReturn, { "MaxRecordsToReturn", "opcua.MaxRecordsToReturn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxReferencesToReturn, { "MaxReferencesToReturn", "opcua.MaxReferencesToReturn", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxRequestMessageSize, { "MaxRequestMessageSize", "opcua.MaxRequestMessageSize", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxResponseMessageSize, { "MaxResponseMessageSize", "opcua.MaxResponseMessageSize", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MaxStringLength, { "MaxStringLength", "opcua.MaxStringLength", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MdnsServerName, { "MdnsServerName", "opcua.MdnsServerName", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Message, { "Message", "opcua.Message", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MinimumSamplingInterval, { "MinimumSamplingInterval", "opcua.MinimumSamplingInterval", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ModificationTime, { "ModificationTime", "opcua.ModificationTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ModifyCount, { "ModifyCount", "opcua.ModifyCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MonitoredItemCount, { "MonitoredItemCount", "opcua.MonitoredItemCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MonitoredItemId, { "MonitoredItemId", "opcua.MonitoredItemId", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MonitoredItemIds, { "MonitoredItemIds", "opcua.MonitoredItemIds", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MonitoringQueueOverflowCount, { "MonitoringQueueOverflowCount", "opcua.MonitoringQueueOverflowCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_MoreNotifications, { "MoreNotifications", "opcua.MoreNotifications", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Name, { "Name", "opcua.Name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_NamespaceUri, { "NamespaceUri", "opcua.NamespaceUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_NextSequenceNumber, { "NextSequenceNumber", "opcua.NextSequenceNumber", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_NotificationsCount, { "NotificationsCount", "opcua.NotificationsCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_NumValuesPerNode, { "NumValuesPerNode", "opcua.NumValuesPerNode", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Offset, { "Offset", "opcua.Offset", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_OperandStatusCodes, { "OperandStatusCodes", "opcua.OperandStatusCodes", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_OperationResults, { "OperationResults", "opcua.OperationResults", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_OperationTimeout, { "OperationTimeout", "opcua.OperationTimeout", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_OrganizationUri, { "OrganizationUri", "opcua.OrganizationUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Password, { "Password", "opcua.Password", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_PercentDataBad, { "PercentDataBad", "opcua.PercentDataBad", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_PercentDataGood, { "PercentDataGood", "opcua.PercentDataGood", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_PolicyId, { "PolicyId", "opcua.PolicyId", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Priority, { "Priority", "opcua.Priority", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ProcessingInterval, { "ProcessingInterval", "opcua.ProcessingInterval", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ProductName, { "ProductName", "opcua.ProductName", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ProductUri, { "ProductUri", "opcua.ProductUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ProfileId, { "ProfileId", "opcua.ProfileId", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ProfileUris, { "ProfileUris", "opcua.ProfileUris", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_PublishRequestCount, { "PublishRequestCount", "opcua.PublishRequestCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_PublishTime, { "PublishTime", "opcua.PublishTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_PublishingEnabled, { "PublishingEnabled", "opcua.PublishingEnabled", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_PublishingInterval, { "PublishingInterval", "opcua.PublishingInterval", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_PublishingIntervalCount, { "PublishingIntervalCount", "opcua.PublishingIntervalCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_QueueSize, { "QueueSize", "opcua.QueueSize", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Real, { "Real", "opcua.Real", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RecordId, { "RecordId", "opcua.RecordId", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RejectedRequestsCount, { "RejectedRequestsCount", "opcua.RejectedRequestsCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RejectedSessionCount, { "RejectedSessionCount", "opcua.RejectedSessionCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ReleaseContinuationPoint, { "ReleaseContinuationPoint", "opcua.ReleaseContinuationPoint", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ReleaseContinuationPoints, { "ReleaseContinuationPoints", "opcua.ReleaseContinuationPoints", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RemainingPathIndex, { "RemainingPathIndex", "opcua.RemainingPathIndex", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RemoveResults, { "RemoveResults", "opcua.RemoveResults", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RepublishMessageCount, { "RepublishMessageCount", "opcua.RepublishMessageCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RepublishMessageRequestCount, { "RepublishMessageRequestCount", "opcua.RepublishMessageRequestCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RepublishRequestCount, { "RepublishRequestCount", "opcua.RepublishRequestCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ReqTimes, { "ReqTimes", "opcua.ReqTimes", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RequestHandle, { "RequestHandle", "opcua.RequestHandle", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RequestedLifetime, { "RequestedLifetime", "opcua.RequestedLifetime", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RequestedLifetimeCount, { "RequestedLifetimeCount", "opcua.RequestedLifetimeCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RequestedMaxKeepAliveCount, { "RequestedMaxKeepAliveCount", "opcua.RequestedMaxKeepAliveCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RequestedMaxReferencesPerNode, { "RequestedMaxReferencesPerNode", "opcua.RequestedMaxReferencesPerNode", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RequestedPublishingInterval, { "RequestedPublishingInterval", "opcua.RequestedPublishingInterval", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RequestedSessionTimeout, { "RequestedSessionTimeout", "opcua.RequestedSessionTimeout", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Results, { "Results", "opcua.Results", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RetransmitSequenceNumber, { "RetransmitSequenceNumber", "opcua.RetransmitSequenceNumber", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ReturnBounds, { "ReturnBounds", "opcua.ReturnBounds", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ReturnDiagnostics, { "ReturnDiagnostics", "opcua.ReturnDiagnostics", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedContinuationPoint, { "RevisedContinuationPoint", "opcua.RevisedContinuationPoint", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedLifetime, { "RevisedLifetime", "opcua.RevisedLifetime", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedLifetimeCount, { "RevisedLifetimeCount", "opcua.RevisedLifetimeCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedMaxKeepAliveCount, { "RevisedMaxKeepAliveCount", "opcua.RevisedMaxKeepAliveCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedProcessingInterval, { "RevisedProcessingInterval", "opcua.RevisedProcessingInterval", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedPublishingInterval, { "RevisedPublishingInterval", "opcua.RevisedPublishingInterval", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedQueueSize, { "RevisedQueueSize", "opcua.RevisedQueueSize", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedSamplingInterval, { "RevisedSamplingInterval", "opcua.RevisedSamplingInterval", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedSessionTimeout, { "RevisedSessionTimeout", "opcua.RevisedSessionTimeout", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_RevisedStartTime, { "RevisedStartTime", "opcua.RevisedStartTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SByte, { "SByte", "opcua.SByte", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SBytes, { "SBytes", "opcua.SBytes", FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SamplingInterval, { "SamplingInterval", "opcua.SamplingInterval", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SecondsTillShutdown, { "SecondsTillShutdown", "opcua.SecondsTillShutdown", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SecurityLevel, { "SecurityLevel", "opcua.SecurityLevel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SecurityPolicyUri, { "SecurityPolicyUri", "opcua.SecurityPolicyUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SecurityRejectedRequestsCount, { "SecurityRejectedRequestsCount", "opcua.SecurityRejectedRequestsCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SecurityRejectedSessionCount, { "SecurityRejectedSessionCount", "opcua.SecurityRejectedSessionCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SecurityTokenLifetime, { "SecurityTokenLifetime", "opcua.SecurityTokenLifetime", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SelectClauseResults, { "SelectClauseResults", "opcua.SelectClauseResults", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SemaphoreFilePath, { "SemaphoreFilePath", "opcua.SemaphoreFilePath", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SendInitialValues, { "SendInitialValues", "opcua.SendInitialValues", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SequenceNumber, { "SequenceNumber", "opcua.SequenceNumber", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerCapabilities, { "ServerCapabilities", "opcua.ServerCapabilities", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerCapabilityFilter, { "ServerCapabilityFilter", "opcua.ServerCapabilityFilter", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerCertificate, { "ServerCertificate", "opcua.ServerCertificate", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerId, { "ServerId", "opcua.ServerId", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerName, { "ServerName", "opcua.ServerName", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerNonce, { "ServerNonce", "opcua.ServerNonce", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerProtocolVersion, { "ServerProtocolVersion", "opcua.ServerProtocolVersion", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerUri, { "ServerUri", "opcua.ServerUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerUris, { "ServerUris", "opcua.ServerUris", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServerViewCount, { "ServerViewCount", "opcua.ServerViewCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServiceLevel, { "ServiceLevel", "opcua.ServiceLevel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ServiceResult, { "ServiceResult", "opcua.ServiceResult", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SessionAbortCount, { "SessionAbortCount", "opcua.SessionAbortCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SessionName, { "SessionName", "opcua.SessionName", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SessionTimeoutCount, { "SessionTimeoutCount", "opcua.SessionTimeoutCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Signature, { "Signature", "opcua.Signature", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SoftwareVersion, { "SoftwareVersion", "opcua.SoftwareVersion", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SpecifiedAttributes, { "SpecifiedAttributes", "opcua.SpecifiedAttributes", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SpecifiedLists, { "SpecifiedLists", "opcua.SpecifiedLists", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_StartTime, { "StartTime", "opcua.StartTime", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_StartingRecordId, { "StartingRecordId", "opcua.StartingRecordId", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Status, { "Status", "opcua.Status", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_StatusCode, { "StatusCode", "opcua.StatusCode", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_StatusCodes, { "StatusCodes", "opcua.StatusCodes", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_String, { "String", "opcua.String", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_StringTable, { "StringTable", "opcua.StringTable", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Strings, { "Strings", "opcua.Strings", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SubscriptionId, { "SubscriptionId", "opcua.SubscriptionId", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_SubscriptionIds, { "SubscriptionIds", "opcua.SubscriptionIds", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Symmetric, { "Symmetric", "opcua.Symmetric", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TargetServerUri, { "TargetServerUri", "opcua.TargetServerUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TestId, { "TestId", "opcua.TestId", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TicketData, { "TicketData", "opcua.TicketData", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TimeoutHint, { "TimeoutHint", "opcua.TimeoutHint", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Timestamp, { "Timestamp", "opcua.Timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TokenData, { "TokenData", "opcua.TokenData", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TokenId, { "TokenId", "opcua.TokenId", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TotalCount, { "TotalCount", "opcua.TotalCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TransferRequestCount, { "TransferRequestCount", "opcua.TransferRequestCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TransferredToAltClientCount, { "TransferredToAltClientCount", "opcua.TransferredToAltClientCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TransferredToSameClientCount, { "TransferredToSameClientCount", "opcua.TransferredToSameClientCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TransportProfileUri, { "TransportProfileUri", "opcua.TransportProfileUri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TransportProtocol, { "TransportProtocol", "opcua.TransportProtocol", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TreatUncertainAsBad, { "TreatUncertainAsBad", "opcua.TreatUncertainAsBad", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TriggeringItemId, { "TriggeringItemId", "opcua.TriggeringItemId", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TrustedCertificates, { "TrustedCertificates", "opcua.TrustedCertificates", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_TrustedCrls, { "TrustedCrls", "opcua.TrustedCrls", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UInt16, { "UInt16", "opcua.UInt16", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UInt16s, { "UInt16s", "opcua.UInt16s", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UInt32, { "UInt32", "opcua.UInt32", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UInt32s, { "UInt32s", "opcua.UInt32s", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UInt64, { "UInt64", "opcua.UInt64", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UInt64s, { "UInt64s", "opcua.UInt64s", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UnacknowledgedMessageCount, { "UnacknowledgedMessageCount", "opcua.UnacknowledgedMessageCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UnauthorizedRequestCount, { "UnauthorizedRequestCount", "opcua.UnauthorizedRequestCount", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UnitId, { "UnitId", "opcua.UnitId", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UnsupportedUnitIds, { "UnsupportedUnitIds", "opcua.UnsupportedUnitIds", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UseBinaryEncoding, { "UseBinaryEncoding", "opcua.UseBinaryEncoding", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UseServerCapabilitiesDefaults, { "UseServerCapabilitiesDefaults", "opcua.UseServerCapabilitiesDefaults", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UseSimpleBounds, { "UseSimpleBounds", "opcua.UseSimpleBounds", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UseSlopedExtrapolation, { "UseSlopedExtrapolation", "opcua.UseSlopedExtrapolation", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UserAccessLevel, { "UserAccessLevel", "opcua.UserAccessLevel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UserExecutable, { "UserExecutable", "opcua.UserExecutable", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UserName, { "UserName", "opcua.UserName", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_UserWriteMask, { "UserWriteMask", "opcua.UserWriteMask", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ValidBits, { "ValidBits", "opcua.ValidBits", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Value, { "Value", "opcua.Value", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ValueRank, { "ValueRank", "opcua.ValueRank", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_VendorName, { "VendorName", "opcua.VendorName", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_VendorProductCertificate, { "VendorProductCertificate", "opcua.VendorProductCertificate", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_Verb, { "Verb", "opcua.Verb", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_ViewVersion, { "ViewVersion", "opcua.ViewVersion", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_WriteMask, { "WriteMask", "opcua.WriteMask", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_X, { "X", "opcua.X", FT_DOUBLE, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_XmlElement, { "XmlElement", "opcua.XmlElement", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + { &hf_opcua_XmlElements, { "XmlElements", "opcua.XmlElements", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } }, + }; + + proto_register_field_array(proto, hf, array_length(hf)); +} + + + diff --git a/plugins/epan/opcua/opcua_hfindeces.h b/plugins/epan/opcua/opcua_hfindeces.h new file mode 100644 index 00000000..0c1bd2cf --- /dev/null +++ b/plugins/epan/opcua/opcua_hfindeces.h @@ -0,0 +1,322 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: This file contains protocol field handles. +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** XXX - well, except that you may have to. See the README. +** +******************************************************************************/ + +#include +#include + +extern int hf_opcua_AccessLevel; +extern int hf_opcua_ActualSessionTimeout; +extern int hf_opcua_AddResults; +extern int hf_opcua_Algorithm; +extern int hf_opcua_Alias; +extern int hf_opcua_AnnotationTime; +extern int hf_opcua_ApplicationUri; +extern int hf_opcua_ArrayDimensions; +extern int hf_opcua_AuditEntryId; +extern int hf_opcua_AuthenticationMechanism; +extern int hf_opcua_AvailableSequenceNumbers; +extern int hf_opcua_AxisSteps; +extern int hf_opcua_Boolean; +extern int hf_opcua_Booleans; +extern int hf_opcua_BuildDate; +extern int hf_opcua_BuildNumber; +extern int hf_opcua_Byte; +extern int hf_opcua_ByteString; +extern int hf_opcua_ByteStrings; +extern int hf_opcua_CancelCount; +extern int hf_opcua_CertificateData; +extern int hf_opcua_ChannelId; +extern int hf_opcua_ChannelLifetime; +extern int hf_opcua_ClientCertificate; +extern int hf_opcua_ClientConnectionTime; +extern int hf_opcua_ClientHandle; +extern int hf_opcua_ClientLastContactTime; +extern int hf_opcua_ClientNonce; +extern int hf_opcua_ClientProtocolVersion; +extern int hf_opcua_ClientUserIdHistory; +extern int hf_opcua_ClientUserIdOfSession; +extern int hf_opcua_ComplianceDate; +extern int hf_opcua_ComplianceTool; +extern int hf_opcua_ConfigurationResults; +extern int hf_opcua_ContainsNoLoops; +extern int hf_opcua_ContinuationPoint; +extern int hf_opcua_ContinuationPoints; +extern int hf_opcua_CreateClientName; +extern int hf_opcua_CreatedAt; +extern int hf_opcua_CumulatedSessionCount; +extern int hf_opcua_CumulatedSubscriptionCount; +extern int hf_opcua_CurrentKeepAliveCount; +extern int hf_opcua_CurrentLifetimeCount; +extern int hf_opcua_CurrentMonitoredItemsCount; +extern int hf_opcua_CurrentPublishRequestsInQueue; +extern int hf_opcua_CurrentSessionCount; +extern int hf_opcua_CurrentSubscriptionCount; +extern int hf_opcua_CurrentSubscriptionsCount; +extern int hf_opcua_CurrentTime; +extern int hf_opcua_DataChangeNotificationsCount; +extern int hf_opcua_DataStatusCodes; +extern int hf_opcua_DateTime; +extern int hf_opcua_DateTimes; +extern int hf_opcua_DaylightSavingInOffset; +extern int hf_opcua_DeadbandType; +extern int hf_opcua_DeadbandValue; +extern int hf_opcua_DeleteBidirectional; +extern int hf_opcua_DeleteSubscriptions; +extern int hf_opcua_DeleteTargetReferences; +extern int hf_opcua_DisableCount; +extern int hf_opcua_DisabledMonitoredItemCount; +extern int hf_opcua_DiscardOldest; +extern int hf_opcua_DiscardedMessageCount; +extern int hf_opcua_DiscoveryProfileUri; +extern int hf_opcua_DiscoveryUrl; +extern int hf_opcua_DiscoveryUrls; +extern int hf_opcua_Double; +extern int hf_opcua_Doubles; +extern int hf_opcua_EnableCount; +extern int hf_opcua_Encoding; +extern int hf_opcua_EncryptionAlgorithm; +extern int hf_opcua_EndTime; +extern int hf_opcua_EndpointUrl; +extern int hf_opcua_EndpointUrlList; +extern int hf_opcua_ErrorCount; +extern int hf_opcua_EventIds; +extern int hf_opcua_EventNotificationsCount; +extern int hf_opcua_EventNotifier; +extern int hf_opcua_EventQueueOverFlowCount; +extern int hf_opcua_Executable; +extern int hf_opcua_Float; +extern int hf_opcua_Floats; +extern int hf_opcua_GatewayServerUri; +extern int hf_opcua_Guid; +extern int hf_opcua_Guids; +extern int hf_opcua_High; +extern int hf_opcua_Historizing; +extern int hf_opcua_Imaginary; +extern int hf_opcua_IncludeSubTypes; +extern int hf_opcua_IncludeSubtypes; +extern int hf_opcua_Index; +extern int hf_opcua_IndexRange; +extern int hf_opcua_InputArgumentResults; +extern int hf_opcua_Int16; +extern int hf_opcua_Int16s; +extern int hf_opcua_Int32; +extern int hf_opcua_Int32s; +extern int hf_opcua_Int64; +extern int hf_opcua_Int64s; +extern int hf_opcua_InvocationCreationTime; +extern int hf_opcua_IsAbstract; +extern int hf_opcua_IsDeleteModified; +extern int hf_opcua_IsForward; +extern int hf_opcua_IsInverse; +extern int hf_opcua_IsOnline; +extern int hf_opcua_IsReadModified; +extern int hf_opcua_IssueDate; +extern int hf_opcua_IssuedBy; +extern int hf_opcua_IssuedTokenType; +extern int hf_opcua_IssuerCertificates; +extern int hf_opcua_IssuerCrls; +extern int hf_opcua_IssuerEndpointUrl; +extern int hf_opcua_Iteration; +extern int hf_opcua_LastCounterResetTime; +extern int hf_opcua_LastMethodCall; +extern int hf_opcua_LastMethodCallTime; +extern int hf_opcua_LastTransitionTime; +extern int hf_opcua_LatePublishRequestCount; +extern int hf_opcua_LinksToAdd; +extern int hf_opcua_LinksToRemove; +extern int hf_opcua_LocaleIds; +extern int hf_opcua_Low; +extern int hf_opcua_ManufacturerName; +extern int hf_opcua_MaxAge; +extern int hf_opcua_MaxArrayLength; +extern int hf_opcua_MaxBufferSize; +extern int hf_opcua_MaxByteStringLength; +extern int hf_opcua_MaxDataSetsToReturn; +extern int hf_opcua_MaxKeepAliveCount; +extern int hf_opcua_MaxLifetimeCount; +extern int hf_opcua_MaxMessageSize; +extern int hf_opcua_MaxMonitoredItemCount; +extern int hf_opcua_MaxNotificationsPerPublish; +extern int hf_opcua_MaxRecordsToReturn; +extern int hf_opcua_MaxReferencesToReturn; +extern int hf_opcua_MaxRequestMessageSize; +extern int hf_opcua_MaxResponseMessageSize; +extern int hf_opcua_MaxStringLength; +extern int hf_opcua_MdnsServerName; +extern int hf_opcua_Message; +extern int hf_opcua_MinimumSamplingInterval; +extern int hf_opcua_ModificationTime; +extern int hf_opcua_ModifyCount; +extern int hf_opcua_MonitoredItemCount; +extern int hf_opcua_MonitoredItemId; +extern int hf_opcua_MonitoredItemIds; +extern int hf_opcua_MonitoringQueueOverflowCount; +extern int hf_opcua_MoreNotifications; +extern int hf_opcua_Name; +extern int hf_opcua_NamespaceUri; +extern int hf_opcua_NextSequenceNumber; +extern int hf_opcua_NotificationsCount; +extern int hf_opcua_NumValuesPerNode; +extern int hf_opcua_Offset; +extern int hf_opcua_OperandStatusCodes; +extern int hf_opcua_OperationResults; +extern int hf_opcua_OperationTimeout; +extern int hf_opcua_OrganizationUri; +extern int hf_opcua_Password; +extern int hf_opcua_PercentDataBad; +extern int hf_opcua_PercentDataGood; +extern int hf_opcua_PolicyId; +extern int hf_opcua_Priority; +extern int hf_opcua_ProcessingInterval; +extern int hf_opcua_ProductName; +extern int hf_opcua_ProductUri; +extern int hf_opcua_ProfileId; +extern int hf_opcua_ProfileUris; +extern int hf_opcua_PublishRequestCount; +extern int hf_opcua_PublishTime; +extern int hf_opcua_PublishingEnabled; +extern int hf_opcua_PublishingInterval; +extern int hf_opcua_PublishingIntervalCount; +extern int hf_opcua_QueueSize; +extern int hf_opcua_Real; +extern int hf_opcua_RecordId; +extern int hf_opcua_RejectedRequestsCount; +extern int hf_opcua_RejectedSessionCount; +extern int hf_opcua_ReleaseContinuationPoint; +extern int hf_opcua_ReleaseContinuationPoints; +extern int hf_opcua_RemainingPathIndex; +extern int hf_opcua_RemoveResults; +extern int hf_opcua_RepublishMessageCount; +extern int hf_opcua_RepublishMessageRequestCount; +extern int hf_opcua_RepublishRequestCount; +extern int hf_opcua_ReqTimes; +extern int hf_opcua_RequestHandle; +extern int hf_opcua_RequestedLifetime; +extern int hf_opcua_RequestedLifetimeCount; +extern int hf_opcua_RequestedMaxKeepAliveCount; +extern int hf_opcua_RequestedMaxReferencesPerNode; +extern int hf_opcua_RequestedPublishingInterval; +extern int hf_opcua_RequestedSessionTimeout; +extern int hf_opcua_Results; +extern int hf_opcua_RetransmitSequenceNumber; +extern int hf_opcua_ReturnBounds; +extern int hf_opcua_ReturnDiagnostics; +extern int hf_opcua_RevisedContinuationPoint; +extern int hf_opcua_RevisedLifetime; +extern int hf_opcua_RevisedLifetimeCount; +extern int hf_opcua_RevisedMaxKeepAliveCount; +extern int hf_opcua_RevisedProcessingInterval; +extern int hf_opcua_RevisedPublishingInterval; +extern int hf_opcua_RevisedQueueSize; +extern int hf_opcua_RevisedSamplingInterval; +extern int hf_opcua_RevisedSessionTimeout; +extern int hf_opcua_RevisedStartTime; +extern int hf_opcua_SByte; +extern int hf_opcua_SBytes; +extern int hf_opcua_SamplingInterval; +extern int hf_opcua_SecondsTillShutdown; +extern int hf_opcua_SecurityLevel; +extern int hf_opcua_SecurityPolicyUri; +extern int hf_opcua_SecurityRejectedRequestsCount; +extern int hf_opcua_SecurityRejectedSessionCount; +extern int hf_opcua_SecurityTokenLifetime; +extern int hf_opcua_SelectClauseResults; +extern int hf_opcua_SemaphoreFilePath; +extern int hf_opcua_SendInitialValues; +extern int hf_opcua_SequenceNumber; +extern int hf_opcua_ServerCapabilities; +extern int hf_opcua_ServerCapabilityFilter; +extern int hf_opcua_ServerCertificate; +extern int hf_opcua_ServerId; +extern int hf_opcua_ServerName; +extern int hf_opcua_ServerNonce; +extern int hf_opcua_ServerProtocolVersion; +extern int hf_opcua_ServerUri; +extern int hf_opcua_ServerUris; +extern int hf_opcua_ServerViewCount; +extern int hf_opcua_ServiceLevel; +extern int hf_opcua_ServiceResult; +extern int hf_opcua_SessionAbortCount; +extern int hf_opcua_SessionName; +extern int hf_opcua_SessionTimeoutCount; +extern int hf_opcua_Signature; +extern int hf_opcua_SoftwareVersion; +extern int hf_opcua_SpecifiedAttributes; +extern int hf_opcua_SpecifiedLists; +extern int hf_opcua_StartTime; +extern int hf_opcua_StartingRecordId; +extern int hf_opcua_Status; +extern int hf_opcua_StatusCode; +extern int hf_opcua_StatusCodes; +extern int hf_opcua_String; +extern int hf_opcua_StringTable; +extern int hf_opcua_Strings; +extern int hf_opcua_SubscriptionId; +extern int hf_opcua_SubscriptionIds; +extern int hf_opcua_Symmetric; +extern int hf_opcua_TargetServerUri; +extern int hf_opcua_TestId; +extern int hf_opcua_TicketData; +extern int hf_opcua_TimeoutHint; +extern int hf_opcua_Timestamp; +extern int hf_opcua_TokenData; +extern int hf_opcua_TokenId; +extern int hf_opcua_TotalCount; +extern int hf_opcua_TransferRequestCount; +extern int hf_opcua_TransferredToAltClientCount; +extern int hf_opcua_TransferredToSameClientCount; +extern int hf_opcua_TransportProfileUri; +extern int hf_opcua_TransportProtocol; +extern int hf_opcua_TreatUncertainAsBad; +extern int hf_opcua_TriggeringItemId; +extern int hf_opcua_TrustedCertificates; +extern int hf_opcua_TrustedCrls; +extern int hf_opcua_UInt16; +extern int hf_opcua_UInt16s; +extern int hf_opcua_UInt32; +extern int hf_opcua_UInt32s; +extern int hf_opcua_UInt64; +extern int hf_opcua_UInt64s; +extern int hf_opcua_UnacknowledgedMessageCount; +extern int hf_opcua_UnauthorizedRequestCount; +extern int hf_opcua_UnitId; +extern int hf_opcua_UnsupportedUnitIds; +extern int hf_opcua_UseBinaryEncoding; +extern int hf_opcua_UseServerCapabilitiesDefaults; +extern int hf_opcua_UseSimpleBounds; +extern int hf_opcua_UseSlopedExtrapolation; +extern int hf_opcua_UserAccessLevel; +extern int hf_opcua_UserExecutable; +extern int hf_opcua_UserName; +extern int hf_opcua_UserWriteMask; +extern int hf_opcua_ValidBits; +extern int hf_opcua_Value; +extern int hf_opcua_ValueRank; +extern int hf_opcua_VendorName; +extern int hf_opcua_VendorProductCertificate; +extern int hf_opcua_Verb; +extern int hf_opcua_ViewVersion; +extern int hf_opcua_WriteMask; +extern int hf_opcua_X; +extern int hf_opcua_XmlElement; +extern int hf_opcua_XmlElements; + +/** Register field types. */ +void registerFieldTypes(int proto); + diff --git a/plugins/epan/opcua/opcua_identifiers.h b/plugins/epan/opcua/opcua_identifiers.h new file mode 100644 index 00000000..2cff1b29 --- /dev/null +++ b/plugins/epan/opcua/opcua_identifiers.h @@ -0,0 +1,43 @@ +/****************************************************************************** +** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: Parser type definitions. +** +** This file was autogenerated on 6/10/2007 2:35:22 AM. +** DON'T MODIFY THIS FILE! +** XXX - well, except that you may have to. See the README. +** +******************************************************************************/ + +#include +#include + +/* declare service parser function prototype */ +typedef void (*fctServiceParser)(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +/* declare enum parser function prototype */ +typedef void (*fctEnumParser)(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +/* declare type parser function prototype */ +typedef void (*fctComplexTypeParser)(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +/* declare type parser function prototype */ +typedef proto_item* (*fctSimpleTypeParser)(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); + +typedef struct _ParserEntry +{ + int iRequestId; + fctServiceParser pParser; +} ParserEntry; + +typedef struct _ExtensionObjectParserEntry +{ + int iRequestId; + fctComplexTypeParser pParser; + const gchar *typeName; +} ExtensionObjectParserEntry; diff --git a/plugins/epan/opcua/opcua_security_layer.c b/plugins/epan/opcua/opcua_security_layer.c new file mode 100644 index 00000000..933fd981 --- /dev/null +++ b/plugins/epan/opcua/opcua_security_layer.c @@ -0,0 +1,60 @@ +/****************************************************************************** +** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Security Layer Decoder. +** +** Author: Gerhard Gappmeier +******************************************************************************/ + +#include "config.h" + +#include +#include "opcua_security_layer.h" + +static int hf_opcua_security_tokenid = -1; +static int hf_opcua_security_seq = -1; +static int hf_opcua_security_rqid = -1; + +/** Register security layer types. */ +void registerSecurityLayerTypes(int proto) +{ + static hf_register_info hf[] = + { + /* id full name abbreviation type display strings bitmask blurb HFILL */ + {&hf_opcua_security_tokenid, {"Security Token Id", "opcua.security.tokenid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_security_seq, {"Security Sequence Number", "opcua.security.seq", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_security_rqid, {"Security RequestId", "opcua.security.rqid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}} + }; + proto_register_field_array(proto, hf, array_length(hf)); +} + +/* Security Layer: message parsers + * Only works for Security Policy "NoSecurity" at the moment. + */ +void parseSecurityLayer(proto_tree *tree, tvbuff_t *tvb, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_security_tokenid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_security_seq, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_security_rqid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/opcua/opcua_security_layer.h b/plugins/epan/opcua/opcua_security_layer.h new file mode 100644 index 00000000..d5b36ce0 --- /dev/null +++ b/plugins/epan/opcua/opcua_security_layer.h @@ -0,0 +1,18 @@ +/****************************************************************************** +** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Security Layer Decoder. +** +** Author: Gerhard Gappmeier +******************************************************************************/ + +void registerSecurityLayerTypes(int proto); +void parseSecurityLayer(proto_tree *tree, tvbuff_t *tvb, gint *pOffset); diff --git a/plugins/epan/opcua/opcua_serviceids.h b/plugins/epan/opcua/opcua_serviceids.h new file mode 100644 index 00000000..9911a927 --- /dev/null +++ b/plugins/epan/opcua/opcua_serviceids.h @@ -0,0 +1,187 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Service IDs +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** XXX - well, except that you may have to. See the README. +** +******************************************************************************/ + +#define OpcUaId_ServiceFault_Encoding_DefaultBinary 397 +#define OpcUaId_FindServersRequest_Encoding_DefaultBinary 422 +#define OpcUaId_FindServersResponse_Encoding_DefaultBinary 425 +#define OpcUaId_FindServersOnNetworkRequest_Encoding_DefaultBinary 12208 +#define OpcUaId_FindServersOnNetworkResponse_Encoding_DefaultBinary 12209 +#define OpcUaId_GetEndpointsRequest_Encoding_DefaultBinary 428 +#define OpcUaId_GetEndpointsResponse_Encoding_DefaultBinary 431 +#define OpcUaId_RegisterServerRequest_Encoding_DefaultBinary 437 +#define OpcUaId_RegisterServerResponse_Encoding_DefaultBinary 440 +#define OpcUaId_RegisterServer2Request_Encoding_DefaultBinary 12211 +#define OpcUaId_RegisterServer2Response_Encoding_DefaultBinary 12212 +#define OpcUaId_OpenSecureChannelRequest_Encoding_DefaultBinary 446 +#define OpcUaId_OpenSecureChannelResponse_Encoding_DefaultBinary 449 +#define OpcUaId_CloseSecureChannelRequest_Encoding_DefaultBinary 452 +#define OpcUaId_CloseSecureChannelResponse_Encoding_DefaultBinary 455 +#define OpcUaId_CreateSessionRequest_Encoding_DefaultBinary 461 +#define OpcUaId_CreateSessionResponse_Encoding_DefaultBinary 464 +#define OpcUaId_ActivateSessionRequest_Encoding_DefaultBinary 467 +#define OpcUaId_ActivateSessionResponse_Encoding_DefaultBinary 470 +#define OpcUaId_CloseSessionRequest_Encoding_DefaultBinary 473 +#define OpcUaId_CloseSessionResponse_Encoding_DefaultBinary 476 +#define OpcUaId_CancelRequest_Encoding_DefaultBinary 479 +#define OpcUaId_CancelResponse_Encoding_DefaultBinary 482 +#define OpcUaId_AddNodesRequest_Encoding_DefaultBinary 488 +#define OpcUaId_AddNodesResponse_Encoding_DefaultBinary 491 +#define OpcUaId_AddReferencesRequest_Encoding_DefaultBinary 494 +#define OpcUaId_AddReferencesResponse_Encoding_DefaultBinary 497 +#define OpcUaId_DeleteNodesRequest_Encoding_DefaultBinary 500 +#define OpcUaId_DeleteNodesResponse_Encoding_DefaultBinary 503 +#define OpcUaId_DeleteReferencesRequest_Encoding_DefaultBinary 506 +#define OpcUaId_DeleteReferencesResponse_Encoding_DefaultBinary 509 +#define OpcUaId_BrowseRequest_Encoding_DefaultBinary 527 +#define OpcUaId_BrowseResponse_Encoding_DefaultBinary 530 +#define OpcUaId_BrowseNextRequest_Encoding_DefaultBinary 533 +#define OpcUaId_BrowseNextResponse_Encoding_DefaultBinary 536 +#define OpcUaId_TranslateBrowsePathsToNodeIdsRequest_Encoding_DefaultBinary 554 +#define OpcUaId_TranslateBrowsePathsToNodeIdsResponse_Encoding_DefaultBinary 557 +#define OpcUaId_RegisterNodesRequest_Encoding_DefaultBinary 560 +#define OpcUaId_RegisterNodesResponse_Encoding_DefaultBinary 563 +#define OpcUaId_UnregisterNodesRequest_Encoding_DefaultBinary 566 +#define OpcUaId_UnregisterNodesResponse_Encoding_DefaultBinary 569 +#define OpcUaId_QueryFirstRequest_Encoding_DefaultBinary 615 +#define OpcUaId_QueryFirstResponse_Encoding_DefaultBinary 618 +#define OpcUaId_QueryNextRequest_Encoding_DefaultBinary 621 +#define OpcUaId_QueryNextResponse_Encoding_DefaultBinary 624 +#define OpcUaId_ReadRequest_Encoding_DefaultBinary 631 +#define OpcUaId_ReadResponse_Encoding_DefaultBinary 634 +#define OpcUaId_HistoryReadRequest_Encoding_DefaultBinary 664 +#define OpcUaId_HistoryReadResponse_Encoding_DefaultBinary 667 +#define OpcUaId_WriteRequest_Encoding_DefaultBinary 673 +#define OpcUaId_WriteResponse_Encoding_DefaultBinary 676 +#define OpcUaId_HistoryUpdateRequest_Encoding_DefaultBinary 700 +#define OpcUaId_HistoryUpdateResponse_Encoding_DefaultBinary 703 +#define OpcUaId_CallRequest_Encoding_DefaultBinary 712 +#define OpcUaId_CallResponse_Encoding_DefaultBinary 715 +#define OpcUaId_CreateMonitoredItemsRequest_Encoding_DefaultBinary 751 +#define OpcUaId_CreateMonitoredItemsResponse_Encoding_DefaultBinary 754 +#define OpcUaId_ModifyMonitoredItemsRequest_Encoding_DefaultBinary 763 +#define OpcUaId_ModifyMonitoredItemsResponse_Encoding_DefaultBinary 766 +#define OpcUaId_SetMonitoringModeRequest_Encoding_DefaultBinary 769 +#define OpcUaId_SetMonitoringModeResponse_Encoding_DefaultBinary 772 +#define OpcUaId_SetTriggeringRequest_Encoding_DefaultBinary 775 +#define OpcUaId_SetTriggeringResponse_Encoding_DefaultBinary 778 +#define OpcUaId_DeleteMonitoredItemsRequest_Encoding_DefaultBinary 781 +#define OpcUaId_DeleteMonitoredItemsResponse_Encoding_DefaultBinary 784 +#define OpcUaId_CreateSubscriptionRequest_Encoding_DefaultBinary 787 +#define OpcUaId_CreateSubscriptionResponse_Encoding_DefaultBinary 790 +#define OpcUaId_ModifySubscriptionRequest_Encoding_DefaultBinary 793 +#define OpcUaId_ModifySubscriptionResponse_Encoding_DefaultBinary 796 +#define OpcUaId_SetPublishingModeRequest_Encoding_DefaultBinary 799 +#define OpcUaId_SetPublishingModeResponse_Encoding_DefaultBinary 802 +#define OpcUaId_PublishRequest_Encoding_DefaultBinary 826 +#define OpcUaId_PublishResponse_Encoding_DefaultBinary 829 +#define OpcUaId_RepublishRequest_Encoding_DefaultBinary 832 +#define OpcUaId_RepublishResponse_Encoding_DefaultBinary 835 +#define OpcUaId_TransferSubscriptionsRequest_Encoding_DefaultBinary 841 +#define OpcUaId_TransferSubscriptionsResponse_Encoding_DefaultBinary 844 +#define OpcUaId_DeleteSubscriptionsRequest_Encoding_DefaultBinary 847 +#define OpcUaId_DeleteSubscriptionsResponse_Encoding_DefaultBinary 850 +#define OpcUaId_TestStackRequest_Encoding_DefaultBinary 410 +#define OpcUaId_TestStackResponse_Encoding_DefaultBinary 413 +#define OpcUaId_TestStackExRequest_Encoding_DefaultBinary 416 +#define OpcUaId_TestStackExResponse_Encoding_DefaultBinary 419 + +#define OpcUaId_ServiceFault_Encoding_DefaultXml 396 +#define OpcUaId_FindServersRequest_Encoding_DefaultXml 421 +#define OpcUaId_FindServersResponse_Encoding_DefaultXml 424 +#define OpcUaId_FindServersOnNetworkRequest_Encoding_DefaultXml 12196 +#define OpcUaId_FindServersOnNetworkResponse_Encoding_DefaultXml 12197 +#define OpcUaId_GetEndpointsRequest_Encoding_DefaultXml 427 +#define OpcUaId_GetEndpointsResponse_Encoding_DefaultXml 430 +#define OpcUaId_RegisterServerRequest_Encoding_DefaultXml 436 +#define OpcUaId_RegisterServerResponse_Encoding_DefaultXml 439 +#define OpcUaId_RegisterServer2Request_Encoding_DefaultXml 12199 +#define OpcUaId_RegisterServer2Response_Encoding_DefaultXml 12200 +#define OpcUaId_OpenSecureChannelRequest_Encoding_DefaultXml 445 +#define OpcUaId_OpenSecureChannelResponse_Encoding_DefaultXml 448 +#define OpcUaId_CloseSecureChannelRequest_Encoding_DefaultXml 451 +#define OpcUaId_CloseSecureChannelResponse_Encoding_DefaultXml 454 +#define OpcUaId_CreateSessionRequest_Encoding_DefaultXml 460 +#define OpcUaId_CreateSessionResponse_Encoding_DefaultXml 463 +#define OpcUaId_ActivateSessionRequest_Encoding_DefaultXml 466 +#define OpcUaId_ActivateSessionResponse_Encoding_DefaultXml 469 +#define OpcUaId_CloseSessionRequest_Encoding_DefaultXml 472 +#define OpcUaId_CloseSessionResponse_Encoding_DefaultXml 475 +#define OpcUaId_CancelRequest_Encoding_DefaultXml 478 +#define OpcUaId_CancelResponse_Encoding_DefaultXml 481 +#define OpcUaId_AddNodesRequest_Encoding_DefaultXml 487 +#define OpcUaId_AddNodesResponse_Encoding_DefaultXml 490 +#define OpcUaId_AddReferencesRequest_Encoding_DefaultXml 493 +#define OpcUaId_AddReferencesResponse_Encoding_DefaultXml 496 +#define OpcUaId_DeleteNodesRequest_Encoding_DefaultXml 499 +#define OpcUaId_DeleteNodesResponse_Encoding_DefaultXml 502 +#define OpcUaId_DeleteReferencesRequest_Encoding_DefaultXml 505 +#define OpcUaId_DeleteReferencesResponse_Encoding_DefaultXml 508 +#define OpcUaId_BrowseRequest_Encoding_DefaultXml 526 +#define OpcUaId_BrowseResponse_Encoding_DefaultXml 529 +#define OpcUaId_BrowseNextRequest_Encoding_DefaultXml 532 +#define OpcUaId_BrowseNextResponse_Encoding_DefaultXml 535 +#define OpcUaId_TranslateBrowsePathsToNodeIdsRequest_Encoding_DefaultXml 553 +#define OpcUaId_TranslateBrowsePathsToNodeIdsResponse_Encoding_DefaultXml 556 +#define OpcUaId_RegisterNodesRequest_Encoding_DefaultXml 559 +#define OpcUaId_RegisterNodesResponse_Encoding_DefaultXml 562 +#define OpcUaId_UnregisterNodesRequest_Encoding_DefaultXml 565 +#define OpcUaId_UnregisterNodesResponse_Encoding_DefaultXml 568 +#define OpcUaId_QueryFirstRequest_Encoding_DefaultXml 614 +#define OpcUaId_QueryFirstResponse_Encoding_DefaultXml 617 +#define OpcUaId_QueryNextRequest_Encoding_DefaultXml 620 +#define OpcUaId_QueryNextResponse_Encoding_DefaultXml 623 +#define OpcUaId_ReadRequest_Encoding_DefaultXml 630 +#define OpcUaId_ReadResponse_Encoding_DefaultXml 633 +#define OpcUaId_HistoryReadRequest_Encoding_DefaultXml 663 +#define OpcUaId_HistoryReadResponse_Encoding_DefaultXml 666 +#define OpcUaId_WriteRequest_Encoding_DefaultXml 672 +#define OpcUaId_WriteResponse_Encoding_DefaultXml 675 +#define OpcUaId_HistoryUpdateRequest_Encoding_DefaultXml 699 +#define OpcUaId_HistoryUpdateResponse_Encoding_DefaultXml 702 +#define OpcUaId_CallRequest_Encoding_DefaultXml 711 +#define OpcUaId_CallResponse_Encoding_DefaultXml 714 +#define OpcUaId_CreateMonitoredItemsRequest_Encoding_DefaultXml 750 +#define OpcUaId_CreateMonitoredItemsResponse_Encoding_DefaultXml 753 +#define OpcUaId_ModifyMonitoredItemsRequest_Encoding_DefaultXml 762 +#define OpcUaId_ModifyMonitoredItemsResponse_Encoding_DefaultXml 765 +#define OpcUaId_SetMonitoringModeRequest_Encoding_DefaultXml 768 +#define OpcUaId_SetMonitoringModeResponse_Encoding_DefaultXml 771 +#define OpcUaId_SetTriggeringRequest_Encoding_DefaultXml 774 +#define OpcUaId_SetTriggeringResponse_Encoding_DefaultXml 777 +#define OpcUaId_DeleteMonitoredItemsRequest_Encoding_DefaultXml 780 +#define OpcUaId_DeleteMonitoredItemsResponse_Encoding_DefaultXml 783 +#define OpcUaId_CreateSubscriptionRequest_Encoding_DefaultXml 786 +#define OpcUaId_CreateSubscriptionResponse_Encoding_DefaultXml 789 +#define OpcUaId_ModifySubscriptionRequest_Encoding_DefaultXml 792 +#define OpcUaId_ModifySubscriptionResponse_Encoding_DefaultXml 795 +#define OpcUaId_SetPublishingModeRequest_Encoding_DefaultXml 798 +#define OpcUaId_SetPublishingModeResponse_Encoding_DefaultXml 801 +#define OpcUaId_PublishRequest_Encoding_DefaultXml 825 +#define OpcUaId_PublishResponse_Encoding_DefaultXml 828 +#define OpcUaId_RepublishRequest_Encoding_DefaultXml 831 +#define OpcUaId_RepublishResponse_Encoding_DefaultXml 834 +#define OpcUaId_TransferSubscriptionsRequest_Encoding_DefaultXml 840 +#define OpcUaId_TransferSubscriptionsResponse_Encoding_DefaultXml 843 +#define OpcUaId_DeleteSubscriptionsRequest_Encoding_DefaultXml 846 +#define OpcUaId_DeleteSubscriptionsResponse_Encoding_DefaultXml 849 +#define OpcUaId_TestStackRequest_Encoding_DefaultXml 409 +#define OpcUaId_TestStackResponse_Encoding_DefaultXml 412 +#define OpcUaId_TestStackExRequest_Encoding_DefaultXml 415 +#define OpcUaId_TestStackExResponse_Encoding_DefaultXml 418 + diff --git a/plugins/epan/opcua/opcua_serviceparser.c b/plugins/epan/opcua/opcua_serviceparser.c new file mode 100644 index 00000000..d71b6781 --- /dev/null +++ b/plugins/epan/opcua/opcua_serviceparser.c @@ -0,0 +1,1317 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Complex Type Parser +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** +******************************************************************************/ + +#include "config.h" + +#include +#include "opcua_complextypeparser.h" +#include "opcua_enumparser.h" +#include "opcua_simpletypes.h" +#include "opcua_hfindeces.h" +#include "opcua_serviceparser.h" + +gint ett_opcua_ServiceFault = -1; +gint ett_opcua_array_ServiceFault = -1; +gint ett_opcua_FindServersRequest = -1; +gint ett_opcua_array_FindServersRequest = -1; +gint ett_opcua_FindServersResponse = -1; +gint ett_opcua_array_FindServersResponse = -1; +gint ett_opcua_FindServersOnNetworkRequest = -1; +gint ett_opcua_array_FindServersOnNetworkRequest = -1; +gint ett_opcua_FindServersOnNetworkResponse = -1; +gint ett_opcua_array_FindServersOnNetworkResponse = -1; +gint ett_opcua_GetEndpointsRequest = -1; +gint ett_opcua_array_GetEndpointsRequest = -1; +gint ett_opcua_GetEndpointsResponse = -1; +gint ett_opcua_array_GetEndpointsResponse = -1; +gint ett_opcua_RegisterServerRequest = -1; +gint ett_opcua_array_RegisterServerRequest = -1; +gint ett_opcua_RegisterServerResponse = -1; +gint ett_opcua_array_RegisterServerResponse = -1; +gint ett_opcua_RegisterServer2Request = -1; +gint ett_opcua_array_RegisterServer2Request = -1; +gint ett_opcua_RegisterServer2Response = -1; +gint ett_opcua_array_RegisterServer2Response = -1; +gint ett_opcua_OpenSecureChannelRequest = -1; +gint ett_opcua_array_OpenSecureChannelRequest = -1; +gint ett_opcua_OpenSecureChannelResponse = -1; +gint ett_opcua_array_OpenSecureChannelResponse = -1; +gint ett_opcua_CloseSecureChannelRequest = -1; +gint ett_opcua_array_CloseSecureChannelRequest = -1; +gint ett_opcua_CloseSecureChannelResponse = -1; +gint ett_opcua_array_CloseSecureChannelResponse = -1; +gint ett_opcua_CreateSessionRequest = -1; +gint ett_opcua_array_CreateSessionRequest = -1; +gint ett_opcua_CreateSessionResponse = -1; +gint ett_opcua_array_CreateSessionResponse = -1; +gint ett_opcua_ActivateSessionRequest = -1; +gint ett_opcua_array_ActivateSessionRequest = -1; +gint ett_opcua_ActivateSessionResponse = -1; +gint ett_opcua_array_ActivateSessionResponse = -1; +gint ett_opcua_CloseSessionRequest = -1; +gint ett_opcua_array_CloseSessionRequest = -1; +gint ett_opcua_CloseSessionResponse = -1; +gint ett_opcua_array_CloseSessionResponse = -1; +gint ett_opcua_CancelRequest = -1; +gint ett_opcua_array_CancelRequest = -1; +gint ett_opcua_CancelResponse = -1; +gint ett_opcua_array_CancelResponse = -1; +gint ett_opcua_AddNodesRequest = -1; +gint ett_opcua_array_AddNodesRequest = -1; +gint ett_opcua_AddNodesResponse = -1; +gint ett_opcua_array_AddNodesResponse = -1; +gint ett_opcua_AddReferencesRequest = -1; +gint ett_opcua_array_AddReferencesRequest = -1; +gint ett_opcua_AddReferencesResponse = -1; +gint ett_opcua_array_AddReferencesResponse = -1; +gint ett_opcua_DeleteNodesRequest = -1; +gint ett_opcua_array_DeleteNodesRequest = -1; +gint ett_opcua_DeleteNodesResponse = -1; +gint ett_opcua_array_DeleteNodesResponse = -1; +gint ett_opcua_DeleteReferencesRequest = -1; +gint ett_opcua_array_DeleteReferencesRequest = -1; +gint ett_opcua_DeleteReferencesResponse = -1; +gint ett_opcua_array_DeleteReferencesResponse = -1; +gint ett_opcua_BrowseRequest = -1; +gint ett_opcua_array_BrowseRequest = -1; +gint ett_opcua_BrowseResponse = -1; +gint ett_opcua_array_BrowseResponse = -1; +gint ett_opcua_BrowseNextRequest = -1; +gint ett_opcua_array_BrowseNextRequest = -1; +gint ett_opcua_BrowseNextResponse = -1; +gint ett_opcua_array_BrowseNextResponse = -1; +gint ett_opcua_TranslateBrowsePathsToNodeIdsRequest = -1; +gint ett_opcua_array_TranslateBrowsePathsToNodeIdsRequest = -1; +gint ett_opcua_TranslateBrowsePathsToNodeIdsResponse = -1; +gint ett_opcua_array_TranslateBrowsePathsToNodeIdsResponse = -1; +gint ett_opcua_RegisterNodesRequest = -1; +gint ett_opcua_array_RegisterNodesRequest = -1; +gint ett_opcua_RegisterNodesResponse = -1; +gint ett_opcua_array_RegisterNodesResponse = -1; +gint ett_opcua_UnregisterNodesRequest = -1; +gint ett_opcua_array_UnregisterNodesRequest = -1; +gint ett_opcua_UnregisterNodesResponse = -1; +gint ett_opcua_array_UnregisterNodesResponse = -1; +gint ett_opcua_QueryFirstRequest = -1; +gint ett_opcua_array_QueryFirstRequest = -1; +gint ett_opcua_QueryFirstResponse = -1; +gint ett_opcua_array_QueryFirstResponse = -1; +gint ett_opcua_QueryNextRequest = -1; +gint ett_opcua_array_QueryNextRequest = -1; +gint ett_opcua_QueryNextResponse = -1; +gint ett_opcua_array_QueryNextResponse = -1; +gint ett_opcua_ReadRequest = -1; +gint ett_opcua_array_ReadRequest = -1; +gint ett_opcua_ReadResponse = -1; +gint ett_opcua_array_ReadResponse = -1; +gint ett_opcua_HistoryReadRequest = -1; +gint ett_opcua_array_HistoryReadRequest = -1; +gint ett_opcua_HistoryReadResponse = -1; +gint ett_opcua_array_HistoryReadResponse = -1; +gint ett_opcua_WriteRequest = -1; +gint ett_opcua_array_WriteRequest = -1; +gint ett_opcua_WriteResponse = -1; +gint ett_opcua_array_WriteResponse = -1; +gint ett_opcua_HistoryUpdateRequest = -1; +gint ett_opcua_array_HistoryUpdateRequest = -1; +gint ett_opcua_HistoryUpdateResponse = -1; +gint ett_opcua_array_HistoryUpdateResponse = -1; +gint ett_opcua_CallRequest = -1; +gint ett_opcua_array_CallRequest = -1; +gint ett_opcua_CallResponse = -1; +gint ett_opcua_array_CallResponse = -1; +gint ett_opcua_CreateMonitoredItemsRequest = -1; +gint ett_opcua_array_CreateMonitoredItemsRequest = -1; +gint ett_opcua_CreateMonitoredItemsResponse = -1; +gint ett_opcua_array_CreateMonitoredItemsResponse = -1; +gint ett_opcua_ModifyMonitoredItemsRequest = -1; +gint ett_opcua_array_ModifyMonitoredItemsRequest = -1; +gint ett_opcua_ModifyMonitoredItemsResponse = -1; +gint ett_opcua_array_ModifyMonitoredItemsResponse = -1; +gint ett_opcua_SetMonitoringModeRequest = -1; +gint ett_opcua_array_SetMonitoringModeRequest = -1; +gint ett_opcua_SetMonitoringModeResponse = -1; +gint ett_opcua_array_SetMonitoringModeResponse = -1; +gint ett_opcua_SetTriggeringRequest = -1; +gint ett_opcua_array_SetTriggeringRequest = -1; +gint ett_opcua_SetTriggeringResponse = -1; +gint ett_opcua_array_SetTriggeringResponse = -1; +gint ett_opcua_DeleteMonitoredItemsRequest = -1; +gint ett_opcua_array_DeleteMonitoredItemsRequest = -1; +gint ett_opcua_DeleteMonitoredItemsResponse = -1; +gint ett_opcua_array_DeleteMonitoredItemsResponse = -1; +gint ett_opcua_CreateSubscriptionRequest = -1; +gint ett_opcua_array_CreateSubscriptionRequest = -1; +gint ett_opcua_CreateSubscriptionResponse = -1; +gint ett_opcua_array_CreateSubscriptionResponse = -1; +gint ett_opcua_ModifySubscriptionRequest = -1; +gint ett_opcua_array_ModifySubscriptionRequest = -1; +gint ett_opcua_ModifySubscriptionResponse = -1; +gint ett_opcua_array_ModifySubscriptionResponse = -1; +gint ett_opcua_SetPublishingModeRequest = -1; +gint ett_opcua_array_SetPublishingModeRequest = -1; +gint ett_opcua_SetPublishingModeResponse = -1; +gint ett_opcua_array_SetPublishingModeResponse = -1; +gint ett_opcua_PublishRequest = -1; +gint ett_opcua_array_PublishRequest = -1; +gint ett_opcua_PublishResponse = -1; +gint ett_opcua_array_PublishResponse = -1; +gint ett_opcua_RepublishRequest = -1; +gint ett_opcua_array_RepublishRequest = -1; +gint ett_opcua_RepublishResponse = -1; +gint ett_opcua_array_RepublishResponse = -1; +gint ett_opcua_TransferSubscriptionsRequest = -1; +gint ett_opcua_array_TransferSubscriptionsRequest = -1; +gint ett_opcua_TransferSubscriptionsResponse = -1; +gint ett_opcua_array_TransferSubscriptionsResponse = -1; +gint ett_opcua_DeleteSubscriptionsRequest = -1; +gint ett_opcua_array_DeleteSubscriptionsRequest = -1; +gint ett_opcua_DeleteSubscriptionsResponse = -1; +gint ett_opcua_array_DeleteSubscriptionsResponse = -1; +gint ett_opcua_TestStackRequest = -1; +gint ett_opcua_array_TestStackRequest = -1; +gint ett_opcua_TestStackResponse = -1; +gint ett_opcua_array_TestStackResponse = -1; +gint ett_opcua_TestStackExRequest = -1; +gint ett_opcua_array_TestStackExRequest = -1; +gint ett_opcua_TestStackExResponse = -1; +gint ett_opcua_array_TestStackExResponse = -1; + +void parseServiceFault(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ServiceFault, &ti, "ServiceFault"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseFindServersRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_FindServersRequest, &ti, "FindServersRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_EndpointUrl); + /* Array length field ignored: NoOfLocaleIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "LocaleIds", "String", hf_opcua_LocaleIds, parseString, ett_opcua_array_String); + /* Array length field ignored: NoOfServerUris */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ServerUris", "String", hf_opcua_ServerUris, parseString, ett_opcua_array_String); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseFindServersResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_FindServersResponse, &ti, "FindServersResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfServers */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Servers", "ApplicationDescription", parseApplicationDescription, ett_opcua_array_ApplicationDescription); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseFindServersOnNetworkRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_FindServersOnNetworkRequest, &ti, "FindServersOnNetworkRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_StartingRecordId); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxRecordsToReturn); + /* Array length field ignored: NoOfServerCapabilityFilter */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ServerCapabilityFilter", "String", hf_opcua_ServerCapabilityFilter, parseString, ett_opcua_array_String); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseFindServersOnNetworkResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_FindServersOnNetworkResponse, &ti, "FindServersOnNetworkResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseDateTime(subtree, tvb, pinfo, pOffset, hf_opcua_LastCounterResetTime); + /* Array length field ignored: NoOfServers */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Servers", "ServerOnNetwork", parseServerOnNetwork, ett_opcua_array_ServerOnNetwork); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseGetEndpointsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_GetEndpointsRequest, &ti, "GetEndpointsRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_EndpointUrl); + /* Array length field ignored: NoOfLocaleIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "LocaleIds", "String", hf_opcua_LocaleIds, parseString, ett_opcua_array_String); + /* Array length field ignored: NoOfProfileUris */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ProfileUris", "String", hf_opcua_ProfileUris, parseString, ett_opcua_array_String); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseGetEndpointsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_GetEndpointsResponse, &ti, "GetEndpointsResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfEndpoints */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Endpoints", "EndpointDescription", parseEndpointDescription, ett_opcua_array_EndpointDescription); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRegisterServerRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_RegisterServerRequest, &ti, "RegisterServerRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseRegisteredServer(subtree, tvb, pinfo, pOffset, "Server"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRegisterServerResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_RegisterServerResponse, &ti, "RegisterServerResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRegisterServer2Request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_RegisterServer2Request, &ti, "RegisterServer2Request"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseRegisteredServer(subtree, tvb, pinfo, pOffset, "Server"); + /* Array length field ignored: NoOfDiscoveryConfiguration */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiscoveryConfiguration", "ExtensionObject", parseExtensionObject, ett_opcua_array_ExtensionObject); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRegisterServer2Response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_RegisterServer2Response, &ti, "RegisterServer2Response"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfConfigurationResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ConfigurationResults", "StatusCode", hf_opcua_ConfigurationResults, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseOpenSecureChannelRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_OpenSecureChannelRequest, &ti, "OpenSecureChannelRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ClientProtocolVersion); + parseSecurityTokenRequestType(subtree, tvb, pinfo, pOffset); + parseMessageSecurityMode(subtree, tvb, pinfo, pOffset); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ClientNonce); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedLifetime); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseOpenSecureChannelResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_OpenSecureChannelResponse, &ti, "OpenSecureChannelResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_ServerProtocolVersion); + parseChannelSecurityToken(subtree, tvb, pinfo, pOffset, "SecurityToken"); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerNonce); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCloseSecureChannelRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CloseSecureChannelRequest, &ti, "CloseSecureChannelRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCloseSecureChannelResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CloseSecureChannelResponse, &ti, "CloseSecureChannelResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCreateSessionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CreateSessionRequest, &ti, "CreateSessionRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseApplicationDescription(subtree, tvb, pinfo, pOffset, "ClientDescription"); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerUri); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_EndpointUrl); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_SessionName); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ClientNonce); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ClientCertificate); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedSessionTimeout); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxResponseMessageSize); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCreateSessionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CreateSessionResponse, &ti, "CreateSessionResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseNodeId(subtree, tvb, pinfo, pOffset, "SessionId"); + parseNodeId(subtree, tvb, pinfo, pOffset, "AuthenticationToken"); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedSessionTimeout); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerNonce); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerCertificate); + /* Array length field ignored: NoOfServerEndpoints */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ServerEndpoints", "EndpointDescription", parseEndpointDescription, ett_opcua_array_EndpointDescription); + /* Array length field ignored: NoOfServerSoftwareCertificates */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ServerSoftwareCertificates", "SignedSoftwareCertificate", parseSignedSoftwareCertificate, ett_opcua_array_SignedSoftwareCertificate); + parseSignatureData(subtree, tvb, pinfo, pOffset, "ServerSignature"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxRequestMessageSize); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseActivateSessionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ActivateSessionRequest, &ti, "ActivateSessionRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseSignatureData(subtree, tvb, pinfo, pOffset, "ClientSignature"); + /* Array length field ignored: NoOfClientSoftwareCertificates */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ClientSoftwareCertificates", "SignedSoftwareCertificate", parseSignedSoftwareCertificate, ett_opcua_array_SignedSoftwareCertificate); + /* Array length field ignored: NoOfLocaleIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "LocaleIds", "String", hf_opcua_LocaleIds, parseString, ett_opcua_array_String); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "UserIdentityToken"); + parseSignatureData(subtree, tvb, pinfo, pOffset, "UserTokenSignature"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseActivateSessionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ActivateSessionResponse, &ti, "ActivateSessionResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ServerNonce); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCloseSessionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CloseSessionRequest, &ti, "CloseSessionRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_DeleteSubscriptions); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCloseSessionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CloseSessionResponse, &ti, "CloseSessionResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCancelRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CancelRequest, &ti, "CancelRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestHandle); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCancelResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CancelResponse, &ti, "CancelResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_CancelCount); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAddNodesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_AddNodesRequest, &ti, "AddNodesRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfNodesToAdd */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodesToAdd", "AddNodesItem", parseAddNodesItem, ett_opcua_array_AddNodesItem); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAddNodesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_AddNodesResponse, &ti, "AddNodesResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "AddNodesResult", parseAddNodesResult, ett_opcua_array_AddNodesResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAddReferencesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_AddReferencesRequest, &ti, "AddReferencesRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfReferencesToAdd */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ReferencesToAdd", "AddReferencesItem", parseAddReferencesItem, ett_opcua_array_AddReferencesItem); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseAddReferencesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_AddReferencesResponse, &ti, "AddReferencesResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteNodesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_DeleteNodesRequest, &ti, "DeleteNodesRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfNodesToDelete */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodesToDelete", "DeleteNodesItem", parseDeleteNodesItem, ett_opcua_array_DeleteNodesItem); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteNodesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_DeleteNodesResponse, &ti, "DeleteNodesResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteReferencesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_DeleteReferencesRequest, &ti, "DeleteReferencesRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfReferencesToDelete */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ReferencesToDelete", "DeleteReferencesItem", parseDeleteReferencesItem, ett_opcua_array_DeleteReferencesItem); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteReferencesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_DeleteReferencesResponse, &ti, "DeleteReferencesResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowseRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_BrowseRequest, &ti, "BrowseRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseViewDescription(subtree, tvb, pinfo, pOffset, "View"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedMaxReferencesPerNode); + /* Array length field ignored: NoOfNodesToBrowse */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodesToBrowse", "BrowseDescription", parseBrowseDescription, ett_opcua_array_BrowseDescription); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowseResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_BrowseResponse, &ti, "BrowseResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "BrowseResult", parseBrowseResult, ett_opcua_array_BrowseResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowseNextRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_BrowseNextRequest, &ti, "BrowseNextRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_ReleaseContinuationPoints); + /* Array length field ignored: NoOfContinuationPoints */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "ContinuationPoints", "ByteString", hf_opcua_ContinuationPoints, parseByteString, ett_opcua_array_ByteString); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseBrowseNextResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_BrowseNextResponse, &ti, "BrowseNextResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "BrowseResult", parseBrowseResult, ett_opcua_array_BrowseResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTranslateBrowsePathsToNodeIdsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_TranslateBrowsePathsToNodeIdsRequest, &ti, "TranslateBrowsePathsToNodeIdsRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfBrowsePaths */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "BrowsePaths", "BrowsePath", parseBrowsePath, ett_opcua_array_BrowsePath); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTranslateBrowsePathsToNodeIdsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_TranslateBrowsePathsToNodeIdsResponse, &ti, "TranslateBrowsePathsToNodeIdsResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "BrowsePathResult", parseBrowsePathResult, ett_opcua_array_BrowsePathResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRegisterNodesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_RegisterNodesRequest, &ti, "RegisterNodesRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfNodesToRegister */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodesToRegister", "NodeId", parseNodeId, ett_opcua_array_NodeId); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRegisterNodesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_RegisterNodesResponse, &ti, "RegisterNodesResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfRegisteredNodeIds */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "RegisteredNodeIds", "NodeId", parseNodeId, ett_opcua_array_NodeId); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseUnregisterNodesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_UnregisterNodesRequest, &ti, "UnregisterNodesRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfNodesToUnregister */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodesToUnregister", "NodeId", parseNodeId, ett_opcua_array_NodeId); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseUnregisterNodesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_UnregisterNodesResponse, &ti, "UnregisterNodesResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseQueryFirstRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_QueryFirstRequest, &ti, "QueryFirstRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseViewDescription(subtree, tvb, pinfo, pOffset, "View"); + /* Array length field ignored: NoOfNodeTypes */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodeTypes", "NodeTypeDescription", parseNodeTypeDescription, ett_opcua_array_NodeTypeDescription); + parseContentFilter(subtree, tvb, pinfo, pOffset, "Filter"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxDataSetsToReturn); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxReferencesToReturn); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseQueryFirstResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_QueryFirstResponse, &ti, "QueryFirstResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfQueryDataSets */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "QueryDataSets", "QueryDataSet", parseQueryDataSet, ett_opcua_array_QueryDataSet); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ContinuationPoint); + /* Array length field ignored: NoOfParsingResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ParsingResults", "ParsingResult", parseParsingResult, ett_opcua_array_ParsingResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + parseContentFilterResult(subtree, tvb, pinfo, pOffset, "FilterResult"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseQueryNextRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_QueryNextRequest, &ti, "QueryNextRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_ReleaseContinuationPoint); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_ContinuationPoint); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseQueryNextResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_QueryNextResponse, &ti, "QueryNextResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfQueryDataSets */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "QueryDataSets", "QueryDataSet", parseQueryDataSet, ett_opcua_array_QueryDataSet); + parseByteString(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedContinuationPoint); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReadRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ReadRequest, &ti, "ReadRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_MaxAge); + parseTimestampsToReturn(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfNodesToRead */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodesToRead", "ReadValueId", parseReadValueId, ett_opcua_array_ReadValueId); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseReadResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ReadResponse, &ti, "ReadResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "DataValue", parseDataValue, ett_opcua_array_DataValue); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryReadRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_HistoryReadRequest, &ti, "HistoryReadRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseExtensionObject(subtree, tvb, pinfo, pOffset, "HistoryReadDetails"); + parseTimestampsToReturn(subtree, tvb, pinfo, pOffset); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_ReleaseContinuationPoints); + /* Array length field ignored: NoOfNodesToRead */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodesToRead", "HistoryReadValueId", parseHistoryReadValueId, ett_opcua_array_HistoryReadValueId); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryReadResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_HistoryReadResponse, &ti, "HistoryReadResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "HistoryReadResult", parseHistoryReadResult, ett_opcua_array_HistoryReadResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseWriteRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_WriteRequest, &ti, "WriteRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfNodesToWrite */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "NodesToWrite", "WriteValue", parseWriteValue, ett_opcua_array_WriteValue); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseWriteResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_WriteResponse, &ti, "WriteResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryUpdateRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_HistoryUpdateRequest, &ti, "HistoryUpdateRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfHistoryUpdateDetails */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "HistoryUpdateDetails", "ExtensionObject", parseExtensionObject, ett_opcua_array_ExtensionObject); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseHistoryUpdateResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_HistoryUpdateResponse, &ti, "HistoryUpdateResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "HistoryUpdateResult", parseHistoryUpdateResult, ett_opcua_array_HistoryUpdateResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCallRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CallRequest, &ti, "CallRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfMethodsToCall */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "MethodsToCall", "CallMethodRequest", parseCallMethodRequest, ett_opcua_array_CallMethodRequest); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCallResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CallResponse, &ti, "CallResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "CallMethodResult", parseCallMethodResult, ett_opcua_array_CallMethodResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCreateMonitoredItemsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CreateMonitoredItemsRequest, &ti, "CreateMonitoredItemsRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseTimestampsToReturn(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfItemsToCreate */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ItemsToCreate", "MonitoredItemCreateRequest", parseMonitoredItemCreateRequest, ett_opcua_array_MonitoredItemCreateRequest); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCreateMonitoredItemsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CreateMonitoredItemsResponse, &ti, "CreateMonitoredItemsResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "MonitoredItemCreateResult", parseMonitoredItemCreateResult, ett_opcua_array_MonitoredItemCreateResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseModifyMonitoredItemsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ModifyMonitoredItemsRequest, &ti, "ModifyMonitoredItemsRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseTimestampsToReturn(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfItemsToModify */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "ItemsToModify", "MonitoredItemModifyRequest", parseMonitoredItemModifyRequest, ett_opcua_array_MonitoredItemModifyRequest); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseModifyMonitoredItemsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ModifyMonitoredItemsResponse, &ti, "ModifyMonitoredItemsResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "MonitoredItemModifyResult", parseMonitoredItemModifyResult, ett_opcua_array_MonitoredItemModifyResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSetMonitoringModeRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_SetMonitoringModeRequest, &ti, "SetMonitoringModeRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseMonitoringMode(subtree, tvb, pinfo, pOffset); + /* Array length field ignored: NoOfMonitoredItemIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "MonitoredItemIds", "UInt32", hf_opcua_MonitoredItemIds, parseUInt32, ett_opcua_array_UInt32); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSetMonitoringModeResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_SetMonitoringModeResponse, &ti, "SetMonitoringModeResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSetTriggeringRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_SetTriggeringRequest, &ti, "SetTriggeringRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TriggeringItemId); + /* Array length field ignored: NoOfLinksToAdd */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "LinksToAdd", "UInt32", hf_opcua_LinksToAdd, parseUInt32, ett_opcua_array_UInt32); + /* Array length field ignored: NoOfLinksToRemove */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "LinksToRemove", "UInt32", hf_opcua_LinksToRemove, parseUInt32, ett_opcua_array_UInt32); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSetTriggeringResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_SetTriggeringResponse, &ti, "SetTriggeringResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfAddResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "AddResults", "StatusCode", hf_opcua_AddResults, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfAddDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "AddDiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + /* Array length field ignored: NoOfRemoveResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "RemoveResults", "StatusCode", hf_opcua_RemoveResults, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfRemoveDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "RemoveDiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteMonitoredItemsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_DeleteMonitoredItemsRequest, &ti, "DeleteMonitoredItemsRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + /* Array length field ignored: NoOfMonitoredItemIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "MonitoredItemIds", "UInt32", hf_opcua_MonitoredItemIds, parseUInt32, ett_opcua_array_UInt32); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteMonitoredItemsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_DeleteMonitoredItemsResponse, &ti, "DeleteMonitoredItemsResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCreateSubscriptionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CreateSubscriptionRequest, &ti, "CreateSubscriptionRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedPublishingInterval); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedLifetimeCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedMaxKeepAliveCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxNotificationsPerPublish); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_PublishingEnabled); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_Priority); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseCreateSubscriptionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_CreateSubscriptionResponse, &ti, "CreateSubscriptionResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedPublishingInterval); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedLifetimeCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedMaxKeepAliveCount); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseModifySubscriptionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ModifySubscriptionRequest, &ti, "ModifySubscriptionRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedPublishingInterval); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedLifetimeCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RequestedMaxKeepAliveCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_MaxNotificationsPerPublish); + parseByte(subtree, tvb, pinfo, pOffset, hf_opcua_Priority); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseModifySubscriptionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_ModifySubscriptionResponse, &ti, "ModifySubscriptionResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseDouble(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedPublishingInterval); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedLifetimeCount); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RevisedMaxKeepAliveCount); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSetPublishingModeRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_SetPublishingModeRequest, &ti, "SetPublishingModeRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_PublishingEnabled); + /* Array length field ignored: NoOfSubscriptionIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "SubscriptionIds", "UInt32", hf_opcua_SubscriptionIds, parseUInt32, ett_opcua_array_UInt32); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseSetPublishingModeResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_SetPublishingModeResponse, &ti, "SetPublishingModeResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parsePublishRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_PublishRequest, &ti, "PublishRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfSubscriptionAcknowledgements */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "SubscriptionAcknowledgements", "SubscriptionAcknowledgement", parseSubscriptionAcknowledgement, ett_opcua_array_SubscriptionAcknowledgement); + proto_item_set_end(ti, tvb, *pOffset); +} +void parsePublishResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_PublishResponse, &ti, "PublishResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + /* Array length field ignored: NoOfAvailableSequenceNumbers */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "AvailableSequenceNumbers", "UInt32", hf_opcua_AvailableSequenceNumbers, parseUInt32, ett_opcua_array_UInt32); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_MoreNotifications); + parseNotificationMessage(subtree, tvb, pinfo, pOffset, "NotificationMessage"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRepublishRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_RepublishRequest, &ti, "RepublishRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_SubscriptionId); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_RetransmitSequenceNumber); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseRepublishResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_RepublishResponse, &ti, "RepublishResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseNotificationMessage(subtree, tvb, pinfo, pOffset, "NotificationMessage"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTransferSubscriptionsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_TransferSubscriptionsRequest, &ti, "TransferSubscriptionsRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfSubscriptionIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "SubscriptionIds", "UInt32", hf_opcua_SubscriptionIds, parseUInt32, ett_opcua_array_UInt32); + parseBoolean(subtree, tvb, pinfo, pOffset, hf_opcua_SendInitialValues); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTransferSubscriptionsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_TransferSubscriptionsResponse, &ti, "TransferSubscriptionsResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "Results", "TransferResult", parseTransferResult, ett_opcua_array_TransferResult); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteSubscriptionsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_DeleteSubscriptionsRequest, &ti, "DeleteSubscriptionsRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + /* Array length field ignored: NoOfSubscriptionIds */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "SubscriptionIds", "UInt32", hf_opcua_SubscriptionIds, parseUInt32, ett_opcua_array_UInt32); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseDeleteSubscriptionsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_DeleteSubscriptionsResponse, &ti, "DeleteSubscriptionsResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + /* Array length field ignored: NoOfResults */ + parseArraySimple(subtree, tvb, pinfo, pOffset, "Results", "StatusCode", hf_opcua_Results, parseStatusCode, ett_opcua_array_StatusCode); + /* Array length field ignored: NoOfDiagnosticInfos */ + parseArrayComplex(subtree, tvb, pinfo, pOffset, "DiagnosticInfos", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTestStackRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_TestStackRequest, &ti, "TestStackRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TestId); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_Iteration); + parseVariant(subtree, tvb, pinfo, pOffset, "Input"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTestStackResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_TestStackResponse, &ti, "TestStackResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseVariant(subtree, tvb, pinfo, pOffset, "Output"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTestStackExRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_TestStackExRequest, &ti, "TestStackExRequest"); + + parseRequestHeader(subtree, tvb, pinfo, pOffset, "RequestHeader"); + parseUInt32(subtree, tvb, pinfo, pOffset, hf_opcua_TestId); + parseInt32(subtree, tvb, pinfo, pOffset, hf_opcua_Iteration); + parseCompositeTestType(subtree, tvb, pinfo, pOffset, "Input"); + proto_item_set_end(ti, tvb, *pOffset); +} +void parseTestStackExResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_TestStackExResponse, &ti, "TestStackExResponse"); + + parseResponseHeader(subtree, tvb, pinfo, pOffset, "ResponseHeader"); + parseCompositeTestType(subtree, tvb, pinfo, pOffset, "Output"); + proto_item_set_end(ti, tvb, *pOffset); +} + +/** Setup protocol subtree array */ +static gint *ett[] = +{ + &ett_opcua_ServiceFault, + &ett_opcua_array_ServiceFault, + &ett_opcua_FindServersRequest, + &ett_opcua_array_FindServersRequest, + &ett_opcua_FindServersResponse, + &ett_opcua_array_FindServersResponse, + &ett_opcua_FindServersOnNetworkRequest, + &ett_opcua_array_FindServersOnNetworkRequest, + &ett_opcua_FindServersOnNetworkResponse, + &ett_opcua_array_FindServersOnNetworkResponse, + &ett_opcua_GetEndpointsRequest, + &ett_opcua_array_GetEndpointsRequest, + &ett_opcua_GetEndpointsResponse, + &ett_opcua_array_GetEndpointsResponse, + &ett_opcua_RegisterServerRequest, + &ett_opcua_array_RegisterServerRequest, + &ett_opcua_RegisterServerResponse, + &ett_opcua_array_RegisterServerResponse, + &ett_opcua_RegisterServer2Request, + &ett_opcua_array_RegisterServer2Request, + &ett_opcua_RegisterServer2Response, + &ett_opcua_array_RegisterServer2Response, + &ett_opcua_OpenSecureChannelRequest, + &ett_opcua_array_OpenSecureChannelRequest, + &ett_opcua_OpenSecureChannelResponse, + &ett_opcua_array_OpenSecureChannelResponse, + &ett_opcua_CloseSecureChannelRequest, + &ett_opcua_array_CloseSecureChannelRequest, + &ett_opcua_CloseSecureChannelResponse, + &ett_opcua_array_CloseSecureChannelResponse, + &ett_opcua_CreateSessionRequest, + &ett_opcua_array_CreateSessionRequest, + &ett_opcua_CreateSessionResponse, + &ett_opcua_array_CreateSessionResponse, + &ett_opcua_ActivateSessionRequest, + &ett_opcua_array_ActivateSessionRequest, + &ett_opcua_ActivateSessionResponse, + &ett_opcua_array_ActivateSessionResponse, + &ett_opcua_CloseSessionRequest, + &ett_opcua_array_CloseSessionRequest, + &ett_opcua_CloseSessionResponse, + &ett_opcua_array_CloseSessionResponse, + &ett_opcua_CancelRequest, + &ett_opcua_array_CancelRequest, + &ett_opcua_CancelResponse, + &ett_opcua_array_CancelResponse, + &ett_opcua_AddNodesRequest, + &ett_opcua_array_AddNodesRequest, + &ett_opcua_AddNodesResponse, + &ett_opcua_array_AddNodesResponse, + &ett_opcua_AddReferencesRequest, + &ett_opcua_array_AddReferencesRequest, + &ett_opcua_AddReferencesResponse, + &ett_opcua_array_AddReferencesResponse, + &ett_opcua_DeleteNodesRequest, + &ett_opcua_array_DeleteNodesRequest, + &ett_opcua_DeleteNodesResponse, + &ett_opcua_array_DeleteNodesResponse, + &ett_opcua_DeleteReferencesRequest, + &ett_opcua_array_DeleteReferencesRequest, + &ett_opcua_DeleteReferencesResponse, + &ett_opcua_array_DeleteReferencesResponse, + &ett_opcua_BrowseRequest, + &ett_opcua_array_BrowseRequest, + &ett_opcua_BrowseResponse, + &ett_opcua_array_BrowseResponse, + &ett_opcua_BrowseNextRequest, + &ett_opcua_array_BrowseNextRequest, + &ett_opcua_BrowseNextResponse, + &ett_opcua_array_BrowseNextResponse, + &ett_opcua_TranslateBrowsePathsToNodeIdsRequest, + &ett_opcua_array_TranslateBrowsePathsToNodeIdsRequest, + &ett_opcua_TranslateBrowsePathsToNodeIdsResponse, + &ett_opcua_array_TranslateBrowsePathsToNodeIdsResponse, + &ett_opcua_RegisterNodesRequest, + &ett_opcua_array_RegisterNodesRequest, + &ett_opcua_RegisterNodesResponse, + &ett_opcua_array_RegisterNodesResponse, + &ett_opcua_UnregisterNodesRequest, + &ett_opcua_array_UnregisterNodesRequest, + &ett_opcua_UnregisterNodesResponse, + &ett_opcua_array_UnregisterNodesResponse, + &ett_opcua_QueryFirstRequest, + &ett_opcua_array_QueryFirstRequest, + &ett_opcua_QueryFirstResponse, + &ett_opcua_array_QueryFirstResponse, + &ett_opcua_QueryNextRequest, + &ett_opcua_array_QueryNextRequest, + &ett_opcua_QueryNextResponse, + &ett_opcua_array_QueryNextResponse, + &ett_opcua_ReadRequest, + &ett_opcua_array_ReadRequest, + &ett_opcua_ReadResponse, + &ett_opcua_array_ReadResponse, + &ett_opcua_HistoryReadRequest, + &ett_opcua_array_HistoryReadRequest, + &ett_opcua_HistoryReadResponse, + &ett_opcua_array_HistoryReadResponse, + &ett_opcua_WriteRequest, + &ett_opcua_array_WriteRequest, + &ett_opcua_WriteResponse, + &ett_opcua_array_WriteResponse, + &ett_opcua_HistoryUpdateRequest, + &ett_opcua_array_HistoryUpdateRequest, + &ett_opcua_HistoryUpdateResponse, + &ett_opcua_array_HistoryUpdateResponse, + &ett_opcua_CallRequest, + &ett_opcua_array_CallRequest, + &ett_opcua_CallResponse, + &ett_opcua_array_CallResponse, + &ett_opcua_CreateMonitoredItemsRequest, + &ett_opcua_array_CreateMonitoredItemsRequest, + &ett_opcua_CreateMonitoredItemsResponse, + &ett_opcua_array_CreateMonitoredItemsResponse, + &ett_opcua_ModifyMonitoredItemsRequest, + &ett_opcua_array_ModifyMonitoredItemsRequest, + &ett_opcua_ModifyMonitoredItemsResponse, + &ett_opcua_array_ModifyMonitoredItemsResponse, + &ett_opcua_SetMonitoringModeRequest, + &ett_opcua_array_SetMonitoringModeRequest, + &ett_opcua_SetMonitoringModeResponse, + &ett_opcua_array_SetMonitoringModeResponse, + &ett_opcua_SetTriggeringRequest, + &ett_opcua_array_SetTriggeringRequest, + &ett_opcua_SetTriggeringResponse, + &ett_opcua_array_SetTriggeringResponse, + &ett_opcua_DeleteMonitoredItemsRequest, + &ett_opcua_array_DeleteMonitoredItemsRequest, + &ett_opcua_DeleteMonitoredItemsResponse, + &ett_opcua_array_DeleteMonitoredItemsResponse, + &ett_opcua_CreateSubscriptionRequest, + &ett_opcua_array_CreateSubscriptionRequest, + &ett_opcua_CreateSubscriptionResponse, + &ett_opcua_array_CreateSubscriptionResponse, + &ett_opcua_ModifySubscriptionRequest, + &ett_opcua_array_ModifySubscriptionRequest, + &ett_opcua_ModifySubscriptionResponse, + &ett_opcua_array_ModifySubscriptionResponse, + &ett_opcua_SetPublishingModeRequest, + &ett_opcua_array_SetPublishingModeRequest, + &ett_opcua_SetPublishingModeResponse, + &ett_opcua_array_SetPublishingModeResponse, + &ett_opcua_PublishRequest, + &ett_opcua_array_PublishRequest, + &ett_opcua_PublishResponse, + &ett_opcua_array_PublishResponse, + &ett_opcua_RepublishRequest, + &ett_opcua_array_RepublishRequest, + &ett_opcua_RepublishResponse, + &ett_opcua_array_RepublishResponse, + &ett_opcua_TransferSubscriptionsRequest, + &ett_opcua_array_TransferSubscriptionsRequest, + &ett_opcua_TransferSubscriptionsResponse, + &ett_opcua_array_TransferSubscriptionsResponse, + &ett_opcua_DeleteSubscriptionsRequest, + &ett_opcua_array_DeleteSubscriptionsRequest, + &ett_opcua_DeleteSubscriptionsResponse, + &ett_opcua_array_DeleteSubscriptionsResponse, + &ett_opcua_TestStackRequest, + &ett_opcua_array_TestStackRequest, + &ett_opcua_TestStackResponse, + &ett_opcua_array_TestStackResponse, + &ett_opcua_TestStackExRequest, + &ett_opcua_array_TestStackExRequest, + &ett_opcua_TestStackExResponse, + &ett_opcua_array_TestStackExResponse, +}; + +void registerServiceTypes(void) +{ + proto_register_subtree_array(ett, array_length(ett)); +} + diff --git a/plugins/epan/opcua/opcua_serviceparser.h b/plugins/epan/opcua/opcua_serviceparser.h new file mode 100644 index 00000000..db8e6c42 --- /dev/null +++ b/plugins/epan/opcua/opcua_serviceparser.h @@ -0,0 +1,273 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Service Type Parser +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** XXX - well, except that you may have to. See the README. +** +******************************************************************************/ + +#include +#include + +extern gint ett_opcua_ServiceFault; +extern gint ett_opcua_array_ServiceFault; +extern gint ett_opcua_FindServersRequest; +extern gint ett_opcua_array_FindServersRequest; +extern gint ett_opcua_FindServersResponse; +extern gint ett_opcua_array_FindServersResponse; +extern gint ett_opcua_FindServersOnNetworkRequest; +extern gint ett_opcua_array_FindServersOnNetworkRequest; +extern gint ett_opcua_FindServersOnNetworkResponse; +extern gint ett_opcua_array_FindServersOnNetworkResponse; +extern gint ett_opcua_GetEndpointsRequest; +extern gint ett_opcua_array_GetEndpointsRequest; +extern gint ett_opcua_GetEndpointsResponse; +extern gint ett_opcua_array_GetEndpointsResponse; +extern gint ett_opcua_RegisterServerRequest; +extern gint ett_opcua_array_RegisterServerRequest; +extern gint ett_opcua_RegisterServerResponse; +extern gint ett_opcua_array_RegisterServerResponse; +extern gint ett_opcua_RegisterServer2Request; +extern gint ett_opcua_array_RegisterServer2Request; +extern gint ett_opcua_RegisterServer2Response; +extern gint ett_opcua_array_RegisterServer2Response; +extern gint ett_opcua_OpenSecureChannelRequest; +extern gint ett_opcua_array_OpenSecureChannelRequest; +extern gint ett_opcua_OpenSecureChannelResponse; +extern gint ett_opcua_array_OpenSecureChannelResponse; +extern gint ett_opcua_CloseSecureChannelRequest; +extern gint ett_opcua_array_CloseSecureChannelRequest; +extern gint ett_opcua_CloseSecureChannelResponse; +extern gint ett_opcua_array_CloseSecureChannelResponse; +extern gint ett_opcua_CreateSessionRequest; +extern gint ett_opcua_array_CreateSessionRequest; +extern gint ett_opcua_CreateSessionResponse; +extern gint ett_opcua_array_CreateSessionResponse; +extern gint ett_opcua_ActivateSessionRequest; +extern gint ett_opcua_array_ActivateSessionRequest; +extern gint ett_opcua_ActivateSessionResponse; +extern gint ett_opcua_array_ActivateSessionResponse; +extern gint ett_opcua_CloseSessionRequest; +extern gint ett_opcua_array_CloseSessionRequest; +extern gint ett_opcua_CloseSessionResponse; +extern gint ett_opcua_array_CloseSessionResponse; +extern gint ett_opcua_CancelRequest; +extern gint ett_opcua_array_CancelRequest; +extern gint ett_opcua_CancelResponse; +extern gint ett_opcua_array_CancelResponse; +extern gint ett_opcua_AddNodesRequest; +extern gint ett_opcua_array_AddNodesRequest; +extern gint ett_opcua_AddNodesResponse; +extern gint ett_opcua_array_AddNodesResponse; +extern gint ett_opcua_AddReferencesRequest; +extern gint ett_opcua_array_AddReferencesRequest; +extern gint ett_opcua_AddReferencesResponse; +extern gint ett_opcua_array_AddReferencesResponse; +extern gint ett_opcua_DeleteNodesRequest; +extern gint ett_opcua_array_DeleteNodesRequest; +extern gint ett_opcua_DeleteNodesResponse; +extern gint ett_opcua_array_DeleteNodesResponse; +extern gint ett_opcua_DeleteReferencesRequest; +extern gint ett_opcua_array_DeleteReferencesRequest; +extern gint ett_opcua_DeleteReferencesResponse; +extern gint ett_opcua_array_DeleteReferencesResponse; +extern gint ett_opcua_BrowseRequest; +extern gint ett_opcua_array_BrowseRequest; +extern gint ett_opcua_BrowseResponse; +extern gint ett_opcua_array_BrowseResponse; +extern gint ett_opcua_BrowseNextRequest; +extern gint ett_opcua_array_BrowseNextRequest; +extern gint ett_opcua_BrowseNextResponse; +extern gint ett_opcua_array_BrowseNextResponse; +extern gint ett_opcua_TranslateBrowsePathsToNodeIdsRequest; +extern gint ett_opcua_array_TranslateBrowsePathsToNodeIdsRequest; +extern gint ett_opcua_TranslateBrowsePathsToNodeIdsResponse; +extern gint ett_opcua_array_TranslateBrowsePathsToNodeIdsResponse; +extern gint ett_opcua_RegisterNodesRequest; +extern gint ett_opcua_array_RegisterNodesRequest; +extern gint ett_opcua_RegisterNodesResponse; +extern gint ett_opcua_array_RegisterNodesResponse; +extern gint ett_opcua_UnregisterNodesRequest; +extern gint ett_opcua_array_UnregisterNodesRequest; +extern gint ett_opcua_UnregisterNodesResponse; +extern gint ett_opcua_array_UnregisterNodesResponse; +extern gint ett_opcua_QueryFirstRequest; +extern gint ett_opcua_array_QueryFirstRequest; +extern gint ett_opcua_QueryFirstResponse; +extern gint ett_opcua_array_QueryFirstResponse; +extern gint ett_opcua_QueryNextRequest; +extern gint ett_opcua_array_QueryNextRequest; +extern gint ett_opcua_QueryNextResponse; +extern gint ett_opcua_array_QueryNextResponse; +extern gint ett_opcua_ReadRequest; +extern gint ett_opcua_array_ReadRequest; +extern gint ett_opcua_ReadResponse; +extern gint ett_opcua_array_ReadResponse; +extern gint ett_opcua_HistoryReadRequest; +extern gint ett_opcua_array_HistoryReadRequest; +extern gint ett_opcua_HistoryReadResponse; +extern gint ett_opcua_array_HistoryReadResponse; +extern gint ett_opcua_WriteRequest; +extern gint ett_opcua_array_WriteRequest; +extern gint ett_opcua_WriteResponse; +extern gint ett_opcua_array_WriteResponse; +extern gint ett_opcua_HistoryUpdateRequest; +extern gint ett_opcua_array_HistoryUpdateRequest; +extern gint ett_opcua_HistoryUpdateResponse; +extern gint ett_opcua_array_HistoryUpdateResponse; +extern gint ett_opcua_CallRequest; +extern gint ett_opcua_array_CallRequest; +extern gint ett_opcua_CallResponse; +extern gint ett_opcua_array_CallResponse; +extern gint ett_opcua_CreateMonitoredItemsRequest; +extern gint ett_opcua_array_CreateMonitoredItemsRequest; +extern gint ett_opcua_CreateMonitoredItemsResponse; +extern gint ett_opcua_array_CreateMonitoredItemsResponse; +extern gint ett_opcua_ModifyMonitoredItemsRequest; +extern gint ett_opcua_array_ModifyMonitoredItemsRequest; +extern gint ett_opcua_ModifyMonitoredItemsResponse; +extern gint ett_opcua_array_ModifyMonitoredItemsResponse; +extern gint ett_opcua_SetMonitoringModeRequest; +extern gint ett_opcua_array_SetMonitoringModeRequest; +extern gint ett_opcua_SetMonitoringModeResponse; +extern gint ett_opcua_array_SetMonitoringModeResponse; +extern gint ett_opcua_SetTriggeringRequest; +extern gint ett_opcua_array_SetTriggeringRequest; +extern gint ett_opcua_SetTriggeringResponse; +extern gint ett_opcua_array_SetTriggeringResponse; +extern gint ett_opcua_DeleteMonitoredItemsRequest; +extern gint ett_opcua_array_DeleteMonitoredItemsRequest; +extern gint ett_opcua_DeleteMonitoredItemsResponse; +extern gint ett_opcua_array_DeleteMonitoredItemsResponse; +extern gint ett_opcua_CreateSubscriptionRequest; +extern gint ett_opcua_array_CreateSubscriptionRequest; +extern gint ett_opcua_CreateSubscriptionResponse; +extern gint ett_opcua_array_CreateSubscriptionResponse; +extern gint ett_opcua_ModifySubscriptionRequest; +extern gint ett_opcua_array_ModifySubscriptionRequest; +extern gint ett_opcua_ModifySubscriptionResponse; +extern gint ett_opcua_array_ModifySubscriptionResponse; +extern gint ett_opcua_SetPublishingModeRequest; +extern gint ett_opcua_array_SetPublishingModeRequest; +extern gint ett_opcua_SetPublishingModeResponse; +extern gint ett_opcua_array_SetPublishingModeResponse; +extern gint ett_opcua_PublishRequest; +extern gint ett_opcua_array_PublishRequest; +extern gint ett_opcua_PublishResponse; +extern gint ett_opcua_array_PublishResponse; +extern gint ett_opcua_RepublishRequest; +extern gint ett_opcua_array_RepublishRequest; +extern gint ett_opcua_RepublishResponse; +extern gint ett_opcua_array_RepublishResponse; +extern gint ett_opcua_TransferSubscriptionsRequest; +extern gint ett_opcua_array_TransferSubscriptionsRequest; +extern gint ett_opcua_TransferSubscriptionsResponse; +extern gint ett_opcua_array_TransferSubscriptionsResponse; +extern gint ett_opcua_DeleteSubscriptionsRequest; +extern gint ett_opcua_array_DeleteSubscriptionsRequest; +extern gint ett_opcua_DeleteSubscriptionsResponse; +extern gint ett_opcua_array_DeleteSubscriptionsResponse; +extern gint ett_opcua_TestStackRequest; +extern gint ett_opcua_array_TestStackRequest; +extern gint ett_opcua_TestStackResponse; +extern gint ett_opcua_array_TestStackResponse; +extern gint ett_opcua_TestStackExRequest; +extern gint ett_opcua_array_TestStackExRequest; +extern gint ett_opcua_TestStackExResponse; +extern gint ett_opcua_array_TestStackExResponse; + +void parseServiceFault(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseFindServersRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseFindServersResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseFindServersOnNetworkRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseFindServersOnNetworkResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseGetEndpointsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseGetEndpointsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRegisterServerRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRegisterServerResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRegisterServer2Request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRegisterServer2Response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseOpenSecureChannelRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseOpenSecureChannelResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCloseSecureChannelRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCloseSecureChannelResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCreateSessionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCreateSessionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseActivateSessionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseActivateSessionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCloseSessionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCloseSessionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCancelRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCancelResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseAddNodesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseAddNodesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseAddReferencesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseAddReferencesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeleteNodesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeleteNodesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeleteReferencesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeleteReferencesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseBrowseRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseBrowseResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseBrowseNextRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseBrowseNextResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTranslateBrowsePathsToNodeIdsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTranslateBrowsePathsToNodeIdsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRegisterNodesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRegisterNodesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseUnregisterNodesRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseUnregisterNodesResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseQueryFirstRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseQueryFirstResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseQueryNextRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseQueryNextResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseReadRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseReadResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseHistoryReadRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseHistoryReadResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseWriteRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseWriteResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseHistoryUpdateRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseHistoryUpdateResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCallRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCallResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCreateMonitoredItemsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCreateMonitoredItemsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseModifyMonitoredItemsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseModifyMonitoredItemsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseSetMonitoringModeRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseSetMonitoringModeResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseSetTriggeringRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseSetTriggeringResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeleteMonitoredItemsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeleteMonitoredItemsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCreateSubscriptionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseCreateSubscriptionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseModifySubscriptionRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseModifySubscriptionResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseSetPublishingModeRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseSetPublishingModeResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parsePublishRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parsePublishResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRepublishRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseRepublishResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTransferSubscriptionsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTransferSubscriptionsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeleteSubscriptionsRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseDeleteSubscriptionsResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTestStackRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTestStackResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTestStackExRequest(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseTestStackExResponse(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void registerServiceTypes(void); diff --git a/plugins/epan/opcua/opcua_servicetable.c b/plugins/epan/opcua/opcua_servicetable.c new file mode 100644 index 00000000..b800da92 --- /dev/null +++ b/plugins/epan/opcua/opcua_servicetable.c @@ -0,0 +1,300 @@ +/****************************************************************************** +** Copyright (C) 2006-2015 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: Service table and service dispatcher. +** +** This file was autogenerated on 13.10.2015. +** DON'T MODIFY THIS FILE! +** +******************************************************************************/ + +#include "config.h" + +#include +#include "opcua_identifiers.h" +#include "opcua_serviceparser.h" +#include "opcua_serviceids.h" +#include "opcua_servicetable.h" + +ParserEntry g_arParserTable[] = { + { OpcUaId_ServiceFault_Encoding_DefaultBinary, parseServiceFault }, + { OpcUaId_FindServersRequest_Encoding_DefaultBinary, parseFindServersRequest }, + { OpcUaId_FindServersResponse_Encoding_DefaultBinary, parseFindServersResponse }, + { OpcUaId_FindServersOnNetworkRequest_Encoding_DefaultBinary, parseFindServersOnNetworkRequest }, + { OpcUaId_FindServersOnNetworkResponse_Encoding_DefaultBinary, parseFindServersOnNetworkResponse }, + { OpcUaId_GetEndpointsRequest_Encoding_DefaultBinary, parseGetEndpointsRequest }, + { OpcUaId_GetEndpointsResponse_Encoding_DefaultBinary, parseGetEndpointsResponse }, + { OpcUaId_RegisterServerRequest_Encoding_DefaultBinary, parseRegisterServerRequest }, + { OpcUaId_RegisterServerResponse_Encoding_DefaultBinary, parseRegisterServerResponse }, + { OpcUaId_RegisterServer2Request_Encoding_DefaultBinary, parseRegisterServer2Request }, + { OpcUaId_RegisterServer2Response_Encoding_DefaultBinary, parseRegisterServer2Response }, + { OpcUaId_OpenSecureChannelRequest_Encoding_DefaultBinary, parseOpenSecureChannelRequest }, + { OpcUaId_OpenSecureChannelResponse_Encoding_DefaultBinary, parseOpenSecureChannelResponse }, + { OpcUaId_CloseSecureChannelRequest_Encoding_DefaultBinary, parseCloseSecureChannelRequest }, + { OpcUaId_CloseSecureChannelResponse_Encoding_DefaultBinary, parseCloseSecureChannelResponse }, + { OpcUaId_CreateSessionRequest_Encoding_DefaultBinary, parseCreateSessionRequest }, + { OpcUaId_CreateSessionResponse_Encoding_DefaultBinary, parseCreateSessionResponse }, + { OpcUaId_ActivateSessionRequest_Encoding_DefaultBinary, parseActivateSessionRequest }, + { OpcUaId_ActivateSessionResponse_Encoding_DefaultBinary, parseActivateSessionResponse }, + { OpcUaId_CloseSessionRequest_Encoding_DefaultBinary, parseCloseSessionRequest }, + { OpcUaId_CloseSessionResponse_Encoding_DefaultBinary, parseCloseSessionResponse }, + { OpcUaId_CancelRequest_Encoding_DefaultBinary, parseCancelRequest }, + { OpcUaId_CancelResponse_Encoding_DefaultBinary, parseCancelResponse }, + { OpcUaId_AddNodesRequest_Encoding_DefaultBinary, parseAddNodesRequest }, + { OpcUaId_AddNodesResponse_Encoding_DefaultBinary, parseAddNodesResponse }, + { OpcUaId_AddReferencesRequest_Encoding_DefaultBinary, parseAddReferencesRequest }, + { OpcUaId_AddReferencesResponse_Encoding_DefaultBinary, parseAddReferencesResponse }, + { OpcUaId_DeleteNodesRequest_Encoding_DefaultBinary, parseDeleteNodesRequest }, + { OpcUaId_DeleteNodesResponse_Encoding_DefaultBinary, parseDeleteNodesResponse }, + { OpcUaId_DeleteReferencesRequest_Encoding_DefaultBinary, parseDeleteReferencesRequest }, + { OpcUaId_DeleteReferencesResponse_Encoding_DefaultBinary, parseDeleteReferencesResponse }, + { OpcUaId_BrowseRequest_Encoding_DefaultBinary, parseBrowseRequest }, + { OpcUaId_BrowseResponse_Encoding_DefaultBinary, parseBrowseResponse }, + { OpcUaId_BrowseNextRequest_Encoding_DefaultBinary, parseBrowseNextRequest }, + { OpcUaId_BrowseNextResponse_Encoding_DefaultBinary, parseBrowseNextResponse }, + { OpcUaId_TranslateBrowsePathsToNodeIdsRequest_Encoding_DefaultBinary, parseTranslateBrowsePathsToNodeIdsRequest }, + { OpcUaId_TranslateBrowsePathsToNodeIdsResponse_Encoding_DefaultBinary, parseTranslateBrowsePathsToNodeIdsResponse }, + { OpcUaId_RegisterNodesRequest_Encoding_DefaultBinary, parseRegisterNodesRequest }, + { OpcUaId_RegisterNodesResponse_Encoding_DefaultBinary, parseRegisterNodesResponse }, + { OpcUaId_UnregisterNodesRequest_Encoding_DefaultBinary, parseUnregisterNodesRequest }, + { OpcUaId_UnregisterNodesResponse_Encoding_DefaultBinary, parseUnregisterNodesResponse }, + { OpcUaId_QueryFirstRequest_Encoding_DefaultBinary, parseQueryFirstRequest }, + { OpcUaId_QueryFirstResponse_Encoding_DefaultBinary, parseQueryFirstResponse }, + { OpcUaId_QueryNextRequest_Encoding_DefaultBinary, parseQueryNextRequest }, + { OpcUaId_QueryNextResponse_Encoding_DefaultBinary, parseQueryNextResponse }, + { OpcUaId_ReadRequest_Encoding_DefaultBinary, parseReadRequest }, + { OpcUaId_ReadResponse_Encoding_DefaultBinary, parseReadResponse }, + { OpcUaId_HistoryReadRequest_Encoding_DefaultBinary, parseHistoryReadRequest }, + { OpcUaId_HistoryReadResponse_Encoding_DefaultBinary, parseHistoryReadResponse }, + { OpcUaId_WriteRequest_Encoding_DefaultBinary, parseWriteRequest }, + { OpcUaId_WriteResponse_Encoding_DefaultBinary, parseWriteResponse }, + { OpcUaId_HistoryUpdateRequest_Encoding_DefaultBinary, parseHistoryUpdateRequest }, + { OpcUaId_HistoryUpdateResponse_Encoding_DefaultBinary, parseHistoryUpdateResponse }, + { OpcUaId_CallRequest_Encoding_DefaultBinary, parseCallRequest }, + { OpcUaId_CallResponse_Encoding_DefaultBinary, parseCallResponse }, + { OpcUaId_CreateMonitoredItemsRequest_Encoding_DefaultBinary, parseCreateMonitoredItemsRequest }, + { OpcUaId_CreateMonitoredItemsResponse_Encoding_DefaultBinary, parseCreateMonitoredItemsResponse }, + { OpcUaId_ModifyMonitoredItemsRequest_Encoding_DefaultBinary, parseModifyMonitoredItemsRequest }, + { OpcUaId_ModifyMonitoredItemsResponse_Encoding_DefaultBinary, parseModifyMonitoredItemsResponse }, + { OpcUaId_SetMonitoringModeRequest_Encoding_DefaultBinary, parseSetMonitoringModeRequest }, + { OpcUaId_SetMonitoringModeResponse_Encoding_DefaultBinary, parseSetMonitoringModeResponse }, + { OpcUaId_SetTriggeringRequest_Encoding_DefaultBinary, parseSetTriggeringRequest }, + { OpcUaId_SetTriggeringResponse_Encoding_DefaultBinary, parseSetTriggeringResponse }, + { OpcUaId_DeleteMonitoredItemsRequest_Encoding_DefaultBinary, parseDeleteMonitoredItemsRequest }, + { OpcUaId_DeleteMonitoredItemsResponse_Encoding_DefaultBinary, parseDeleteMonitoredItemsResponse }, + { OpcUaId_CreateSubscriptionRequest_Encoding_DefaultBinary, parseCreateSubscriptionRequest }, + { OpcUaId_CreateSubscriptionResponse_Encoding_DefaultBinary, parseCreateSubscriptionResponse }, + { OpcUaId_ModifySubscriptionRequest_Encoding_DefaultBinary, parseModifySubscriptionRequest }, + { OpcUaId_ModifySubscriptionResponse_Encoding_DefaultBinary, parseModifySubscriptionResponse }, + { OpcUaId_SetPublishingModeRequest_Encoding_DefaultBinary, parseSetPublishingModeRequest }, + { OpcUaId_SetPublishingModeResponse_Encoding_DefaultBinary, parseSetPublishingModeResponse }, + { OpcUaId_PublishRequest_Encoding_DefaultBinary, parsePublishRequest }, + { OpcUaId_PublishResponse_Encoding_DefaultBinary, parsePublishResponse }, + { OpcUaId_RepublishRequest_Encoding_DefaultBinary, parseRepublishRequest }, + { OpcUaId_RepublishResponse_Encoding_DefaultBinary, parseRepublishResponse }, + { OpcUaId_TransferSubscriptionsRequest_Encoding_DefaultBinary, parseTransferSubscriptionsRequest }, + { OpcUaId_TransferSubscriptionsResponse_Encoding_DefaultBinary, parseTransferSubscriptionsResponse }, + { OpcUaId_DeleteSubscriptionsRequest_Encoding_DefaultBinary, parseDeleteSubscriptionsRequest }, + { OpcUaId_DeleteSubscriptionsResponse_Encoding_DefaultBinary, parseDeleteSubscriptionsResponse }, + { OpcUaId_TestStackRequest_Encoding_DefaultBinary, parseTestStackRequest }, + { OpcUaId_TestStackResponse_Encoding_DefaultBinary, parseTestStackResponse }, + { OpcUaId_TestStackExRequest_Encoding_DefaultBinary, parseTestStackExRequest }, + { OpcUaId_TestStackExResponse_Encoding_DefaultBinary, parseTestStackExResponse }, +}; +const int g_NumServices = sizeof(g_arParserTable) / sizeof(ParserEntry); + +/** Service type table */ +const value_string g_requesttypes[] = { + { OpcUaId_ServiceFault_Encoding_DefaultBinary, "ServiceFault" }, + { OpcUaId_FindServersRequest_Encoding_DefaultBinary, "FindServersRequest" }, + { OpcUaId_FindServersResponse_Encoding_DefaultBinary, "FindServersResponse" }, + { OpcUaId_FindServersOnNetworkRequest_Encoding_DefaultBinary, "FindServersOnNetworkRequest" }, + { OpcUaId_FindServersOnNetworkResponse_Encoding_DefaultBinary, "FindServersOnNetworkResponse" }, + { OpcUaId_GetEndpointsRequest_Encoding_DefaultBinary, "GetEndpointsRequest" }, + { OpcUaId_GetEndpointsResponse_Encoding_DefaultBinary, "GetEndpointsResponse" }, + { OpcUaId_RegisterServerRequest_Encoding_DefaultBinary, "RegisterServerRequest" }, + { OpcUaId_RegisterServerResponse_Encoding_DefaultBinary, "RegisterServerResponse" }, + { OpcUaId_RegisterServer2Request_Encoding_DefaultBinary, "RegisterServer2Request" }, + { OpcUaId_RegisterServer2Response_Encoding_DefaultBinary, "RegisterServer2Response" }, + { OpcUaId_OpenSecureChannelRequest_Encoding_DefaultBinary, "OpenSecureChannelRequest" }, + { OpcUaId_OpenSecureChannelResponse_Encoding_DefaultBinary, "OpenSecureChannelResponse" }, + { OpcUaId_CloseSecureChannelRequest_Encoding_DefaultBinary, "CloseSecureChannelRequest" }, + { OpcUaId_CloseSecureChannelResponse_Encoding_DefaultBinary, "CloseSecureChannelResponse" }, + { OpcUaId_CreateSessionRequest_Encoding_DefaultBinary, "CreateSessionRequest" }, + { OpcUaId_CreateSessionResponse_Encoding_DefaultBinary, "CreateSessionResponse" }, + { OpcUaId_ActivateSessionRequest_Encoding_DefaultBinary, "ActivateSessionRequest" }, + { OpcUaId_ActivateSessionResponse_Encoding_DefaultBinary, "ActivateSessionResponse" }, + { OpcUaId_CloseSessionRequest_Encoding_DefaultBinary, "CloseSessionRequest" }, + { OpcUaId_CloseSessionResponse_Encoding_DefaultBinary, "CloseSessionResponse" }, + { OpcUaId_CancelRequest_Encoding_DefaultBinary, "CancelRequest" }, + { OpcUaId_CancelResponse_Encoding_DefaultBinary, "CancelResponse" }, + { OpcUaId_AddNodesRequest_Encoding_DefaultBinary, "AddNodesRequest" }, + { OpcUaId_AddNodesResponse_Encoding_DefaultBinary, "AddNodesResponse" }, + { OpcUaId_AddReferencesRequest_Encoding_DefaultBinary, "AddReferencesRequest" }, + { OpcUaId_AddReferencesResponse_Encoding_DefaultBinary, "AddReferencesResponse" }, + { OpcUaId_DeleteNodesRequest_Encoding_DefaultBinary, "DeleteNodesRequest" }, + { OpcUaId_DeleteNodesResponse_Encoding_DefaultBinary, "DeleteNodesResponse" }, + { OpcUaId_DeleteReferencesRequest_Encoding_DefaultBinary, "DeleteReferencesRequest" }, + { OpcUaId_DeleteReferencesResponse_Encoding_DefaultBinary, "DeleteReferencesResponse" }, + { OpcUaId_BrowseRequest_Encoding_DefaultBinary, "BrowseRequest" }, + { OpcUaId_BrowseResponse_Encoding_DefaultBinary, "BrowseResponse" }, + { OpcUaId_BrowseNextRequest_Encoding_DefaultBinary, "BrowseNextRequest" }, + { OpcUaId_BrowseNextResponse_Encoding_DefaultBinary, "BrowseNextResponse" }, + { OpcUaId_TranslateBrowsePathsToNodeIdsRequest_Encoding_DefaultBinary, "TranslateBrowsePathsToNodeIdsRequest" }, + { OpcUaId_TranslateBrowsePathsToNodeIdsResponse_Encoding_DefaultBinary, "TranslateBrowsePathsToNodeIdsResponse" }, + { OpcUaId_RegisterNodesRequest_Encoding_DefaultBinary, "RegisterNodesRequest" }, + { OpcUaId_RegisterNodesResponse_Encoding_DefaultBinary, "RegisterNodesResponse" }, + { OpcUaId_UnregisterNodesRequest_Encoding_DefaultBinary, "UnregisterNodesRequest" }, + { OpcUaId_UnregisterNodesResponse_Encoding_DefaultBinary, "UnregisterNodesResponse" }, + { OpcUaId_QueryFirstRequest_Encoding_DefaultBinary, "QueryFirstRequest" }, + { OpcUaId_QueryFirstResponse_Encoding_DefaultBinary, "QueryFirstResponse" }, + { OpcUaId_QueryNextRequest_Encoding_DefaultBinary, "QueryNextRequest" }, + { OpcUaId_QueryNextResponse_Encoding_DefaultBinary, "QueryNextResponse" }, + { OpcUaId_ReadRequest_Encoding_DefaultBinary, "ReadRequest" }, + { OpcUaId_ReadResponse_Encoding_DefaultBinary, "ReadResponse" }, + { OpcUaId_HistoryReadRequest_Encoding_DefaultBinary, "HistoryReadRequest" }, + { OpcUaId_HistoryReadResponse_Encoding_DefaultBinary, "HistoryReadResponse" }, + { OpcUaId_WriteRequest_Encoding_DefaultBinary, "WriteRequest" }, + { OpcUaId_WriteResponse_Encoding_DefaultBinary, "WriteResponse" }, + { OpcUaId_HistoryUpdateRequest_Encoding_DefaultBinary, "HistoryUpdateRequest" }, + { OpcUaId_HistoryUpdateResponse_Encoding_DefaultBinary, "HistoryUpdateResponse" }, + { OpcUaId_CallRequest_Encoding_DefaultBinary, "CallRequest" }, + { OpcUaId_CallResponse_Encoding_DefaultBinary, "CallResponse" }, + { OpcUaId_CreateMonitoredItemsRequest_Encoding_DefaultBinary, "CreateMonitoredItemsRequest" }, + { OpcUaId_CreateMonitoredItemsResponse_Encoding_DefaultBinary, "CreateMonitoredItemsResponse" }, + { OpcUaId_ModifyMonitoredItemsRequest_Encoding_DefaultBinary, "ModifyMonitoredItemsRequest" }, + { OpcUaId_ModifyMonitoredItemsResponse_Encoding_DefaultBinary, "ModifyMonitoredItemsResponse" }, + { OpcUaId_SetMonitoringModeRequest_Encoding_DefaultBinary, "SetMonitoringModeRequest" }, + { OpcUaId_SetMonitoringModeResponse_Encoding_DefaultBinary, "SetMonitoringModeResponse" }, + { OpcUaId_SetTriggeringRequest_Encoding_DefaultBinary, "SetTriggeringRequest" }, + { OpcUaId_SetTriggeringResponse_Encoding_DefaultBinary, "SetTriggeringResponse" }, + { OpcUaId_DeleteMonitoredItemsRequest_Encoding_DefaultBinary, "DeleteMonitoredItemsRequest" }, + { OpcUaId_DeleteMonitoredItemsResponse_Encoding_DefaultBinary, "DeleteMonitoredItemsResponse" }, + { OpcUaId_CreateSubscriptionRequest_Encoding_DefaultBinary, "CreateSubscriptionRequest" }, + { OpcUaId_CreateSubscriptionResponse_Encoding_DefaultBinary, "CreateSubscriptionResponse" }, + { OpcUaId_ModifySubscriptionRequest_Encoding_DefaultBinary, "ModifySubscriptionRequest" }, + { OpcUaId_ModifySubscriptionResponse_Encoding_DefaultBinary, "ModifySubscriptionResponse" }, + { OpcUaId_SetPublishingModeRequest_Encoding_DefaultBinary, "SetPublishingModeRequest" }, + { OpcUaId_SetPublishingModeResponse_Encoding_DefaultBinary, "SetPublishingModeResponse" }, + { OpcUaId_PublishRequest_Encoding_DefaultBinary, "PublishRequest" }, + { OpcUaId_PublishResponse_Encoding_DefaultBinary, "PublishResponse" }, + { OpcUaId_RepublishRequest_Encoding_DefaultBinary, "RepublishRequest" }, + { OpcUaId_RepublishResponse_Encoding_DefaultBinary, "RepublishResponse" }, + { OpcUaId_TransferSubscriptionsRequest_Encoding_DefaultBinary, "TransferSubscriptionsRequest" }, + { OpcUaId_TransferSubscriptionsResponse_Encoding_DefaultBinary, "TransferSubscriptionsResponse" }, + { OpcUaId_DeleteSubscriptionsRequest_Encoding_DefaultBinary, "DeleteSubscriptionsRequest" }, + { OpcUaId_DeleteSubscriptionsResponse_Encoding_DefaultBinary, "DeleteSubscriptionsResponse" }, + { OpcUaId_TestStackRequest_Encoding_DefaultBinary, "TestStackRequest" }, + { OpcUaId_TestStackResponse_Encoding_DefaultBinary, "TestStackResponse" }, + { OpcUaId_TestStackExRequest_Encoding_DefaultBinary, "TestStackExRequest" }, + { OpcUaId_TestStackExResponse_Encoding_DefaultBinary, "TestStackExResponse" }, + { OpcUaId_ServiceFault_Encoding_DefaultXml, "ServiceFault (XML Encoding)" }, + { OpcUaId_FindServersRequest_Encoding_DefaultXml, "FindServersRequest (XML Encoding)" }, + { OpcUaId_FindServersResponse_Encoding_DefaultXml, "FindServersResponse (XML Encoding)" }, + { OpcUaId_FindServersOnNetworkRequest_Encoding_DefaultXml, "FindServersOnNetworkRequest (XML Encoding)" }, + { OpcUaId_FindServersOnNetworkResponse_Encoding_DefaultXml, "FindServersOnNetworkResponse (XML Encoding)" }, + { OpcUaId_GetEndpointsRequest_Encoding_DefaultXml, "GetEndpointsRequest (XML Encoding)" }, + { OpcUaId_GetEndpointsResponse_Encoding_DefaultXml, "GetEndpointsResponse (XML Encoding)" }, + { OpcUaId_RegisterServerRequest_Encoding_DefaultXml, "RegisterServerRequest (XML Encoding)" }, + { OpcUaId_RegisterServerResponse_Encoding_DefaultXml, "RegisterServerResponse (XML Encoding)" }, + { OpcUaId_RegisterServer2Request_Encoding_DefaultXml, "RegisterServer2Request (XML Encoding)" }, + { OpcUaId_RegisterServer2Response_Encoding_DefaultXml, "RegisterServer2Response (XML Encoding)" }, + { OpcUaId_OpenSecureChannelRequest_Encoding_DefaultXml, "OpenSecureChannelRequest (XML Encoding)" }, + { OpcUaId_OpenSecureChannelResponse_Encoding_DefaultXml, "OpenSecureChannelResponse (XML Encoding)" }, + { OpcUaId_CloseSecureChannelRequest_Encoding_DefaultXml, "CloseSecureChannelRequest (XML Encoding)" }, + { OpcUaId_CloseSecureChannelResponse_Encoding_DefaultXml, "CloseSecureChannelResponse (XML Encoding)" }, + { OpcUaId_CreateSessionRequest_Encoding_DefaultXml, "CreateSessionRequest (XML Encoding)" }, + { OpcUaId_CreateSessionResponse_Encoding_DefaultXml, "CreateSessionResponse (XML Encoding)" }, + { OpcUaId_ActivateSessionRequest_Encoding_DefaultXml, "ActivateSessionRequest (XML Encoding)" }, + { OpcUaId_ActivateSessionResponse_Encoding_DefaultXml, "ActivateSessionResponse (XML Encoding)" }, + { OpcUaId_CloseSessionRequest_Encoding_DefaultXml, "CloseSessionRequest (XML Encoding)" }, + { OpcUaId_CloseSessionResponse_Encoding_DefaultXml, "CloseSessionResponse (XML Encoding)" }, + { OpcUaId_CancelRequest_Encoding_DefaultXml, "CancelRequest (XML Encoding)" }, + { OpcUaId_CancelResponse_Encoding_DefaultXml, "CancelResponse (XML Encoding)" }, + { OpcUaId_AddNodesRequest_Encoding_DefaultXml, "AddNodesRequest (XML Encoding)" }, + { OpcUaId_AddNodesResponse_Encoding_DefaultXml, "AddNodesResponse (XML Encoding)" }, + { OpcUaId_AddReferencesRequest_Encoding_DefaultXml, "AddReferencesRequest (XML Encoding)" }, + { OpcUaId_AddReferencesResponse_Encoding_DefaultXml, "AddReferencesResponse (XML Encoding)" }, + { OpcUaId_DeleteNodesRequest_Encoding_DefaultXml, "DeleteNodesRequest (XML Encoding)" }, + { OpcUaId_DeleteNodesResponse_Encoding_DefaultXml, "DeleteNodesResponse (XML Encoding)" }, + { OpcUaId_DeleteReferencesRequest_Encoding_DefaultXml, "DeleteReferencesRequest (XML Encoding)" }, + { OpcUaId_DeleteReferencesResponse_Encoding_DefaultXml, "DeleteReferencesResponse (XML Encoding)" }, + { OpcUaId_BrowseRequest_Encoding_DefaultXml, "BrowseRequest (XML Encoding)" }, + { OpcUaId_BrowseResponse_Encoding_DefaultXml, "BrowseResponse (XML Encoding)" }, + { OpcUaId_BrowseNextRequest_Encoding_DefaultXml, "BrowseNextRequest (XML Encoding)" }, + { OpcUaId_BrowseNextResponse_Encoding_DefaultXml, "BrowseNextResponse (XML Encoding)" }, + { OpcUaId_TranslateBrowsePathsToNodeIdsRequest_Encoding_DefaultXml, "TranslateBrowsePathsToNodeIdsRequest (XML Encoding)" }, + { OpcUaId_TranslateBrowsePathsToNodeIdsResponse_Encoding_DefaultXml, "TranslateBrowsePathsToNodeIdsResponse (XML Encoding)" }, + { OpcUaId_RegisterNodesRequest_Encoding_DefaultXml, "RegisterNodesRequest (XML Encoding)" }, + { OpcUaId_RegisterNodesResponse_Encoding_DefaultXml, "RegisterNodesResponse (XML Encoding)" }, + { OpcUaId_UnregisterNodesRequest_Encoding_DefaultXml, "UnregisterNodesRequest (XML Encoding)" }, + { OpcUaId_UnregisterNodesResponse_Encoding_DefaultXml, "UnregisterNodesResponse (XML Encoding)" }, + { OpcUaId_QueryFirstRequest_Encoding_DefaultXml, "QueryFirstRequest (XML Encoding)" }, + { OpcUaId_QueryFirstResponse_Encoding_DefaultXml, "QueryFirstResponse (XML Encoding)" }, + { OpcUaId_QueryNextRequest_Encoding_DefaultXml, "QueryNextRequest (XML Encoding)" }, + { OpcUaId_QueryNextResponse_Encoding_DefaultXml, "QueryNextResponse (XML Encoding)" }, + { OpcUaId_ReadRequest_Encoding_DefaultXml, "ReadRequest (XML Encoding)" }, + { OpcUaId_ReadResponse_Encoding_DefaultXml, "ReadResponse (XML Encoding)" }, + { OpcUaId_HistoryReadRequest_Encoding_DefaultXml, "HistoryReadRequest (XML Encoding)" }, + { OpcUaId_HistoryReadResponse_Encoding_DefaultXml, "HistoryReadResponse (XML Encoding)" }, + { OpcUaId_WriteRequest_Encoding_DefaultXml, "WriteRequest (XML Encoding)" }, + { OpcUaId_WriteResponse_Encoding_DefaultXml, "WriteResponse (XML Encoding)" }, + { OpcUaId_HistoryUpdateRequest_Encoding_DefaultXml, "HistoryUpdateRequest (XML Encoding)" }, + { OpcUaId_HistoryUpdateResponse_Encoding_DefaultXml, "HistoryUpdateResponse (XML Encoding)" }, + { OpcUaId_CallRequest_Encoding_DefaultXml, "CallRequest (XML Encoding)" }, + { OpcUaId_CallResponse_Encoding_DefaultXml, "CallResponse (XML Encoding)" }, + { OpcUaId_CreateMonitoredItemsRequest_Encoding_DefaultXml, "CreateMonitoredItemsRequest (XML Encoding)" }, + { OpcUaId_CreateMonitoredItemsResponse_Encoding_DefaultXml, "CreateMonitoredItemsResponse (XML Encoding)" }, + { OpcUaId_ModifyMonitoredItemsRequest_Encoding_DefaultXml, "ModifyMonitoredItemsRequest (XML Encoding)" }, + { OpcUaId_ModifyMonitoredItemsResponse_Encoding_DefaultXml, "ModifyMonitoredItemsResponse (XML Encoding)" }, + { OpcUaId_SetMonitoringModeRequest_Encoding_DefaultXml, "SetMonitoringModeRequest (XML Encoding)" }, + { OpcUaId_SetMonitoringModeResponse_Encoding_DefaultXml, "SetMonitoringModeResponse (XML Encoding)" }, + { OpcUaId_SetTriggeringRequest_Encoding_DefaultXml, "SetTriggeringRequest (XML Encoding)" }, + { OpcUaId_SetTriggeringResponse_Encoding_DefaultXml, "SetTriggeringResponse (XML Encoding)" }, + { OpcUaId_DeleteMonitoredItemsRequest_Encoding_DefaultXml, "DeleteMonitoredItemsRequest (XML Encoding)" }, + { OpcUaId_DeleteMonitoredItemsResponse_Encoding_DefaultXml, "DeleteMonitoredItemsResponse (XML Encoding)" }, + { OpcUaId_CreateSubscriptionRequest_Encoding_DefaultXml, "CreateSubscriptionRequest (XML Encoding)" }, + { OpcUaId_CreateSubscriptionResponse_Encoding_DefaultXml, "CreateSubscriptionResponse (XML Encoding)" }, + { OpcUaId_ModifySubscriptionRequest_Encoding_DefaultXml, "ModifySubscriptionRequest (XML Encoding)" }, + { OpcUaId_ModifySubscriptionResponse_Encoding_DefaultXml, "ModifySubscriptionResponse (XML Encoding)" }, + { OpcUaId_SetPublishingModeRequest_Encoding_DefaultXml, "SetPublishingModeRequest (XML Encoding)" }, + { OpcUaId_SetPublishingModeResponse_Encoding_DefaultXml, "SetPublishingModeResponse (XML Encoding)" }, + { OpcUaId_PublishRequest_Encoding_DefaultXml, "PublishRequest (XML Encoding)" }, + { OpcUaId_PublishResponse_Encoding_DefaultXml, "PublishResponse (XML Encoding)" }, + { OpcUaId_RepublishRequest_Encoding_DefaultXml, "RepublishRequest (XML Encoding)" }, + { OpcUaId_RepublishResponse_Encoding_DefaultXml, "RepublishResponse (XML Encoding)" }, + { OpcUaId_TransferSubscriptionsRequest_Encoding_DefaultXml, "TransferSubscriptionsRequest (XML Encoding)" }, + { OpcUaId_TransferSubscriptionsResponse_Encoding_DefaultXml, "TransferSubscriptionsResponse (XML Encoding)" }, + { OpcUaId_DeleteSubscriptionsRequest_Encoding_DefaultXml, "DeleteSubscriptionsRequest (XML Encoding)" }, + { OpcUaId_DeleteSubscriptionsResponse_Encoding_DefaultXml, "DeleteSubscriptionsResponse (XML Encoding)" }, + { OpcUaId_TestStackRequest_Encoding_DefaultXml, "TestStackRequest (XML Encoding)" }, + { OpcUaId_TestStackResponse_Encoding_DefaultXml, "TestStackResponse (XML Encoding)" }, + { OpcUaId_TestStackExRequest_Encoding_DefaultXml, "TestStackExRequest (XML Encoding)" }, + { OpcUaId_TestStackExResponse_Encoding_DefaultXml, "TestStackExResponse (XML Encoding)" }, + { 0, NULL } +}; + +/** Dispatch all services to a special parser function. */ +void dispatchService(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int ServiceId) +{ + int indx = 0; + + while (indx < g_NumServices) + { + if (g_arParserTable[indx].iRequestId == ServiceId) + { + (*g_arParserTable[indx].pParser)(tree, tvb, pinfo, pOffset); + break; + } + indx++; + } +} + diff --git a/plugins/epan/opcua/opcua_servicetable.h b/plugins/epan/opcua/opcua_servicetable.h new file mode 100644 index 00000000..0b614ae6 --- /dev/null +++ b/plugins/epan/opcua/opcua_servicetable.h @@ -0,0 +1,17 @@ +/****************************************************************************** +** Copyright (C) 2006-2009 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: Service table and service dispatcher. +** +******************************************************************************/ + +void dispatchService(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int ServiceId); + diff --git a/plugins/epan/opcua/opcua_simpletypes.c b/plugins/epan/opcua/opcua_simpletypes.c new file mode 100644 index 00000000..e913ac69 --- /dev/null +++ b/plugins/epan/opcua/opcua_simpletypes.c @@ -0,0 +1,1398 @@ +/****************************************************************************** +** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: Implementation of OpcUa built-in type parsers. +** This contains all the simple types and some complex types. +** +** Author: Gerhard Gappmeier +******************************************************************************/ + +#include "config.h" + +#include +#include +#include +#include +#include "opcua_simpletypes.h" +#include "opcua_hfindeces.h" +#include "opcua_statuscode.h" + +#define DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG 0x01 +#define DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE_FLAG 0x02 +#define DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT_FLAG 0x04 +#define DIAGNOSTICINFO_ENCODINGMASK_LOCALE_FLAG 0x08 +#define DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO_FLAG 0x10 +#define DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE_FLAG 0x20 +#define DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO_FLAG 0x40 +#define LOCALIZEDTEXT_ENCODINGBYTE_LOCALE 0x01 +#define LOCALIZEDTEXT_ENCODINGBYTE_TEXT 0x02 +#define NODEID_NAMESPACEURIFLAG 0x80 +#define NODEID_SERVERINDEXFLAG 0x40 +#define DATAVALUE_ENCODINGBYTE_VALUE 0x01 +#define DATAVALUE_ENCODINGBYTE_STATUSCODE 0x02 +#define DATAVALUE_ENCODINGBYTE_SOURCETIMESTAMP 0x04 +#define DATAVALUE_ENCODINGBYTE_SERVERTIMESTAMP 0x08 +#define DATAVALUE_ENCODINGBYTE_SOURCEPICOSECONDS 0x10 +#define DATAVALUE_ENCODINGBYTE_SERVERPICOSECONDS 0x20 +#define EXTOBJ_ENCODINGMASK_BINBODY_FLAG 0x01 +#define EXTOBJ_ENCODINGMASK_XMLBODY_FLAG 0x02 +#define STATUSCODE_STRUCTURECHANGED 0x8000 +#define STATUSCODE_SEMANTICSCHANGED 0x4000 +#define STATUSCODE_INFOTYPE_DATAVALUE 0x00000400 +#define STATUSCODE_INFOBIT_OVERFLOW 0x0080 +#define STATUSCODE_INFOBIT_HISTORIAN_PARTIAL 0x0004 +#define STATUSCODE_INFOBIT_HISTORIAN_EXTRADATA 0x0008 +#define STATUSCODE_INFOBIT_HISTORIAN_MULTIVALUE 0x0010 +#define RETURNDIAGNOSTICS_SERVICELEVEL_SYMBOLICID 0x0001 +#define RETURNDIAGNOSTICS_SERVICELEVEL_LOCALIZEDTEXT 0x0002 +#define RETURNDIAGNOSTICS_SERVICELEVEL_ADDITIONALINFO 0x0004 +#define RETURNDIAGNOSTICS_SERVICELEVEL_INNERSTATUSCODE 0x0008 +#define RETURNDIAGNOSTICS_SERVICELEVEL_INNERDIAGNOSTICS 0x0010 +#define RETURNDIAGNOSTICS_OPERATIONLEVEL_SYMBOLICID 0x0020 +#define RETURNDIAGNOSTICS_OPERATIONLEVEL_LOCALIZEDTEXT 0x0040 +#define RETURNDIAGNOSTICS_OPERATIONLEVEL_ADDITIONALINFO 0x0080 +#define RETURNDIAGNOSTICS_OPERATIONLEVEL_INNERSTATUSCODE 0x0100 +#define RETURNDIAGNOSTICS_OPERATIONLEVEL_INNERDIAGNOSTICS 0x0200 +#define NODECLASSMASK_ALL 0x0000 +#define NODECLASSMASK_OBJECT 0x0001 +#define NODECLASSMASK_VARIABLE 0x0002 +#define NODECLASSMASK_METHOD 0x0004 +#define NODECLASSMASK_OBJECTTYPE 0x0008 +#define NODECLASSMASK_VARIABLETYPE 0x0010 +#define NODECLASSMASK_REFERENCETYPE 0x0020 +#define NODECLASSMASK_DATATYPE 0x0040 +#define NODECLASSMASK_VIEW 0x0080 +#define RESULTMASK_REFERENCETYPE 0x0001 +#define RESULTMASK_ISFORWARD 0x0002 +#define RESULTMASK_NODECLASS 0x0004 +#define RESULTMASK_BROWSENAME 0x0008 +#define RESULTMASK_DISPLAYNAME 0x0010 +#define RESULTMASK_TYPEDEFINITION 0x0020 +#define RESULTMASK_ALL 0x003F + + +/* Chosen arbitrarily */ +#define MAX_ARRAY_LEN 10000 +#define MAX_NESTING_DEPTH 100 + +static int hf_opcua_diag_mask = -1; +static int hf_opcua_diag_mask_symbolicflag = -1; +static int hf_opcua_diag_mask_namespaceflag = -1; +static int hf_opcua_diag_mask_localizedtextflag = -1; +static int hf_opcua_diag_mask_localeflag = -1; +static int hf_opcua_diag_mask_additionalinfoflag = -1; +static int hf_opcua_diag_mask_innerstatuscodeflag = -1; +static int hf_opcua_diag_mask_innerdiaginfoflag = -1; +static int hf_opcua_loctext_mask = -1; +static int hf_opcua_loctext_mask_localeflag = -1; +static int hf_opcua_loctext_mask_textflag = -1; +static int hf_opcua_datavalue_mask = -1; +static int hf_opcua_datavalue_mask_valueflag = -1; +static int hf_opcua_datavalue_mask_statuscodeflag = -1; +static int hf_opcua_datavalue_mask_sourcetimestampflag = -1; +static int hf_opcua_datavalue_mask_servertimestampflag = -1; +static int hf_opcua_datavalue_mask_sourcepicoseconds = -1; +static int hf_opcua_datavalue_mask_serverpicoseconds = -1; +static int hf_opcua_nodeid_encodingmask = -1; +static int hf_opcua_expandednodeid_mask = -1; +static int hf_opcua_expandednodeid_mask_namespaceuri = -1; +static int hf_opcua_expandednodeid_mask_serverindex = -1; +static int hf_opcua_variant_encodingmask = -1; +static int hf_opcua_nodeid_nsindex = -1; +static int hf_opcua_nodeid_numeric = -1; +static int hf_opcua_nodeid_string = -1; +static int hf_opcua_nodeid_guid = -1; +static int hf_opcua_nodeid_bytestring = -1; +static int hf_opcua_localizedtext_locale = -1; +static int hf_opcua_localizedtext_text = -1; +static int hf_opcua_qualifiedname_id = -1; +static int hf_opcua_qualifiedname_name = -1; +static int hf_opcua_SourceTimestamp = -1; +static int hf_opcua_SourcePicoseconds = -1; +static int hf_opcua_ServerTimestamp = -1; +static int hf_opcua_ServerPicoseconds = -1; +static int hf_opcua_diag_symbolicid = -1; +static int hf_opcua_diag_namespace = -1; +static int hf_opcua_diag_localizedtext = -1; +static int hf_opcua_diag_locale = -1; +static int hf_opcua_diag_additionalinfo = -1; +static int hf_opcua_diag_innerstatuscode = -1; +static int hf_opcua_extobj_mask = -1; +static int hf_opcua_extobj_mask_binbodyflag = -1; +static int hf_opcua_extobj_mask_xmlbodyflag = -1; +static int hf_opcua_ArraySize = -1; +static int hf_opcua_ServerIndex = -1; +static int hf_opcua_status_StructureChanged = -1; +static int hf_opcua_status_SemanticsChanged = -1; +static int hf_opcua_status_InfoBit_Limit_Overflow = -1; +static int hf_opcua_status_InfoBit_Historian_Partial = -1; +static int hf_opcua_status_InfoBit_Historian_ExtraData = -1; +static int hf_opcua_status_InfoBit_Historian_MultiValue = -1; +static int hf_opcua_status_InfoType = -1; +static int hf_opcua_status_Limit = -1; +static int hf_opcua_status_Historian = -1; +int hf_opcua_returnDiag = -1; +int hf_opcua_returnDiag_mask_sl_symbolicId = -1; +int hf_opcua_returnDiag_mask_sl_localizedText = -1; +int hf_opcua_returnDiag_mask_sl_additionalinfo = -1; +int hf_opcua_returnDiag_mask_sl_innerstatuscode = -1; +int hf_opcua_returnDiag_mask_sl_innerdiagnostics = -1; +int hf_opcua_returnDiag_mask_ol_symbolicId = -1; +int hf_opcua_returnDiag_mask_ol_localizedText = -1; +int hf_opcua_returnDiag_mask_ol_additionalinfo = -1; +int hf_opcua_returnDiag_mask_ol_innerstatuscode = -1; +int hf_opcua_returnDiag_mask_ol_innerdiagnostics = -1; +int hf_opcua_nodeClassMask = -1; +int hf_opcua_nodeClassMask_all = -1; +int hf_opcua_nodeClassMask_object = -1; +int hf_opcua_nodeClassMask_variable = -1; +int hf_opcua_nodeClassMask_method = -1; +int hf_opcua_nodeClassMask_objecttype = -1; +int hf_opcua_nodeClassMask_variabletype = -1; +int hf_opcua_nodeClassMask_referencetype = -1; +int hf_opcua_nodeClassMask_datatype = -1; +int hf_opcua_nodeClassMask_view = -1; +int hf_opcua_resultMask = -1; +int hf_opcua_resultMask_all = -1; +int hf_opcua_resultMask_referencetype = -1; +int hf_opcua_resultMask_isforward = -1; +int hf_opcua_resultMask_nodeclass = -1; +int hf_opcua_resultMask_browsename = -1; +int hf_opcua_resultMask_displayname = -1; +int hf_opcua_resultMask_typedefinition = -1; + +static expert_field ei_array_length = EI_INIT; +static expert_field ei_nesting_depth = EI_INIT; + +extern int proto_opcua; + +/** NodeId encoding mask table */ +static const value_string g_nodeidmasks[] = { + { 0x00, "Two byte encoded Numeric" }, + { 0x01, "Four byte encoded Numeric" }, + { 0x02, "Numeric of arbitrary length" }, + { 0x03, "String" }, + { 0x04, "GUID" }, + { 0x05, "Opaque" }, + { 0, NULL } +}; + +/** StatusCode info types */ +static const value_string g_infotype[] = { + { 0x00, "Not used" }, + { 0x01, "DataValue" }, + { 0x02, "Reserved" }, + { 0x03, "Reserved" }, + { 0, NULL } +}; + +/** StatusCode Limit types */ +static const value_string g_limit[] = { + { 0x00, "None" }, + { 0x01, "Low" }, + { 0x02, "High" }, + { 0x03, "Constant" }, + { 0, NULL } +}; + +/** StatusCode Historian types */ +static const value_string g_historian[] = { + { 0x00, "Raw" }, + { 0x01, "Calculated" }, + { 0x02, "Interpolated" }, + { 0x03, "Reserved" }, + { 0, NULL } +}; + +/** UA Variant Type enum */ +typedef enum _OpcUa_BuiltInType +{ + OpcUaType_Null = 0, + OpcUaType_Boolean = 1, + OpcUaType_SByte = 2, + OpcUaType_Byte = 3, + OpcUaType_Int16 = 4, + OpcUaType_UInt16 = 5, + OpcUaType_Int32 = 6, + OpcUaType_UInt32 = 7, + OpcUaType_Int64 = 8, + OpcUaType_UInt64 = 9, + OpcUaType_Float = 10, + OpcUaType_Double = 11, + OpcUaType_String = 12, + OpcUaType_DateTime = 13, + OpcUaType_Guid = 14, + OpcUaType_ByteString = 15, + OpcUaType_XmlElement = 16, + OpcUaType_NodeId = 17, + OpcUaType_ExpandedNodeId = 18, + OpcUaType_StatusCode = 19, + OpcUaType_QualifiedName = 20, + OpcUaType_LocalizedText = 21, + OpcUaType_ExtensionObject = 22, + OpcUaType_DataValue = 23, + OpcUaType_Variant = 24, + OpcUaType_DiagnosticInfo = 25 +} +OpcUa_BuiltInType; + +/** Variant encoding mask table */ +static const value_string g_VariantTypes[] = { + { 0, "Null" }, + { 1, "Boolean" }, + { 2, "SByte" }, + { 3, "Byte" }, + { 4, "Int16" }, + { 5, "UInt16" }, + { 6, "Int32" }, + { 7, "UInt32" }, + { 8, "Int64" }, + { 9, "UInt64" }, + { 10, "Float" }, + { 11, "Double" }, + { 12, "String" }, + { 13, "DateTime" }, + { 14, "Guid" }, + { 15, "ByteString" }, + { 16, "XmlElement" }, + { 17, "NodeId" }, + { 18, "ExpandedNodeId" }, + { 19, "StatusCode" }, + { 20, "QualifiedName" }, + { 21, "LocalizedText" }, + { 22, "ExtensionObject" }, + { 23, "DataValue" }, + { 24, "Variant" }, + { 25, "DiagnosticInfo" }, + { 0x80, "Array of Null" }, + { 0x80+1, "Array of Boolean" }, + { 0x80+2, "Array of SByte" }, + { 0x80+3, "Array of Byte" }, + { 0x80+4, "Array of Int16" }, + { 0x80+5, "Array of UInt16" }, + { 0x80+6, "Array of Int32" }, + { 0x80+7, "Array of UInt32" }, + { 0x80+8, "Array of Int64" }, + { 0x80+9, "Array of UInt64" }, + { 0x80+10, "Array of Float" }, + { 0x80+11, "Array of Double" }, + { 0x80+12, "Array of String" }, + { 0x80+13, "Array of DateTime" }, + { 0x80+14, "Array of Guid" }, + { 0x80+15, "Array of ByteString" }, + { 0x80+16, "Array of XmlElement" }, + { 0x80+17, "Array of NodeId" }, + { 0x80+18, "Array of ExpandedNodeId" }, + { 0x80+19, "Array of StatusCode" }, + { 0x80+20, "Array of QualifiedName" }, + { 0x80+21, "Array of LocalizedText" }, + { 0x80+22, "Array of ExtensionObject" }, + { 0x80+23, "Array of DataValue" }, + { 0x80+24, "Array of Variant" }, + { 0x80+25, "Array of DiagnosticInfo" }, + { 0xC0, "Matrix of Null" }, + { 0xC0+1, "Matrix of Boolean" }, + { 0xC0+2, "Matrix of SByte" }, + { 0xC0+3, "Matrix of Byte" }, + { 0xC0+4, "Matrix of Int16" }, + { 0xC0+5, "Matrix of UInt16" }, + { 0xC0+6, "Matrix of Int32" }, + { 0xC0+7, "Matrix of UInt32" }, + { 0xC0+8, "Matrix of Int64" }, + { 0xC0+9, "Matrix of UInt64" }, + { 0xC0+10, "Matrix of Float" }, + { 0xC0+11, "Matrix of Double" }, + { 0xC0+12, "Matrix of String" }, + { 0xC0+13, "Matrix of DateTime" }, + { 0xC0+14, "Matrix of Guid" }, + { 0xC0+15, "Matrix of ByteString" }, + { 0xC0+16, "Matrix of XmlElement" }, + { 0xC0+17, "Matrix of NodeId" }, + { 0xC0+18, "Matrix of ExpandedNodeId" }, + { 0xC0+19, "Matrix of StatusCode" }, + { 0xC0+20, "Matrix of QualifiedName" }, + { 0xC0+21, "Matrix of LocalizedText" }, + { 0xC0+22, "Matrix of ExtensionObject" }, + { 0xC0+23, "Matrix of DataValue" }, + { 0xC0+24, "Matrix of Variant" }, + { 0xC0+25, "Matrix of DiagnosticInfo" }, + { 0, NULL } +}; +#define VARIANT_ARRAYDIMENSIONS 0x40 +#define VARIANT_ARRAYMASK 0x80 + +/** BrowseRequest's BrowseDescription's NodeClassMaskTable enum table */ +static const value_string g_NodeClassMask[] = { + { NODECLASSMASK_ALL, "All" }, + { 0, NULL } +}; + +/* BrowseRequest's BrowseDescription's ResultMaskTable enum table */ +static const value_string g_ResultMask[] = { + { RESULTMASK_ALL, "All" }, + { 0, NULL } +}; + +/* trees */ +static gint ett_opcua_diagnosticinfo = -1; +static gint ett_opcua_diagnosticinfo_encodingmask = -1; +static gint ett_opcua_nodeid = -1; +static gint ett_opcua_expandednodeid = -1; +static gint ett_opcua_expandednodeid_encodingmask = -1; +static gint ett_opcua_localizedtext = -1; +static gint ett_opcua_localizedtext_encodingmask = -1; +static gint ett_opcua_qualifiedname = -1; +static gint ett_opcua_datavalue = -1; +static gint ett_opcua_datavalue_encodingmask = -1; +static gint ett_opcua_variant = -1; +static gint ett_opcua_variant_arraydims = -1; +static gint ett_opcua_extensionobject = -1; +static gint ett_opcua_extensionobject_encodingmask = -1; +static gint ett_opcua_statuscode = -1; +static gint ett_opcua_statuscode_info = -1; +gint ett_opcua_array_Boolean = -1; +gint ett_opcua_array_SByte = -1; +gint ett_opcua_array_Byte = -1; +gint ett_opcua_array_Int16 = -1; +gint ett_opcua_array_UInt16 = -1; +gint ett_opcua_array_Int32 = -1; +gint ett_opcua_array_UInt32 = -1; +gint ett_opcua_array_Int64 = -1; +gint ett_opcua_array_UInt64 = -1; +gint ett_opcua_array_Float = -1; +gint ett_opcua_array_Double = -1; +gint ett_opcua_array_String = -1; +gint ett_opcua_array_DateTime = -1; +gint ett_opcua_array_Guid = -1; +gint ett_opcua_array_ByteString = -1; +gint ett_opcua_array_XmlElement = -1; +gint ett_opcua_array_NodeId = -1; +gint ett_opcua_array_ExpandedNodeId = -1; +gint ett_opcua_array_StatusCode = -1; +gint ett_opcua_array_DiagnosticInfo = -1; +gint ett_opcua_array_QualifiedName = -1; +gint ett_opcua_array_LocalizedText = -1; +gint ett_opcua_array_ExtensionObject = -1; +gint ett_opcua_array_DataValue = -1; +gint ett_opcua_array_Variant = -1; +gint ett_opcua_returnDiagnostics = -1; +gint ett_opcua_nodeClassMask = -1; +gint ett_opcua_resultMask = -1; + +static gint *ett[] = +{ + &ett_opcua_diagnosticinfo, + &ett_opcua_diagnosticinfo_encodingmask, + &ett_opcua_nodeid, + &ett_opcua_expandednodeid, + &ett_opcua_expandednodeid_encodingmask, + &ett_opcua_localizedtext, + &ett_opcua_localizedtext_encodingmask, + &ett_opcua_qualifiedname, + &ett_opcua_datavalue, + &ett_opcua_datavalue_encodingmask, + &ett_opcua_variant, + &ett_opcua_variant_arraydims, + &ett_opcua_extensionobject, + &ett_opcua_extensionobject_encodingmask, + &ett_opcua_statuscode, + &ett_opcua_statuscode_info, + &ett_opcua_array_Boolean, + &ett_opcua_array_SByte, + &ett_opcua_array_Byte, + &ett_opcua_array_Int16, + &ett_opcua_array_UInt16, + &ett_opcua_array_Int32, + &ett_opcua_array_UInt32, + &ett_opcua_array_Int64, + &ett_opcua_array_UInt64, + &ett_opcua_array_Float, + &ett_opcua_array_Double, + &ett_opcua_array_String, + &ett_opcua_array_DateTime, + &ett_opcua_array_Guid, + &ett_opcua_array_ByteString, + &ett_opcua_array_XmlElement, + &ett_opcua_array_NodeId, + &ett_opcua_array_ExpandedNodeId, + &ett_opcua_array_StatusCode, + &ett_opcua_array_DiagnosticInfo, + &ett_opcua_array_QualifiedName, + &ett_opcua_array_LocalizedText, + &ett_opcua_array_ExtensionObject, + &ett_opcua_array_DataValue, + &ett_opcua_array_Variant, + &ett_opcua_returnDiagnostics, + &ett_opcua_nodeClassMask, + &ett_opcua_resultMask +}; + +void registerSimpleTypes(int proto) +{ + expert_module_t* expert_proto; + + static hf_register_info hf[] = + { + /* id full name abbreviation type display strings bitmask blurb HFILL */ + {&hf_opcua_diag_mask, {"EncodingMask", "opcua.diag.mask", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_diag_mask_symbolicflag, {"has symbolic id", "opcua.diag.has_symbolic_id", FT_BOOLEAN, 8, NULL, DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG, NULL, HFILL}}, + {&hf_opcua_diag_mask_namespaceflag, {"has namespace", "opcua.diag.has_namespace", FT_BOOLEAN, 8, NULL, DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE_FLAG, NULL, HFILL}}, + {&hf_opcua_diag_mask_localizedtextflag, {"has localizedtext", "opcua.diag.has_localizedtext", FT_BOOLEAN, 8, NULL, DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT_FLAG, NULL, HFILL}}, + {&hf_opcua_diag_mask_localeflag, {"has locale", "opcua.diag.has_locale", FT_BOOLEAN, 8, NULL, DIAGNOSTICINFO_ENCODINGMASK_LOCALE_FLAG, NULL, HFILL}}, + {&hf_opcua_diag_mask_additionalinfoflag, {"has additional info", "opcua.diag.has_additional_info", FT_BOOLEAN, 8, NULL, DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO_FLAG, NULL, HFILL}}, + {&hf_opcua_diag_mask_innerstatuscodeflag, {"has inner statuscode", "opcua.diag.has_inner_statuscode", FT_BOOLEAN, 8, NULL, DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE_FLAG, NULL, HFILL}}, + {&hf_opcua_diag_mask_innerdiaginfoflag, {"has inner diagnostic info", "opcua.diag.has_inner_diagnostic_code", FT_BOOLEAN, 8, NULL, DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO_FLAG, NULL, HFILL}}, + {&hf_opcua_loctext_mask, {"EncodingMask", "opcua.loctext.mask", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_loctext_mask_localeflag, {"has locale information", "opcua.loctext.has_locale_information", FT_BOOLEAN, 8, NULL, LOCALIZEDTEXT_ENCODINGBYTE_LOCALE, NULL, HFILL}}, + {&hf_opcua_loctext_mask_textflag, {"has text", "opcua.loctext.has_text", FT_BOOLEAN, 8, NULL, LOCALIZEDTEXT_ENCODINGBYTE_TEXT, NULL, HFILL}}, + {&hf_opcua_nodeid_encodingmask, {"EncodingMask", "opcua.nodeid.encodingmask", FT_UINT8, BASE_HEX, VALS(g_nodeidmasks), 0x0F, NULL, HFILL}}, + {&hf_opcua_nodeid_nsindex, {"Namespace Index", "opcua.nodeid.nsindex", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_nodeid_numeric, {"Identifier Numeric", "opcua.nodeid.numeric", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_nodeid_string, {"Identifier String", "opcua.nodeid.string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_nodeid_guid, {"Identifier Guid", "opcua.nodeid.guid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_nodeid_bytestring, {"Identifier ByteString", "opcua.nodeid.bytestring", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_expandednodeid_mask, {"EncodingMask", "opcua.expandednodeid.mask", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_expandednodeid_mask_namespaceuri, {"has namespace uri", "opcua.expandednodeid.has_namespace_uri", FT_BOOLEAN, 8, NULL, NODEID_NAMESPACEURIFLAG, NULL, HFILL}}, + {&hf_opcua_expandednodeid_mask_serverindex, {"has server index", "opcua.expandednodeid.has_server_index", FT_BOOLEAN, 8, NULL, NODEID_SERVERINDEXFLAG, NULL, HFILL}}, + {&hf_opcua_localizedtext_locale, {"Locale", "opcua.loctext.Locale", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_localizedtext_text, {"Text", "opcua.loctext.Text", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_qualifiedname_id, {"Id", "opcua.qualname.Id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_qualifiedname_name, {"Name", "opcua.qualname.Name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_datavalue_mask, {"EncodingMask", "opcua.datavalue.mask", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_datavalue_mask_valueflag, {"has value", "opcua.datavalue.has_value", FT_BOOLEAN, 8, NULL, DATAVALUE_ENCODINGBYTE_VALUE, NULL, HFILL}}, + {&hf_opcua_datavalue_mask_statuscodeflag, {"has statuscode", "opcua.datavalue.has_statuscode", FT_BOOLEAN, 8, NULL, DATAVALUE_ENCODINGBYTE_STATUSCODE, NULL, HFILL}}, + {&hf_opcua_datavalue_mask_sourcetimestampflag, {"has source timestamp", "opcua.datavalue.has_source_timestamp", FT_BOOLEAN, 8, NULL, DATAVALUE_ENCODINGBYTE_SOURCETIMESTAMP, NULL, HFILL}}, + {&hf_opcua_datavalue_mask_servertimestampflag, {"has server timestamp", "opcua.datavalue.has_server_timestamp", FT_BOOLEAN, 8, NULL, DATAVALUE_ENCODINGBYTE_SERVERTIMESTAMP, NULL, HFILL}}, + {&hf_opcua_datavalue_mask_sourcepicoseconds, {"has source picoseconds", "opcua.datavalue.has_source_picoseconds", FT_BOOLEAN, 8, NULL, DATAVALUE_ENCODINGBYTE_SOURCEPICOSECONDS, NULL, HFILL}}, + {&hf_opcua_datavalue_mask_serverpicoseconds, {"has server picoseconds", "opcua.datavalue.has_server_picoseconds", FT_BOOLEAN, 8, NULL, DATAVALUE_ENCODINGBYTE_SERVERPICOSECONDS, NULL, HFILL}}, + {&hf_opcua_variant_encodingmask, {"Variant Type", "opcua.variant.has_value", FT_UINT8, BASE_HEX, VALS(g_VariantTypes), 0x0, NULL, HFILL}}, + {&hf_opcua_SourceTimestamp, {"SourceTimestamp", "opcua.datavalue.SourceTimestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_SourcePicoseconds, {"SourcePicoseconds", "opcua.datavalue.SourcePicoseconds", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_ServerTimestamp, {"ServerTimestamp", "opcua.datavalue.ServerTimestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_ServerPicoseconds, {"ServerPicoseconds", "opcua.datavalue.ServerPicoseconds", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_diag_symbolicid, {"SymbolicId", "opcua.diag.SymbolicId", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_diag_namespace, {"Namespace", "opcua.diag.Namespace", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_diag_localizedtext, {"LocalizedText", "opcua.diag.LocalizedText", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_diag_locale, {"Locale", "opcua.diag.Locale", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_diag_additionalinfo, {"AdditionalInfo", "opcua.diag.AdditionalInfo", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_diag_innerstatuscode, {"InnerStatusCode", "opcua.diag.InnerStatusCode", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_extobj_mask, {"EncodingMask", "opcua.extobj.mask", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_extobj_mask_binbodyflag, {"has binary body", "opcua.extobj.has_binary_body", FT_BOOLEAN, 8, NULL, EXTOBJ_ENCODINGMASK_BINBODY_FLAG, NULL, HFILL}}, + {&hf_opcua_extobj_mask_xmlbodyflag, {"has xml body", "opcua.extobj.has_xml_body", FT_BOOLEAN, 8, NULL, EXTOBJ_ENCODINGMASK_XMLBODY_FLAG, NULL, HFILL}}, + {&hf_opcua_ArraySize, {"ArraySize", "opcua.variant.ArraySize", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_ServerIndex, {"ServerIndex", "opcua.expandednodeid.ServerIndex", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_status_StructureChanged, {"StructureChanged", "opcua.statuscode.structureChanged", FT_BOOLEAN, 16, NULL, STATUSCODE_STRUCTURECHANGED, NULL, HFILL}}, + {&hf_opcua_status_SemanticsChanged, {"SemanticsChanged", "opcua.statuscode.semanticsChanged", FT_BOOLEAN, 16, NULL, STATUSCODE_SEMANTICSCHANGED, NULL, HFILL}}, + {&hf_opcua_status_InfoBit_Limit_Overflow, {"Overflow", "opcua.statuscode.overflow", FT_BOOLEAN, 16, NULL, STATUSCODE_INFOBIT_OVERFLOW, NULL, HFILL}}, + {&hf_opcua_status_InfoBit_Historian_Partial, {"HistorianBit: Partial", "opcua.statuscode.historian.partial", FT_BOOLEAN, 16, NULL, STATUSCODE_INFOBIT_HISTORIAN_PARTIAL, NULL, HFILL}}, + {&hf_opcua_status_InfoBit_Historian_ExtraData, {"HistorianBit: ExtraData", "opcua.statuscode.historian.extraData", FT_BOOLEAN, 16, NULL, STATUSCODE_INFOBIT_HISTORIAN_EXTRADATA, NULL, HFILL}}, + {&hf_opcua_status_InfoBit_Historian_MultiValue, {"HistorianBit: MultiValue", "opcua.statuscode.historian.multiValue", FT_BOOLEAN, 16, NULL, STATUSCODE_INFOBIT_HISTORIAN_MULTIVALUE, NULL, HFILL}}, + {&hf_opcua_status_InfoType, {"InfoType", "opcua.statuscode.infoType", FT_UINT16, BASE_HEX, VALS(g_infotype), 0x0C00, NULL, HFILL}}, + {&hf_opcua_status_Limit, {"Limit", "opcua.statuscode.limit", FT_UINT16, BASE_HEX, VALS(g_limit), 0x0300, NULL, HFILL}}, + {&hf_opcua_status_Historian, {"Historian", "opcua.statuscode.historian", FT_UINT16, BASE_HEX, VALS(g_historian), 0x0003, NULL, HFILL}}, + {&hf_opcua_returnDiag, {"Return Diagnostics", "opcua.returndiag", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_sl_symbolicId, {"ServiceLevel / SymbolicId", "opcua.returndiag.servicelevel.symbolicid", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_SERVICELEVEL_SYMBOLICID, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_sl_localizedText, {"ServiceLevel / LocalizedText", "opcua.returndiag.servicelevel.localizedtext", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_SERVICELEVEL_LOCALIZEDTEXT, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_sl_additionalinfo, {"ServiceLevel / AdditionalInfo", "opcua.returndiag.servicelevel.additionalinfo", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_SERVICELEVEL_ADDITIONALINFO, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_sl_innerstatuscode, {"ServiceLevel / Inner StatusCode", "opcua.returndiag.servicelevel.innerstatuscode", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_SERVICELEVEL_INNERSTATUSCODE, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_sl_innerdiagnostics, {"ServiceLevel / Inner Diagnostics", "opcua.returndiag.servicelevel.innerdiagnostics", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_SERVICELEVEL_INNERDIAGNOSTICS, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_ol_symbolicId, {"OperationLevel / SymbolicId", "opcua.returndiag.operationlevel.symbolicid", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_OPERATIONLEVEL_SYMBOLICID, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_ol_localizedText, {"OperationLevel / LocalizedText", "opcua.returndiag.operationlevel.localizedtext", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_OPERATIONLEVEL_LOCALIZEDTEXT, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_ol_additionalinfo, {"OperationLevel / AdditionalInfo", "opcua.returndiag.operationlevel.additionalinfo", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_OPERATIONLEVEL_ADDITIONALINFO, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_ol_innerstatuscode, {"OperationLevel / Inner StatusCode", "opcua.returndiag.operationlevel.innerstatuscode", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_OPERATIONLEVEL_INNERSTATUSCODE, NULL, HFILL}}, + {&hf_opcua_returnDiag_mask_ol_innerdiagnostics, {"OperationLevel / Inner Diagnostics", "opcua.returndiag.operationlevel.innerdiagnostics", FT_BOOLEAN, 16, NULL, RETURNDIAGNOSTICS_OPERATIONLEVEL_INNERDIAGNOSTICS, NULL, HFILL}}, + {&hf_opcua_nodeClassMask, {"Node Class Mask", "opcua.nodeclassmask", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_all, {"Node Class Mask", "opcua.nodeclassmask.all", FT_UINT32, BASE_HEX, VALS(g_NodeClassMask), 0x0, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_object, {"Object", "opcua.nodeclassmask.object", FT_BOOLEAN, 16, NULL, NODECLASSMASK_OBJECT, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_variable, {"Variable", "opcua.nodeclassmask.variable", FT_BOOLEAN, 16, NULL, NODECLASSMASK_VARIABLE, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_method, {"Method", "opcua.nodeclassmask.method", FT_BOOLEAN, 16, NULL, NODECLASSMASK_METHOD, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_objecttype, {"ObjectType", "opcua.nodeclassmask.objecttype", FT_BOOLEAN, 16, NULL, NODECLASSMASK_OBJECTTYPE, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_variabletype, {"VariableType", "opcua.nodeclassmask.variabletype", FT_BOOLEAN, 16, NULL, NODECLASSMASK_VARIABLETYPE, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_referencetype, {"ReferenceType", "opcua.nodeclassmask.referencetype", FT_BOOLEAN, 16, NULL, NODECLASSMASK_REFERENCETYPE, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_datatype, {"DataType", "opcua.nodeclassmask.datatype", FT_BOOLEAN, 16, NULL, NODECLASSMASK_DATATYPE, NULL, HFILL}}, + {&hf_opcua_nodeClassMask_view, {"View", "opcua.nodeclassmask.view", FT_BOOLEAN, 16, NULL, NODECLASSMASK_VIEW, NULL, HFILL}}, + {&hf_opcua_resultMask, {"Result Mask", "opcua.resultmask", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_resultMask_referencetype, {"Reference Type", "opcua.resultmask.referencetype", FT_BOOLEAN, 16, NULL, RESULTMASK_REFERENCETYPE, NULL, HFILL}}, + {&hf_opcua_resultMask_isforward, {"Is Forward", "opcua.resultmask.isforward", FT_BOOLEAN, 16, NULL, RESULTMASK_ISFORWARD, NULL, HFILL}}, + {&hf_opcua_resultMask_nodeclass, {"Node Class", "opcua.resultmask.nodeclass", FT_BOOLEAN, 16, NULL, RESULTMASK_NODECLASS, NULL, HFILL}}, + {&hf_opcua_resultMask_browsename, {"Browse Name", "opcua.resultmask.browsename", FT_BOOLEAN, 16, NULL, RESULTMASK_BROWSENAME, NULL, HFILL}}, + {&hf_opcua_resultMask_displayname, {"Display Name", "opcua.resultmask.displayname", FT_BOOLEAN, 16, NULL, RESULTMASK_DISPLAYNAME, NULL, HFILL}}, + {&hf_opcua_resultMask_typedefinition, {"Type Definition", "opcua.resultmask.typedefinition", FT_BOOLEAN, 16, NULL, RESULTMASK_TYPEDEFINITION, NULL, HFILL}}, + {&hf_opcua_resultMask_all, {"Result Mask", "opcua.resultmask.all", FT_UINT32, BASE_HEX, VALS(g_ResultMask), 0x0, NULL, HFILL}}, + }; + + static ei_register_info ei[] = { + { &ei_array_length, { "opcua.array.length", PI_UNDECODED, PI_ERROR, "Max array length exceeded", EXPFILL }}, + { &ei_nesting_depth, { "opcua.nestingdepth", PI_UNDECODED, PI_ERROR, "Max nesting depth exceeded", EXPFILL }}, + }; + + proto_register_field_array(proto, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + expert_proto = expert_register_protocol(proto); + expert_register_field_array(expert_proto, ei, array_length(ei)); +} + +proto_item* parseBoolean(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 1, ENC_LITTLE_ENDIAN); + *pOffset+=1; + return item; +} + +proto_item* parseByte(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 1, ENC_LITTLE_ENDIAN); + *pOffset+=1; + return item; +} + +proto_item* parseSByte(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 1, ENC_LITTLE_ENDIAN); + *pOffset+=1; + return item; +} + +proto_item* parseUInt16(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 2, ENC_LITTLE_ENDIAN); + *pOffset+=2; + return item; +} + +proto_item* parseInt16(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 2, ENC_LITTLE_ENDIAN); + *pOffset+=2; + return item; +} + +proto_item* parseUInt32(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); + *pOffset+=4; + return item; +} + +proto_item* parseInt32(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); + *pOffset+=4; + return item; +} + +proto_item* parseUInt64(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 8, ENC_LITTLE_ENDIAN); + *pOffset+=8; + return item; +} + +proto_item* parseInt64(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 8, ENC_LITTLE_ENDIAN); + *pOffset+=8; + return item; +} + +proto_item* parseString(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = NULL; + char *szValue; + gint iOffset = *pOffset; + gint32 iLen = tvb_get_letohl(tvb, *pOffset); + iOffset+=4; + + if (iLen == -1) + { + item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 0, ENC_NA); + proto_item_append_text(item, "[OpcUa Null String]"); + proto_item_set_end(item, tvb, *pOffset + 4); + } + else if (iLen == 0) + { + item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 0, ENC_NA); + proto_item_append_text(item, "[OpcUa Empty String]"); + proto_item_set_end(item, tvb, *pOffset + 4); + } + else if (iLen > 0) + { + item = proto_tree_add_item(tree, hfIndex, tvb, iOffset, iLen, ENC_UTF_8|ENC_NA); + iOffset += iLen; /* eat the whole string */ + } + else + { + item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 0, ENC_NA); + szValue = wmem_strdup_printf(pinfo->pool, "[Invalid String] Invalid length: %d", iLen); + proto_item_append_text(item, "%s", szValue); + proto_item_set_end(item, tvb, *pOffset + 4); + } + + *pOffset = iOffset; + return item; +} + +proto_item* parseStatusCode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = NULL; + guint32 uStatusCode = 0; + const gchar *szStatusCode = NULL; + + item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); + + uStatusCode = tvb_get_letohl(tvb, *pOffset); + szStatusCode = val_to_str_const(uStatusCode & 0xFFFF0000, g_statusCodes, "Unknown Status Code"); + proto_item_append_text(item, " [%s]", szStatusCode); + + /* check for status code info flags */ + if (uStatusCode & 0x0000FFFF) + { + gint iOffset = *pOffset; + proto_tree *flags_tree; + proto_item *ti_inner; + + flags_tree = proto_item_add_subtree(item, ett_opcua_statuscode); + + proto_tree_add_item(flags_tree, hf_opcua_status_StructureChanged, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(flags_tree, hf_opcua_status_SemanticsChanged, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + ti_inner = proto_tree_add_item(flags_tree, hf_opcua_status_InfoType, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + + switch (uStatusCode & 0x00000C00) + { + case STATUSCODE_INFOTYPE_DATAVALUE: + { + /* InfoType == DataValue */ + proto_tree *tree_inner; + + tree_inner = proto_item_add_subtree(ti_inner, ett_opcua_statuscode_info); + + proto_tree_add_item(tree_inner, hf_opcua_status_Limit, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree_inner, hf_opcua_status_InfoBit_Limit_Overflow, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree_inner, hf_opcua_status_InfoBit_Historian_MultiValue, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree_inner, hf_opcua_status_InfoBit_Historian_ExtraData, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree_inner, hf_opcua_status_InfoBit_Historian_Partial, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree_inner, hf_opcua_status_Historian, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + } + default: + break; + } + } + + *pOffset += 4; + return item; +} + +void parseLocalizedText(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + static int * const loctext_mask[] = {&hf_opcua_loctext_mask_localeflag, + &hf_opcua_loctext_mask_textflag, + NULL}; + + gint iOffset = *pOffset; + guint8 EncodingMask; + proto_tree *subtree; + proto_item *ti; + + subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_localizedtext, &ti, "%s: LocalizedText", szFieldName); + + /* parse encoding mask */ + EncodingMask = tvb_get_guint8(tvb, iOffset); + proto_tree_add_bitmask(subtree, tvb, iOffset, hf_opcua_loctext_mask, ett_opcua_localizedtext_encodingmask, loctext_mask, ENC_LITTLE_ENDIAN); + iOffset++; + + if (EncodingMask & LOCALIZEDTEXT_ENCODINGBYTE_LOCALE) + { + parseString(subtree, tvb, pinfo, &iOffset, hf_opcua_localizedtext_locale); + } + + if (EncodingMask & LOCALIZEDTEXT_ENCODINGBYTE_TEXT) + { + parseString(subtree, tvb, pinfo, &iOffset, hf_opcua_localizedtext_text); + } + + proto_item_set_end(ti, tvb, iOffset); + *pOffset = iOffset; +} + +proto_item* parseGuid(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, GUID_LEN, ENC_LITTLE_ENDIAN); + *pOffset+=GUID_LEN; + return item; +} + +proto_item* parseByteString(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = NULL; + char *szValue; + int iOffset = *pOffset; + gint32 iLen = tvb_get_letohl(tvb, iOffset); + iOffset += 4; + + if (iLen == -1) + { + item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 0, ENC_NA); + proto_item_append_text(item, "[OpcUa Null ByteString]"); + proto_item_set_end(item, tvb, *pOffset + 4); + } + else if (iLen == 0) + { + item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 0, ENC_NA); + proto_item_append_text(item, "[OpcUa Empty ByteString]"); + proto_item_set_end(item, tvb, *pOffset + 4); + } + else if (iLen > 0) + { + item = proto_tree_add_item(tree, hfIndex, tvb, iOffset, iLen, ENC_NA); + iOffset += iLen; /* eat the whole bytestring */ + } + else + { + item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, 0, ENC_NA); + szValue = wmem_strdup_printf(pinfo->pool, "[Invalid ByteString] Invalid length: %d", iLen); + proto_item_append_text(item, "%s", szValue); + proto_item_set_end(item, tvb, *pOffset + 4); + } + + *pOffset = iOffset; + return item; +} + +proto_item* parseXmlElement(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex) +{ + return parseByteString(tree, tvb, pinfo, pOffset, hfIndex); +} + +proto_item* parseFloat(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, (int)sizeof(gfloat), ENC_LITTLE_ENDIAN); + *pOffset += (int)sizeof(gfloat); + return item; +} + +proto_item* parseDouble(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = proto_tree_add_item(tree, hfIndex, tvb, *pOffset, (int)sizeof(gdouble), ENC_LITTLE_ENDIAN); + *pOffset += (int)sizeof(gdouble); + return item; +} + +proto_item* parseDateTime(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset, int hfIndex) +{ + proto_item *item = NULL; + *pOffset = dissect_nt_64bit_time_ex(tvb, tree, *pOffset, hfIndex, &item, FALSE); + return item; +} + +void parseDiagnosticInfo(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + static int * const diag_mask[] = {&hf_opcua_diag_mask_symbolicflag, + &hf_opcua_diag_mask_namespaceflag, + &hf_opcua_diag_mask_localizedtextflag, + &hf_opcua_diag_mask_localeflag, + &hf_opcua_diag_mask_additionalinfoflag, + &hf_opcua_diag_mask_innerstatuscodeflag, + &hf_opcua_diag_mask_innerdiaginfoflag, + NULL}; + + gint iOffset = *pOffset; + guint8 EncodingMask; + proto_tree *subtree; + proto_item *ti; + guint opcua_nested_count; + + subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, ett_opcua_diagnosticinfo, &ti, "%s: DiagnosticInfo", szFieldName); + + /* prevent a too high nesting depth */ + opcua_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_opcua, 0)); + if (opcua_nested_count >= MAX_NESTING_DEPTH) + { + expert_add_info(pinfo, ti, &ei_nesting_depth); + return; + } + opcua_nested_count++; + p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); + + /* parse encoding mask */ + EncodingMask = tvb_get_guint8(tvb, iOffset); + proto_tree_add_bitmask(subtree, tvb, iOffset, hf_opcua_diag_mask, ett_opcua_diagnosticinfo_encodingmask, diag_mask, ENC_LITTLE_ENDIAN); + iOffset++; + + if (EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_SYMBOLICID_FLAG) + { + parseInt32(subtree, tvb, pinfo, &iOffset, hf_opcua_diag_symbolicid); + } + if (EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_NAMESPACE_FLAG) + { + parseInt32(subtree, tvb, pinfo, &iOffset, hf_opcua_diag_namespace); + } + if (EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_LOCALE_FLAG) + { + parseInt32(subtree, tvb, pinfo, &iOffset, hf_opcua_diag_locale); + } + if (EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_LOCALIZEDTEXT_FLAG) + { + parseInt32(subtree, tvb, pinfo, &iOffset, hf_opcua_diag_localizedtext); + } + if (EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_ADDITIONALINFO_FLAG) + { + parseString(subtree, tvb, pinfo, &iOffset, hf_opcua_diag_additionalinfo); + } + if (EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_INNERSTATUSCODE_FLAG) + { + parseStatusCode(subtree, tvb, pinfo, &iOffset, hf_opcua_diag_innerstatuscode); + } + if (EncodingMask & DIAGNOSTICINFO_ENCODINGMASK_INNERDIAGNOSTICINFO_FLAG) + { + parseDiagnosticInfo(subtree, tvb, pinfo, &iOffset, "Inner DiagnosticInfo"); + } + + proto_item_set_end(ti, tvb, iOffset); + *pOffset = iOffset; + + opcua_nested_count--; + p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); +} + +void parseQualifiedName(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, + ett_opcua_qualifiedname, &ti, "%s: QualifiedName", szFieldName); + + parseUInt16(subtree, tvb, pinfo, pOffset, hf_opcua_qualifiedname_id); + parseString(subtree, tvb, pinfo, pOffset, hf_opcua_qualifiedname_name); + + proto_item_set_end(ti, tvb, *pOffset); +} + +void parseDataValue(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + static int * const datavalue_mask[] = {&hf_opcua_datavalue_mask_valueflag, + &hf_opcua_datavalue_mask_statuscodeflag, + &hf_opcua_datavalue_mask_sourcetimestampflag, + &hf_opcua_datavalue_mask_servertimestampflag, + &hf_opcua_datavalue_mask_sourcepicoseconds, + &hf_opcua_datavalue_mask_serverpicoseconds, + NULL}; + + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, + ett_opcua_datavalue, &ti, "%s: DataValue", szFieldName); + gint iOffset = *pOffset; + guint8 EncodingMask; + + EncodingMask = tvb_get_guint8(tvb, iOffset); + proto_tree_add_bitmask(subtree, tvb, iOffset, hf_opcua_datavalue_mask, ett_opcua_datavalue_encodingmask, datavalue_mask, ENC_LITTLE_ENDIAN); + iOffset++; + + if (EncodingMask & DATAVALUE_ENCODINGBYTE_VALUE) + { + parseVariant(subtree, tvb, pinfo, &iOffset, "Value"); + } + if (EncodingMask & DATAVALUE_ENCODINGBYTE_STATUSCODE) + { + parseStatusCode(subtree, tvb, pinfo, &iOffset, hf_opcua_StatusCode); + } + if (EncodingMask & DATAVALUE_ENCODINGBYTE_SOURCETIMESTAMP) + { + parseDateTime(subtree, tvb, pinfo, &iOffset, hf_opcua_SourceTimestamp); + } + if (EncodingMask & DATAVALUE_ENCODINGBYTE_SOURCEPICOSECONDS) + { + parseUInt16(subtree, tvb, pinfo, &iOffset, hf_opcua_SourcePicoseconds); + } + if (EncodingMask & DATAVALUE_ENCODINGBYTE_SERVERTIMESTAMP) + { + parseDateTime(subtree, tvb, pinfo, &iOffset, hf_opcua_ServerTimestamp); + } + if (EncodingMask & DATAVALUE_ENCODINGBYTE_SERVERPICOSECONDS) + { + parseUInt16(subtree, tvb, pinfo, &iOffset, hf_opcua_ServerPicoseconds); + } + + proto_item_set_end(ti, tvb, iOffset); + *pOffset = iOffset; +} + +void parseVariant(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, + ett_opcua_variant, &ti, "%s: Variant", szFieldName); + gint iOffset = *pOffset; + guint8 EncodingMask; + gint32 ArrayDimensions = 0; + guint opcua_nested_count; + + /* prevent a too high nesting depth */ + opcua_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_opcua, 0)); + if (opcua_nested_count >= MAX_NESTING_DEPTH) + { + expert_add_info(pinfo, ti, &ei_nesting_depth); + return; + } + opcua_nested_count++; + p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); + + EncodingMask = tvb_get_guint8(tvb, iOffset); + proto_tree_add_item(subtree, hf_opcua_variant_encodingmask, tvb, iOffset, 1, ENC_LITTLE_ENDIAN); + iOffset++; + + if (EncodingMask & VARIANT_ARRAYMASK) + { + /* type is encoded in bits 0-5 */ + switch(EncodingMask & 0x3f) + { + case OpcUaType_Null: break; + case OpcUaType_Boolean: parseArraySimple(subtree, tvb, pinfo, &iOffset, "Boolean", "Boolean", hf_opcua_Boolean, parseBoolean, ett_opcua_array_Boolean); break; + case OpcUaType_SByte: parseArraySimple(subtree, tvb, pinfo, &iOffset, "SByte", "SByte", hf_opcua_SByte, parseSByte, ett_opcua_array_SByte); break; + case OpcUaType_Byte: parseArraySimple(subtree, tvb, pinfo, &iOffset, "Byte", "Byte", hf_opcua_Byte, parseByte, ett_opcua_array_Byte); break; + case OpcUaType_Int16: parseArraySimple(subtree, tvb, pinfo, &iOffset, "Int16", "Int16", hf_opcua_Int16, parseInt16, ett_opcua_array_Int16); break; + case OpcUaType_UInt16: parseArraySimple(subtree, tvb, pinfo, &iOffset, "UInt16", "UInt16", hf_opcua_UInt16, parseUInt16, ett_opcua_array_UInt16); break; + case OpcUaType_Int32: parseArraySimple(subtree, tvb, pinfo, &iOffset, "Int32", "Int32", hf_opcua_Int32, parseInt32, ett_opcua_array_Int32); break; + case OpcUaType_UInt32: parseArraySimple(subtree, tvb, pinfo, &iOffset, "UInt32", "UInt32", hf_opcua_UInt32, parseUInt32, ett_opcua_array_UInt32); break; + case OpcUaType_Int64: parseArraySimple(subtree, tvb, pinfo, &iOffset, "Int64", "Int64", hf_opcua_Int64, parseInt64, ett_opcua_array_Int64); break; + case OpcUaType_UInt64: parseArraySimple(subtree, tvb, pinfo, &iOffset, "UInt64", "UInt64", hf_opcua_UInt64, parseUInt64, ett_opcua_array_UInt64); break; + case OpcUaType_Float: parseArraySimple(subtree, tvb, pinfo, &iOffset, "Float", "Float", hf_opcua_Float, parseFloat, ett_opcua_array_Float); break; + case OpcUaType_Double: parseArraySimple(subtree, tvb, pinfo, &iOffset, "Double", "Double", hf_opcua_Double, parseDouble, ett_opcua_array_Double); break; + case OpcUaType_String: parseArraySimple(subtree, tvb, pinfo, &iOffset, "String", "String", hf_opcua_String, parseString, ett_opcua_array_String); break; + case OpcUaType_DateTime: parseArraySimple(subtree, tvb, pinfo, &iOffset, "DateTime", "DateTime", hf_opcua_DateTime, parseDateTime, ett_opcua_array_DateTime); break; + case OpcUaType_Guid: parseArraySimple(subtree, tvb, pinfo, &iOffset, "Guid", "Guid", hf_opcua_Guid, parseGuid, ett_opcua_array_Guid); break; + case OpcUaType_ByteString: parseArraySimple(subtree, tvb, pinfo, &iOffset, "ByteString", "ByteString", hf_opcua_ByteString, parseByteString, ett_opcua_array_ByteString); break; + case OpcUaType_XmlElement: parseArraySimple(subtree, tvb, pinfo, &iOffset, "XmlElement", "XmlElement", hf_opcua_XmlElement, parseXmlElement, ett_opcua_array_XmlElement); break; + case OpcUaType_NodeId: parseArrayComplex(subtree, tvb, pinfo, &iOffset, "NodeId", "NodeId", parseNodeId, ett_opcua_array_NodeId); break; + case OpcUaType_ExpandedNodeId: parseArrayComplex(subtree, tvb, pinfo, &iOffset, "ExpandedNodeId", "ExpandedNodeId", parseExpandedNodeId, ett_opcua_array_ExpandedNodeId); break; + case OpcUaType_StatusCode: parseArraySimple(subtree, tvb, pinfo, &iOffset, "StatusCode", "StatusCode", hf_opcua_StatusCode, parseStatusCode, ett_opcua_array_StatusCode); break; + case OpcUaType_DiagnosticInfo: parseArrayComplex(subtree, tvb, pinfo, &iOffset, "DiagnosticInfo", "DiagnosticInfo", parseDiagnosticInfo, ett_opcua_array_DiagnosticInfo); break; + case OpcUaType_QualifiedName: parseArrayComplex(subtree, tvb, pinfo, &iOffset, "QualifiedName", "QualifiedName", parseQualifiedName, ett_opcua_array_QualifiedName); break; + case OpcUaType_LocalizedText: parseArrayComplex(subtree, tvb, pinfo, &iOffset, "LocalizedText", "LocalizedText", parseLocalizedText, ett_opcua_array_LocalizedText); break; + case OpcUaType_ExtensionObject: parseArrayComplex(subtree, tvb, pinfo, &iOffset, "ExtensionObject", "ExtensionObject", parseExtensionObject, ett_opcua_array_ExtensionObject); break; + case OpcUaType_DataValue: parseArrayComplex(subtree, tvb, pinfo, &iOffset, "DataValue", "DataValue", parseDataValue, ett_opcua_array_DataValue); break; + case OpcUaType_Variant: parseArrayComplex(subtree, tvb, pinfo, &iOffset, "Variant", "Variant", parseVariant, ett_opcua_array_Variant); break; + } + + if (EncodingMask & VARIANT_ARRAYDIMENSIONS) + { + proto_item *ti_2; + proto_tree *subtree_2 = proto_tree_add_subtree(subtree, tvb, iOffset, -1, + ett_opcua_variant_arraydims, &ti_2, "ArrayDimensions"); + int i; + + /* read array length */ + ArrayDimensions = tvb_get_letohl(tvb, iOffset); + proto_tree_add_item(subtree_2, hf_opcua_ArraySize, tvb, iOffset, 4, ENC_LITTLE_ENDIAN); + + if (ArrayDimensions > MAX_ARRAY_LEN) + { + proto_tree_add_expert_format(subtree_2, pinfo, &ei_array_length, tvb, iOffset, 4, "ArrayDimensions length %d too large to process", ArrayDimensions); + return; + } + + iOffset += 4; + for (i=0; ipool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); +} + +/** General parsing function for arrays of simple types. + * All arrays have one 4 byte signed integer length information, + * followed by n data elements. + */ +void parseArraySimple(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName, const char *szTypeName, int hfIndex, fctSimpleTypeParser pParserFunction, const gint idx) +{ + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, idx, &ti, "%s: Array of %s", szFieldName, szTypeName); + int i; + gint32 iLen; + + /* read array length */ + iLen = tvb_get_letohl(tvb, *pOffset); + proto_tree_add_item(subtree, hf_opcua_ArraySize, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); + + if (iLen > MAX_ARRAY_LEN) + { + proto_tree_add_expert_format(subtree, pinfo, &ei_array_length, tvb, *pOffset, 4, "Array length %d too large to process", iLen); + return; + } + + *pOffset += 4; + for (i=0; i MAX_ARRAY_LEN) + { + proto_tree_add_expert_format(subtree, pinfo, &ei_array_length, tvb, *pOffset, 4, "Array length %d too large to process", iLen); + return; + } + + *pOffset += 4; + for (i=0; i MAX_ARRAY_LEN) + { + proto_tree_add_expert_format(subtree, pinfo, &ei_array_length, tvb, *pOffset, 4, "Array length %d too large to process", iLen); + return; + } + + *pOffset += 4; + for (i=0; ipool, pinfo, proto_opcua, 0)); + if (opcua_nested_count >= MAX_NESTING_DEPTH) + { + expert_add_info(pinfo, ti, &ei_nesting_depth); + return; + } + opcua_nested_count++; + p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); + + /* add nodeid subtree */ + TypeId = getExtensionObjectType(tvb, &iOffset); + parseNodeId(extobj_tree, tvb, pinfo, &iOffset, "TypeId"); + + /* parse encoding mask */ + EncodingMask = tvb_get_guint8(tvb, iOffset); + proto_tree_add_bitmask(extobj_tree, tvb, iOffset, hf_opcua_extobj_mask, ett_opcua_extensionobject_encodingmask, extobj_mask, ENC_LITTLE_ENDIAN); + iOffset++; + + if (EncodingMask & EXTOBJ_ENCODINGMASK_BINBODY_FLAG) /* has binary body ? */ + { + dispatchExtensionObjectType(extobj_tree, tvb, pinfo, &iOffset, TypeId); + } + + proto_item_set_end(ti, tvb, iOffset); + *pOffset = iOffset; + + opcua_nested_count--; + p_add_proto_data(pinfo->pool, pinfo, proto_opcua, 0, GUINT_TO_POINTER(opcua_nested_count)); +} + +void parseExpandedNodeId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName) +{ + static int * const expandednodeid_mask[] = {&hf_opcua_nodeid_encodingmask, + &hf_opcua_expandednodeid_mask_serverindex, + &hf_opcua_expandednodeid_mask_namespaceuri, + NULL}; + + proto_item *ti; + proto_tree *subtree = proto_tree_add_subtree_format(tree, tvb, *pOffset, -1, + ett_opcua_expandednodeid, &ti, "%s: ExpandedNodeId", szFieldName); + gint iOffset = *pOffset; + guint8 EncodingMask; + + EncodingMask = tvb_get_guint8(tvb, iOffset); + proto_tree_add_bitmask(subtree, tvb, iOffset, hf_opcua_expandednodeid_mask, ett_opcua_expandednodeid_encodingmask, expandednodeid_mask, ENC_LITTLE_ENDIAN); + iOffset++; + + switch(EncodingMask & 0x0F) + { + case 0x00: /* two byte node id */ + proto_tree_add_item(subtree, hf_opcua_nodeid_numeric, tvb, iOffset, 1, ENC_LITTLE_ENDIAN); + iOffset+=1; + break; + case 0x01: /* four byte node id */ + proto_tree_add_item(subtree, hf_opcua_nodeid_nsindex, tvb, iOffset, 1, ENC_LITTLE_ENDIAN); + iOffset+=1; + proto_tree_add_item(subtree, hf_opcua_nodeid_numeric, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + iOffset+=2; + break; + case 0x02: /* numeric, that does not fit into four bytes */ + proto_tree_add_item(subtree, hf_opcua_nodeid_nsindex, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + iOffset+=2; + proto_tree_add_item(subtree, hf_opcua_nodeid_numeric, tvb, iOffset, 4, ENC_LITTLE_ENDIAN); + iOffset+=4; + break; + case 0x03: /* string */ + proto_tree_add_item(subtree, hf_opcua_nodeid_nsindex, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + iOffset+=2; + parseString(subtree, tvb, pinfo, &iOffset, hf_opcua_nodeid_string); + break; + case 0x04: /* guid */ + proto_tree_add_item(subtree, hf_opcua_nodeid_nsindex, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + iOffset+=2; + parseGuid(subtree, tvb, pinfo, &iOffset, hf_opcua_nodeid_guid); + break; + case 0x05: /* byte string */ + proto_tree_add_item(subtree, hf_opcua_nodeid_nsindex, tvb, iOffset, 2, ENC_LITTLE_ENDIAN); + iOffset+=2; + parseByteString(subtree, tvb, pinfo, &iOffset, hf_opcua_nodeid_bytestring); + break; + }; + + if (EncodingMask & NODEID_NAMESPACEURIFLAG) + { + parseString(subtree, tvb, pinfo, &iOffset, hf_opcua_NamespaceUri); + } + if (EncodingMask & NODEID_SERVERINDEXFLAG) + { + parseUInt32(subtree, tvb, pinfo, &iOffset, hf_opcua_ServerIndex); + } + + proto_item_set_end(ti, tvb, iOffset); + *pOffset = iOffset; +} + +guint32 getExtensionObjectType(tvbuff_t *tvb, gint *pOffset) +{ + gint iOffset = *pOffset; + guint8 EncodingMask; + guint32 Numeric = 0; + + EncodingMask = tvb_get_guint8(tvb, iOffset); + iOffset++; + + switch(EncodingMask) + { + case 0x00: /* two byte node id */ + Numeric = tvb_get_guint8(tvb, iOffset); + /*iOffset+=1;*/ + break; + case 0x01: /* four byte node id */ + iOffset+=1; + Numeric = tvb_get_letohs(tvb, iOffset); + break; + case 0x02: /* numeric, that does not fit into four bytes */ + iOffset+=2; + Numeric = tvb_get_letohl(tvb, iOffset); + break; + case 0x03: /* string */ + case 0x04: /* uri */ + case 0x05: /* guid */ + case 0x06: /* byte string */ + /* NOT USED */ + break; + }; + + return Numeric; +} + +void parseNodeClassMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + static int * const nodeclass_mask[] = { + &hf_opcua_nodeClassMask_object, + &hf_opcua_nodeClassMask_variable, + &hf_opcua_nodeClassMask_method, + &hf_opcua_nodeClassMask_objecttype, + &hf_opcua_nodeClassMask_variabletype, + &hf_opcua_nodeClassMask_referencetype, + &hf_opcua_nodeClassMask_datatype, + &hf_opcua_nodeClassMask_view, + NULL}; + + guint8 NodeClassMask = tvb_get_guint8(tvb, *pOffset); + if(NodeClassMask == NODECLASSMASK_ALL) + { + proto_tree_add_item(tree, hf_opcua_nodeClassMask_all, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); + } + else + { + proto_tree_add_bitmask(tree, tvb, *pOffset, hf_opcua_nodeClassMask, ett_opcua_nodeClassMask, nodeclass_mask, ENC_LITTLE_ENDIAN); + } + *pOffset+=4; +} + +void parseResultMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + static int * const browseresult_mask[] = { + &hf_opcua_resultMask_referencetype, + &hf_opcua_resultMask_isforward, + &hf_opcua_resultMask_nodeclass, + &hf_opcua_resultMask_browsename, + &hf_opcua_resultMask_displayname, + &hf_opcua_resultMask_typedefinition, + NULL}; + + guint8 ResultMask = tvb_get_guint8(tvb, *pOffset); + if(ResultMask == RESULTMASK_ALL) + { + proto_tree_add_item(tree, hf_opcua_resultMask_all, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); + } + else + { + proto_tree_add_bitmask(tree, tvb, *pOffset, hf_opcua_resultMask, ett_opcua_resultMask, browseresult_mask, ENC_LITTLE_ENDIAN); + } + *pOffset+=4; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/opcua/opcua_simpletypes.h b/plugins/epan/opcua/opcua_simpletypes.h new file mode 100644 index 00000000..9d88983b --- /dev/null +++ b/plugins/epan/opcua/opcua_simpletypes.h @@ -0,0 +1,105 @@ +/****************************************************************************** +** Copyright (C) 2006-2007 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: Implementation of OpcUa built-in type parsers. +** This contains all the simple types and some complex types. +** +** Author: Gerhard Gappmeier +******************************************************************************/ +#include "opcua_identifiers.h" + +/* simple header fields */ +extern int hf_opcua_returnDiag; +extern int hf_opcua_returnDiag_mask_sl_symbolicId; +extern int hf_opcua_returnDiag_mask_sl_localizedText; +extern int hf_opcua_returnDiag_mask_sl_additionalinfo; +extern int hf_opcua_returnDiag_mask_sl_innerstatuscode; +extern int hf_opcua_returnDiag_mask_sl_innerdiagnostics; +extern int hf_opcua_returnDiag_mask_ol_symbolicId; +extern int hf_opcua_returnDiag_mask_ol_localizedText; +extern int hf_opcua_returnDiag_mask_ol_additionalinfo; +extern int hf_opcua_returnDiag_mask_ol_innerstatuscode; +extern int hf_opcua_returnDiag_mask_ol_innerdiagnostics; +extern int hf_opcua_nodeClassMask; +extern int hf_opcua_nodeClassMask_object; +extern int hf_opcua_nodeClassMask_variable; +extern int hf_opcua_nodeClassMask_method; +extern int hf_opcua_nodeClassMask_objecttype; +extern int hf_opcua_nodeClassMask_variabletype; +extern int hf_opcua_nodeClassMask_referencetype; +extern int hf_opcua_nodeClassMask_datatype; +extern int hf_opcua_nodeClassMask_view; + +/* simple types trees */ +extern gint ett_opcua_array_Boolean; +extern gint ett_opcua_array_SByte; +extern gint ett_opcua_array_Byte; +extern gint ett_opcua_array_Int16; +extern gint ett_opcua_array_UInt16; +extern gint ett_opcua_array_Int32; +extern gint ett_opcua_array_UInt32; +extern gint ett_opcua_array_Int64; +extern gint ett_opcua_array_UInt64; +extern gint ett_opcua_array_Float; +extern gint ett_opcua_array_Double; +extern gint ett_opcua_array_String; +extern gint ett_opcua_array_DateTime; +extern gint ett_opcua_array_Guid; +extern gint ett_opcua_array_ByteString; +extern gint ett_opcua_array_XmlElement; +extern gint ett_opcua_array_NodeId; +extern gint ett_opcua_array_ExpandedNodeId; +extern gint ett_opcua_array_StatusCode; +extern gint ett_opcua_array_DiagnosticInfo; +extern gint ett_opcua_array_QualifiedName; +extern gint ett_opcua_array_LocalizedText; +extern gint ett_opcua_array_ExtensionObject; +extern gint ett_opcua_array_DataValue; +extern gint ett_opcua_array_Variant; +extern gint ett_opcua_returnDiagnostics; + +/* simple types */ +proto_item* parseBoolean(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseByte(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseSByte(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseUInt16(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseInt16(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseUInt32(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseInt32(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseUInt64(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseInt64(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseString(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseGuid(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseByteString(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseXmlElement(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseFloat(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseDouble(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseDateTime(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +proto_item* parseStatusCode(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int hfIndex); +/* complex types */ +void parseLocalizedText(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseNodeId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDiagnosticInfo(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseExtensionObject(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseQualifiedName(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseDataValue(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseVariant(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseExpandedNodeId(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName); +void parseArraySimple(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName, const char *szTypeName, int hfIndex, fctSimpleTypeParser pParserFunction, const gint idx); +void parseArrayEnum(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName, const char *szTypeName, fctEnumParser pParserFunction, const gint idx); +void parseArrayComplex(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, const char *szFieldName, const char *szTypeName, fctComplexTypeParser pParserFunction, const gint idx); +void registerSimpleTypes(int proto); +guint32 getExtensionObjectType(tvbuff_t *tvb, gint *pOffset); +void parseNodeClassMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void parseResultMask(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); + +void dispatchExtensionObjectType(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset, int TypeId); + diff --git a/plugins/epan/opcua/opcua_statuscode.c b/plugins/epan/opcua/opcua_statuscode.c new file mode 100644 index 00000000..78447d77 --- /dev/null +++ b/plugins/epan/opcua/opcua_statuscode.c @@ -0,0 +1,267 @@ +/****************************************************************************** +** Copyright (C) 2014 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Author: Hannes Mezger +** +** This file was autogenerated on 10.06.2014. +** DON'T MODIFY THIS FILE! +** +******************************************************************************/ + +#include "config.h" + +#include + +const value_string g_statusCodes[] = { + {0x00000000, "Good"}, + {0x40000000, "Uncertain"}, + {0x80000000, "Bad"}, + {0x80010000, "BadUnexpectedError"}, + {0x80020000, "BadInternalError"}, + {0x80030000, "BadOutOfMemory"}, + {0x80040000, "BadResourceUnavailable"}, + {0x80050000, "BadCommunicationError"}, + {0x80060000, "BadEncodingError"}, + {0x80070000, "BadDecodingError"}, + {0x80080000, "BadEncodingLimitsExceeded"}, + {0x80B80000, "BadRequestTooLarge"}, + {0x80B90000, "BadResponseTooLarge"}, + {0x80090000, "BadUnknownResponse"}, + {0x800A0000, "BadTimeout"}, + {0x800B0000, "BadServiceUnsupported"}, + {0x800C0000, "BadShutdown"}, + {0x800D0000, "BadServerNotConnected"}, + {0x800E0000, "BadServerHalted"}, + {0x800F0000, "BadNothingToDo"}, + {0x80100000, "BadTooManyOperations"}, + {0x80DB0000, "BadTooManyMonitoredItems"}, + {0x80110000, "BadDataTypeIdUnknown"}, + {0x80120000, "BadCertificateInvalid"}, + {0x80130000, "BadSecurityChecksFailed"}, + {0x80140000, "BadCertificateTimeInvalid"}, + {0x80150000, "BadCertificateIssuerTimeInvalid"}, + {0x80160000, "BadCertificateHostNameInvalid"}, + {0x80170000, "BadCertificateUriInvalid"}, + {0x80180000, "BadCertificateUseNotAllowed"}, + {0x80190000, "BadCertificateIssuerUseNotAllowed"}, + {0x801A0000, "BadCertificateUntrusted"}, + {0x801B0000, "BadCertificateRevocationUnknown"}, + {0x801C0000, "BadCertificateIssuerRevocationUnknown"}, + {0x801D0000, "BadCertificateRevoked"}, + {0x801E0000, "BadCertificateIssuerRevoked"}, + {0x810D0000, "BadCertificateChainIncomplete"}, + {0x801F0000, "BadUserAccessDenied"}, + {0x80200000, "BadIdentityTokenInvalid"}, + {0x80210000, "BadIdentityTokenRejected"}, + {0x80220000, "BadSecureChannelIdInvalid"}, + {0x80230000, "BadInvalidTimestamp"}, + {0x80240000, "BadNonceInvalid"}, + {0x80250000, "BadSessionIdInvalid"}, + {0x80260000, "BadSessionClosed"}, + {0x80270000, "BadSessionNotActivated"}, + {0x80280000, "BadSubscriptionIdInvalid"}, + {0x802A0000, "BadRequestHeaderInvalid"}, + {0x802B0000, "BadTimestampsToReturnInvalid"}, + {0x802C0000, "BadRequestCancelledByClient"}, + {0x80E50000, "BadTooManyArguments"}, + {0x002D0000, "GoodSubscriptionTransferred"}, + {0x002E0000, "GoodCompletesAsynchronously"}, + {0x002F0000, "GoodOverload"}, + {0x00300000, "GoodClamped"}, + {0x80310000, "BadNoCommunication"}, + {0x80320000, "BadWaitingForInitialData"}, + {0x80330000, "BadNodeIdInvalid"}, + {0x80340000, "BadNodeIdUnknown"}, + {0x80350000, "BadAttributeIdInvalid"}, + {0x80360000, "BadIndexRangeInvalid"}, + {0x80370000, "BadIndexRangeNoData"}, + {0x80380000, "BadDataEncodingInvalid"}, + {0x80390000, "BadDataEncodingUnsupported"}, + {0x803A0000, "BadNotReadable"}, + {0x803B0000, "BadNotWritable"}, + {0x803C0000, "BadOutOfRange"}, + {0x803D0000, "BadNotSupported"}, + {0x803E0000, "BadNotFound"}, + {0x803F0000, "BadObjectDeleted"}, + {0x80400000, "BadNotImplemented"}, + {0x80410000, "BadMonitoringModeInvalid"}, + {0x80420000, "BadMonitoredItemIdInvalid"}, + {0x80430000, "BadMonitoredItemFilterInvalid"}, + {0x80440000, "BadMonitoredItemFilterUnsupported"}, + {0x80450000, "BadFilterNotAllowed"}, + {0x80460000, "BadStructureMissing"}, + {0x80470000, "BadEventFilterInvalid"}, + {0x80480000, "BadContentFilterInvalid"}, + {0x80C10000, "BadFilterOperatorInvalid"}, + {0x80C20000, "BadFilterOperatorUnsupported"}, + {0x80C30000, "BadFilterOperandCountMismatch"}, + {0x80490000, "BadFilterOperandInvalid"}, + {0x80C40000, "BadFilterElementInvalid"}, + {0x80C50000, "BadFilterLiteralInvalid"}, + {0x804A0000, "BadContinuationPointInvalid"}, + {0x804B0000, "BadNoContinuationPoints"}, + {0x804C0000, "BadReferenceTypeIdInvalid"}, + {0x804D0000, "BadBrowseDirectionInvalid"}, + {0x804E0000, "BadNodeNotInView"}, + {0x804F0000, "BadServerUriInvalid"}, + {0x80500000, "BadServerNameMissing"}, + {0x80510000, "BadDiscoveryUrlMissing"}, + {0x80520000, "BadSemaphoreFileMissing"}, + {0x80530000, "BadRequestTypeInvalid"}, + {0x80540000, "BadSecurityModeRejected"}, + {0x80550000, "BadSecurityPolicyRejected"}, + {0x80560000, "BadTooManySessions"}, + {0x80570000, "BadUserSignatureInvalid"}, + {0x80580000, "BadApplicationSignatureInvalid"}, + {0x80590000, "BadNoValidCertificates"}, + {0x80C60000, "BadIdentityChangeNotSupported"}, + {0x805A0000, "BadRequestCancelledByRequest"}, + {0x805B0000, "BadParentNodeIdInvalid"}, + {0x805C0000, "BadReferenceNotAllowed"}, + {0x805D0000, "BadNodeIdRejected"}, + {0x805E0000, "BadNodeIdExists"}, + {0x805F0000, "BadNodeClassInvalid"}, + {0x80600000, "BadBrowseNameInvalid"}, + {0x80610000, "BadBrowseNameDuplicated"}, + {0x80620000, "BadNodeAttributesInvalid"}, + {0x80630000, "BadTypeDefinitionInvalid"}, + {0x80640000, "BadSourceNodeIdInvalid"}, + {0x80650000, "BadTargetNodeIdInvalid"}, + {0x80660000, "BadDuplicateReferenceNotAllowed"}, + {0x80670000, "BadInvalidSelfReference"}, + {0x80680000, "BadReferenceLocalOnly"}, + {0x80690000, "BadNoDeleteRights"}, + {0x40BC0000, "UncertainReferenceNotDeleted"}, + {0x806A0000, "BadServerIndexInvalid"}, + {0x806B0000, "BadViewIdUnknown"}, + {0x80C90000, "BadViewTimestampInvalid"}, + {0x80CA0000, "BadViewParameterMismatch"}, + {0x80CB0000, "BadViewVersionInvalid"}, + {0x40C00000, "UncertainNotAllNodesAvailable"}, + {0x00BA0000, "GoodResultsMayBeIncomplete"}, + {0x80C80000, "BadNotTypeDefinition"}, + {0x406C0000, "UncertainReferenceOutOfServer"}, + {0x806D0000, "BadTooManyMatches"}, + {0x806E0000, "BadQueryTooComplex"}, + {0x806F0000, "BadNoMatch"}, + {0x80700000, "BadMaxAgeInvalid"}, + {0x80E60000, "BadSecurityModeInsufficient"}, + {0x80710000, "BadHistoryOperationInvalid"}, + {0x80720000, "BadHistoryOperationUnsupported"}, + {0x80BD0000, "BadInvalidTimestampArgument"}, + {0x80730000, "BadWriteNotSupported"}, + {0x80740000, "BadTypeMismatch"}, + {0x80750000, "BadMethodInvalid"}, + {0x80760000, "BadArgumentsMissing"}, + {0x80770000, "BadTooManySubscriptions"}, + {0x80780000, "BadTooManyPublishRequests"}, + {0x80790000, "BadNoSubscription"}, + {0x807A0000, "BadSequenceNumberUnknown"}, + {0x807B0000, "BadMessageNotAvailable"}, + {0x807C0000, "BadInsufficientClientProfile"}, + {0x80BF0000, "BadStateNotActive"}, + {0x807D0000, "BadTcpServerTooBusy"}, + {0x807E0000, "BadTcpMessageTypeInvalid"}, + {0x807F0000, "BadTcpSecureChannelUnknown"}, + {0x80800000, "BadTcpMessageTooLarge"}, + {0x80810000, "BadTcpNotEnoughResources"}, + {0x80820000, "BadTcpInternalError"}, + {0x80830000, "BadTcpEndpointUrlInvalid"}, + {0x80840000, "BadRequestInterrupted"}, + {0x80850000, "BadRequestTimeout"}, + {0x80860000, "BadSecureChannelClosed"}, + {0x80870000, "BadSecureChannelTokenUnknown"}, + {0x80880000, "BadSequenceNumberInvalid"}, + {0x80BE0000, "BadProtocolVersionUnsupported"}, + {0x80890000, "BadConfigurationError"}, + {0x808A0000, "BadNotConnected"}, + {0x808B0000, "BadDeviceFailure"}, + {0x808C0000, "BadSensorFailure"}, + {0x808D0000, "BadOutOfService"}, + {0x808E0000, "BadDeadbandFilterInvalid"}, + {0x408F0000, "UncertainNoCommunicationLastUsableValue"}, + {0x40900000, "UncertainLastUsableValue"}, + {0x40910000, "UncertainSubstituteValue"}, + {0x40920000, "UncertainInitialValue"}, + {0x40930000, "UncertainSensorNotAccurate"}, + {0x40940000, "UncertainEngineeringUnitsExceeded"}, + {0x40950000, "UncertainSubNormal"}, + {0x00960000, "GoodLocalOverride"}, + {0x80970000, "BadRefreshInProgress"}, + {0x80980000, "BadConditionAlreadyDisabled"}, + {0x80CC0000, "BadConditionAlreadyEnabled"}, + {0x80990000, "BadConditionDisabled"}, + {0x809A0000, "BadEventIdUnknown"}, + {0x80BB0000, "BadEventNotAcknowledgeable"}, + {0x80CD0000, "BadDialogNotActive"}, + {0x80CE0000, "BadDialogResponseInvalid"}, + {0x80CF0000, "BadConditionBranchAlreadyAcked"}, + {0x80D00000, "BadConditionBranchAlreadyConfirmed"}, + {0x80D10000, "BadConditionAlreadyShelved"}, + {0x80D20000, "BadConditionNotShelved"}, + {0x80D30000, "BadShelvingTimeOutOfRange"}, + {0x809B0000, "BadNoData"}, + {0x80D70000, "BadBoundNotFound"}, + {0x80D80000, "BadBoundNotSupported"}, + {0x809D0000, "BadDataLost"}, + {0x809E0000, "BadDataUnavailable"}, + {0x809F0000, "BadEntryExists"}, + {0x80A00000, "BadNoEntryExists"}, + {0x80A10000, "BadTimestampNotSupported"}, + {0x00A20000, "GoodEntryInserted"}, + {0x00A30000, "GoodEntryReplaced"}, + {0x40A40000, "UncertainDataSubNormal"}, + {0x00A50000, "GoodNoData"}, + {0x00A60000, "GoodMoreData"}, + {0x80D40000, "BadAggregateListMismatch"}, + {0x80D50000, "BadAggregateNotSupported"}, + {0x80D60000, "BadAggregateInvalidInputs"}, + {0x80DA0000, "BadAggregateConfigurationRejected"}, + {0x00D90000, "GoodDataIgnored"}, + {0x80E40000, "BadRequestNotAllowed"}, + {0x00DC0000, "GoodEdited"}, + {0x00DD0000, "GoodPostActionFailed"}, + {0x40DE0000, "UncertainDominantValueChanged"}, + {0x00E00000, "GoodDependentValueChanged"}, + {0x80E10000, "BadDominantValueChanged"}, + {0x40E20000, "UncertainDependentValueChanged"}, + {0x80E30000, "BadDependentValueChanged"}, + {0x00A70000, "GoodCommunicationEvent"}, + {0x00A80000, "GoodShutdownEvent"}, + {0x00A90000, "GoodCallAgain"}, + {0x00AA0000, "GoodNonCriticalTimeout"}, + {0x80AB0000, "BadInvalidArgument"}, + {0x80AC0000, "BadConnectionRejected"}, + {0x80AD0000, "BadDisconnect"}, + {0x80AE0000, "BadConnectionClosed"}, + {0x80AF0000, "BadInvalidState"}, + {0x80B00000, "BadEndOfStream"}, + {0x80B10000, "BadNoDataAvailable"}, + {0x80B20000, "BadWaitingForResponse"}, + {0x80B30000, "BadOperationAbandoned"}, + {0x80B40000, "BadExpectedStreamToBlock"}, + {0x80B50000, "BadWouldBlock"}, + {0x80B60000, "BadSyntaxError"}, + {0x80B70000, "BadMaxConnectionsReached"}, + {0x81000000, "StartOfStackStatusCodes"}, + {0x81010000, "BadSignatureInvalid"}, + {0x81040000, "BadExtensibleParameterInvalid"}, + {0x81050000, "BadExtensibleParameterUnsupported"}, + {0x81060000, "BadHostUnknown"}, + {0x81070000, "BadTooManyPosts"}, + {0x81080000, "BadSecurityConfig"}, + {0x81090000, "BadFileNotFound"}, + {0x810A0000, "BadContinue"}, + {0x810B0000, "BadHttpMethodNotAllowed"}, + {0x810C0000, "BadFileExists"}, + {0x810D0000, "BadCertificateChainIncomplete"}, + {0, NULL} +}; diff --git a/plugins/epan/opcua/opcua_statuscode.h b/plugins/epan/opcua/opcua_statuscode.h new file mode 100644 index 00000000..a48c2666 --- /dev/null +++ b/plugins/epan/opcua/opcua_statuscode.h @@ -0,0 +1,16 @@ +/****************************************************************************** +** Copyright (C) 2014 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Author: Hannes Mezger +** +******************************************************************************/ + +extern const value_string g_statusCodes[]; diff --git a/plugins/epan/opcua/opcua_transport_layer.c b/plugins/epan/opcua/opcua_transport_layer.c new file mode 100644 index 00000000..31fdca3b --- /dev/null +++ b/plugins/epan/opcua/opcua_transport_layer.c @@ -0,0 +1,245 @@ +/****************************************************************************** +** Copyright (C) 2006-2009 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Transport Layer Decoder. +** +** Author: Gerhard Gappmeier +******************************************************************************/ + +#include "config.h" + +#include +#include "opcua_security_layer.h" +#include "opcua_application_layer.h" +#include "opcua_simpletypes.h" +#include "opcua_transport_layer.h" +#include "opcua_servicetable.h" + +static int hf_opcua_transport_type = -1; +static int hf_opcua_transport_chunk = -1; +static int hf_opcua_transport_size = -1; +static int hf_opcua_transport_ver = -1; +static int hf_opcua_transport_scid = -1; +static int hf_opcua_transport_rbs = -1; +static int hf_opcua_transport_sbs = -1; +static int hf_opcua_transport_mms = -1; +static int hf_opcua_transport_mcc = -1; +static int hf_opcua_transport_endpoint = -1; +static int hf_opcua_transport_suri = -1; +static int hf_opcua_transport_error = -1; +static int hf_opcua_transport_reason = -1; +static int hf_opcua_transport_spu = -1; +static int hf_opcua_transport_scert = -1; +static int hf_opcua_transport_rcthumb = -1; +static int hf_opcua_transport_seq = -1; +static int hf_opcua_transport_rqid = -1; + +/** subtree types */ +extern gint ett_opcua_nodeid; +extern gint ett_opcua_extensionobject; + +/** Register transport layer types. */ +void registerTransportLayerTypes(int proto) +{ + static hf_register_info hf[] = + { + /* id full name abbreviation type display strings bitmask blurb HFILL */ + {&hf_opcua_transport_type, {"Message Type", "opcua.transport.type", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_chunk, {"Chunk Type", "opcua.transport.chunk", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_size, {"Message Size", "opcua.transport.size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_ver, {"Version", "opcua.transport.ver", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_scid, {"SecureChannelId", "opcua.transport.scid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_rbs, {"ReceiveBufferSize", "opcua.transport.rbs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_sbs, {"SendBufferSize", "opcua.transport.sbs", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_mms, {"MaxMessageSize", "opcua.transport.mms", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_mcc, {"MaxChunkCount", "opcua.transport.mcc", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_endpoint, {"EndpointUrl", "opcua.transport.endpoint", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_suri, {"ServerUri", "opcua.transport.suri", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_error, {"Error", "opcua.transport.error", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_reason, {"Reason", "opcua.transport.reason", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_spu, {"SecurityPolicyUri", "opcua.security.spu", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_scert, {"SenderCertificate", "opcua.security.scert", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_rcthumb, {"ReceiverCertificateThumbprint", "opcua.security.rcthumb", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_seq, {"SequenceNumber", "opcua.security.seq", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + {&hf_opcua_transport_rqid, {"RequestId", "opcua.security.rqid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}}, + }; + + proto_register_field_array(proto, hf, array_length(hf)); +} + +/* Transport Layer: message parsers */ +int parseHello(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, ENC_ASCII|ENC_NA); *pOffset+=3; + proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1; + proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_rbs, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_sbs, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_mms, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_mcc, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + parseString(tree, tvb, pinfo, pOffset, hf_opcua_transport_endpoint); + return -1; +} + +int parseAcknowledge(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, ENC_ASCII|ENC_NA); *pOffset+=3; + proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1; + proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_ver, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_rbs, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_sbs, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_mms, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_mcc, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + return -1; +} + +int parseError(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, ENC_ASCII|ENC_NA); *pOffset+=3; + proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1; + proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + parseStatusCode(tree, tvb, pinfo, pOffset, hf_opcua_transport_error); + parseString(tree, tvb, pinfo, pOffset, hf_opcua_transport_reason); + return -1; +} + +int parseReverseHello(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, ENC_ASCII|ENC_NA); *pOffset+=3; + proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1; + proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + parseString(tree, tvb, pinfo, pOffset, hf_opcua_transport_suri); + parseString(tree, tvb, pinfo, pOffset, hf_opcua_transport_endpoint); + return -1; +} + +int parseMessage(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, ENC_ASCII|ENC_NA); *pOffset+=3; + proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1; + proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + + /* message data contains the security layer */ + parseSecurityLayer(tree, tvb, pOffset); + + return -1; +} + +int parseAbort(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint *pOffset) +{ + parseStatusCode(tree, tvb, pinfo, pOffset, hf_opcua_transport_error); + parseString(tree, tvb, pinfo, pOffset, hf_opcua_transport_reason); + + return -1; +} + +int parseService(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_item *ti_inner; + proto_tree *encobj_tree; + proto_tree *nodeid_tree; + int ServiceId = 0; + + /* AT THE MOMENT NO SECURITY IS IMPLEMENTED IN UA. + * WE CAN JUST JUMP INTO THE APPLICATION LAYER DATA. + * THIS WILL CHAHNGE IN THE FUTURE. */ + + /* add encodeable object subtree */ + encobj_tree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_extensionobject, &ti, "OpcUa Service : Encodeable Object"); + + /* add nodeid subtree */ + nodeid_tree = proto_tree_add_subtree(encobj_tree, tvb, *pOffset, -1, ett_opcua_nodeid, &ti_inner, "TypeId : ExpandedNodeId"); + ServiceId = parseServiceNodeId(nodeid_tree, tvb, pOffset); + proto_item_set_end(ti_inner, tvb, *pOffset); + + dispatchService(encobj_tree, tvb, pinfo, pOffset, ServiceId); + + proto_item_set_end(ti, tvb, *pOffset); + return ServiceId; +} + +int parseOpenSecureChannel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_item *ti_inner; + proto_tree *encobj_tree; + proto_tree *nodeid_tree; + int ServiceId = 0; + + proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, ENC_ASCII|ENC_NA); *pOffset+=3; + proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1; + proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + parseString(tree, tvb, pinfo, pOffset, hf_opcua_transport_spu); + parseByteString(tree, tvb, pinfo, pOffset, hf_opcua_transport_scert); + parseByteString(tree, tvb, pinfo, pOffset, hf_opcua_transport_rcthumb); + proto_tree_add_item(tree, hf_opcua_transport_seq, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_rqid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + + /* add encodeable object subtree */ + encobj_tree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_extensionobject, &ti, "Message : Encodeable Object"); + + /* add nodeid subtree */ + nodeid_tree = proto_tree_add_subtree(encobj_tree, tvb, *pOffset, -1, ett_opcua_nodeid, &ti_inner, "TypeId : ExpandedNodeId"); + ServiceId = parseServiceNodeId(nodeid_tree, tvb, pOffset); + proto_item_set_end(ti_inner, tvb, *pOffset); + + dispatchService(encobj_tree, tvb, pinfo, pOffset, ServiceId); + + proto_item_set_end(ti, tvb, *pOffset); + return ServiceId; +} + +int parseCloseSecureChannel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset) +{ + proto_item *ti; + proto_item *ti_inner; + proto_tree *encobj_tree; + proto_tree *nodeid_tree; + int ServiceId = 0; + + proto_tree_add_item(tree, hf_opcua_transport_type, tvb, *pOffset, 3, ENC_ASCII|ENC_NA); *pOffset+=3; + proto_tree_add_item(tree, hf_opcua_transport_chunk, tvb, *pOffset, 1, ENC_ASCII|ENC_NA); *pOffset+=1; + proto_tree_add_item(tree, hf_opcua_transport_size, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + proto_tree_add_item(tree, hf_opcua_transport_scid, tvb, *pOffset, 4, ENC_LITTLE_ENDIAN); *pOffset+=4; + + parseSecurityLayer(tree, tvb, pOffset); + + /* add encodeable object subtree */ + encobj_tree = proto_tree_add_subtree(tree, tvb, *pOffset, -1, ett_opcua_extensionobject, &ti, "Message : Encodeable Object"); + + /* add nodeid subtree */ + nodeid_tree = proto_tree_add_subtree(encobj_tree, tvb, *pOffset, -1, ett_opcua_nodeid, &ti_inner, "TypeId : ExpandedNodeId"); + ServiceId = parseServiceNodeId(nodeid_tree, tvb, pOffset); + proto_item_set_end(ti_inner, tvb, *pOffset); + + dispatchService(encobj_tree, tvb, pinfo, pOffset, ServiceId); + + proto_item_set_end(ti, tvb, *pOffset); + return ServiceId; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/opcua/opcua_transport_layer.h b/plugins/epan/opcua/opcua_transport_layer.h new file mode 100644 index 00000000..4e63aa5a --- /dev/null +++ b/plugins/epan/opcua/opcua_transport_layer.h @@ -0,0 +1,27 @@ +/****************************************************************************** +** Copyright (C) 2006-2009 ascolab GmbH. All Rights Reserved. +** Web: http://www.ascolab.com +** +** SPDX-License-Identifier: GPL-2.0-or-later +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** Project: OpcUa Wireshark Plugin +** +** Description: OpcUa Transport Layer Decoder. +** +** Author: Gerhard Gappmeier +******************************************************************************/ + +/* Transport Layer: message parsers */ +int parseHello(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +int parseAcknowledge(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +int parseError(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +int parseReverseHello(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +int parseMessage(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +int parseAbort(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +int parseService(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +int parseOpenSecureChannel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +int parseCloseSecureChannel(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint *pOffset); +void registerTransportLayerTypes(int proto); diff --git a/plugins/epan/pluginifdemo/AUTHORS b/plugins/epan/pluginifdemo/AUTHORS new file mode 100644 index 00000000..ca50630c --- /dev/null +++ b/plugins/epan/pluginifdemo/AUTHORS @@ -0,0 +1,2 @@ +Author : +Roland Knall diff --git a/plugins/epan/pluginifdemo/CMakeLists.txt b/plugins/epan/pluginifdemo/CMakeLists.txt new file mode 100644 index 00000000..95c05a03 --- /dev/null +++ b/plugins/epan/pluginifdemo/CMakeLists.txt @@ -0,0 +1,75 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(pluginifdemo 0 0 2 0) + +SET(CMAKE_AUTOMOC ON) +SET(CMAKE_AUTOUIC ON) + +if(USE_qt6) + set(qtver "6") +else() + set(qtver "5") +endif() + +find_package(Qt${qtver}Core) +find_package(Qt${qtver}PrintSupport) +find_package(Qt${qtver}Widgets) + +set(DISSECTOR_SRC + pluginifdemo.c + ui/uihandler.cpp + ui/uiclasshandler.cpp + ui/pluginifdemo_main.cpp + ui/pluginifdemo_about.cpp + ${UI_SRC} +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +set_source_files_properties( + plugin.c + PROPERTIES + SKIP_AUTOGEN ON +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_wireshark_plugin_library(pluginifdemo epan) + +target_link_libraries(pluginifdemo epan Qt${qtver}::Core Qt${qtver}::Widgets Qt${qtver}::PrintSupport) + +install_plugin(pluginifdemo epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + pluginifdemo + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS} +) diff --git a/plugins/epan/pluginifdemo/README b/plugins/epan/pluginifdemo/README new file mode 100644 index 00000000..7aa753f7 --- /dev/null +++ b/plugins/epan/pluginifdemo/README @@ -0,0 +1,2 @@ +This plugin demonstrates a Qt integration using plugin_if and +menubar_ext functionality. diff --git a/plugins/epan/pluginifdemo/pluginifdemo.c b/plugins/epan/pluginifdemo/pluginifdemo.c new file mode 100644 index 00000000..e6c42b47 --- /dev/null +++ b/plugins/epan/pluginifdemo/pluginifdemo.c @@ -0,0 +1,156 @@ +/* pluginifdemo.c + * Routines for plugin_if demo capability + * Author: Roland Knall + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include +#include +#include +#include +#include "pluginifdemo.h" + +#include "ui/uihandler.h" + +void proto_register_pluginifdemo(void); +void proto_reg_handoff_pluginifdemo(void); + +static int proto_pluginifdemo = -1; + +void toolbar_cb(gpointer object, gpointer item_data, gpointer user_data); + +void +menu_cb(ext_menubar_gui_type gui_type, gpointer gui_data, gpointer user_data _U_) +{ + pluginifdemo_ui_main(gui_type, gui_data); +} + +void +about_cb(ext_menubar_gui_type gui_type _U_, gpointer gui_data _U_, gpointer user_data _U_) +{ + pluginifdemo_ui_about(gui_type, gui_data); +} + +void +proto_register_pluginifdemo(void) +{ + +#if 0 + module_t *pluginif_module = NULL; +#endif + ext_menu_t * ext_menu = NULL; + + proto_pluginifdemo = proto_register_protocol("Plugin IF Demo Protocol", "Pluginifdemo", "pluginifdemo"); + + ext_menu = ext_menubar_register_menu ( proto_pluginifdemo, "Plugin IF Demonstration", TRUE ); + ext_menubar_set_parentmenu (ext_menu, "Tools"); + + ext_menubar_add_entry(ext_menu, "Toolbar Action Demonstrator", "Action demonstrator for the plugin toolbar", menu_cb, NULL); + ext_menubar_add_separator(ext_menu); + ext_menubar_add_website(ext_menu, "Wireshark Development", "See Wireshark Development", "https://www.wireshark.org/develop.html"); + ext_menubar_add_separator(ext_menu); + ext_menubar_add_entry(ext_menu, "&About Plugin IF Demonstration", "Further information", about_cb, NULL); +#if 0 + pluginif_module = prefs_register_protocol(proto_pluginifdemo, NULL); +#endif + + + ext_toolbar_t * tb = ext_toolbar_register_toolbar("Plugin Interface Demo Toolbar"); + + ext_toolbar_add_entry(tb, EXT_TOOLBAR_BUTTON, "Button 1", 0, "Button 1 to press", FALSE, 0, FALSE, 0, toolbar_cb, 0); + ext_toolbar_add_entry(tb, EXT_TOOLBAR_BUTTON, "Button 2", 0, "Button 2 to press", TRUE, 0, FALSE, 0, toolbar_cb, 0); + ext_toolbar_add_entry(tb, EXT_TOOLBAR_BOOLEAN, "Checkbox", 0, "Checkbox to Select", FALSE, 0, FALSE, 0, toolbar_cb, 0); + ext_toolbar_add_entry(tb, EXT_TOOLBAR_STRING, "String 1", "Default String", "String without validation", FALSE, 0, TRUE, 0, toolbar_cb, 0); + ext_toolbar_add_entry(tb, EXT_TOOLBAR_STRING, "String 2", "ABC", "String with validation", FALSE, 0, FALSE, "^[A-Z]+", toolbar_cb, 0); + GList * entries = 0; + entries = ext_toolbar_add_val( entries, "1", "ABCD", FALSE ); + entries = ext_toolbar_add_val(entries, "2", "EFG", FALSE ); + entries = ext_toolbar_add_val(entries, "3", "HIJ", TRUE ); + entries = ext_toolbar_add_val(entries, "4", "KLM", FALSE ); + entries = ext_toolbar_add_val(entries, "5", "NOP", FALSE ); + entries = ext_toolbar_add_val(entries, "6", "QRS", FALSE ); + entries = ext_toolbar_add_val(entries, "7", "TUVW", FALSE ); + entries = ext_toolbar_add_val(entries, "8", "XYZ", FALSE ); + ext_toolbar_add_entry(tb, EXT_TOOLBAR_SELECTOR, "Selector", 0, "Selector to choose from", FALSE, entries, FALSE, 0, toolbar_cb, 0); + + pluginifdemo_toolbar_register(tb); +} + +void* get_frame_data_cb(frame_data* fdata, void* user_data _U_) { + return GUINT_TO_POINTER(fdata->num); +} + +void* get_capture_file_cb(capture_file* cf, void* user_data _U_) { + return cf->filename; +} + +void toolbar_cb(gpointer toolbar_item, gpointer item_data, gpointer user_data _U_) +{ + if ( ! toolbar_item ) + return; + + gchar * message = 0; + ext_toolbar_t * entry = (ext_toolbar_t *)toolbar_item; + + if (entry->item_type == EXT_TOOLBAR_BUTTON) { + pluginifdemo_toolbar_log("Button pressed at toolbar"); + guint32 fnum = GPOINTER_TO_UINT(plugin_if_get_frame_data(get_frame_data_cb, NULL)); + if (fnum) { + message = ws_strdup_printf("Current frame is: %u", fnum); + pluginifdemo_toolbar_log(message); + } + const gchar* fnm = (const gchar*)plugin_if_get_capture_file(get_capture_file_cb, NULL); + if (fnm) { + message = ws_strdup_printf("Capture file name is: %s", fnm); + pluginifdemo_toolbar_log(message); + } + } + else if ( entry->item_type == EXT_TOOLBAR_BOOLEAN ) + { + gboolean data = *((gboolean *)item_data); + message = ws_strdup_printf( "Checkbox selected value: %d", (int) (data) ); + pluginifdemo_toolbar_log(message); + } + else if ( entry->item_type == EXT_TOOLBAR_STRING ) + { + gchar * data = (gchar *)item_data; + message = ws_strdup_printf( "String entered in toolbar: %s", data ); + pluginifdemo_toolbar_log(message); + } + else if ( entry->item_type == EXT_TOOLBAR_SELECTOR ) + { + ext_toolbar_value_t * data = (ext_toolbar_value_t *)item_data; + message = ws_strdup_printf( "Value from toolbar: %s", data->value ); + pluginifdemo_toolbar_log(message); + } + + g_free(message); +} + +void +proto_reg_handoff_pluginifdemo(void) +{ + +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/pluginifdemo/pluginifdemo.h b/plugins/epan/pluginifdemo/pluginifdemo.h new file mode 100644 index 00000000..e928b7fc --- /dev/null +++ b/plugins/epan/pluginifdemo/pluginifdemo.h @@ -0,0 +1,11 @@ +/* pluginifdemo.h + * Definitions for plugin_if_demo structures and routines + * By Steve Limkemann + * Copyright 1998 Steve Limkemann + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ diff --git a/plugins/epan/pluginifdemo/ui/pluginifdemo_about.cpp b/plugins/epan/pluginifdemo/ui/pluginifdemo_about.cpp new file mode 100644 index 00000000..63a69fb1 --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/pluginifdemo_about.cpp @@ -0,0 +1,49 @@ +/* pluginifdemo_about.cpp + * + * Author: Roland Knall + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include + +#include + +#include +#include +#include + +PluginIFDemo_About::PluginIFDemo_About(QWidget *parent) : + QDialog(parent), + ui(new Ui::PluginIFDemo_About) +{ + ui->setupUi(this); +} + +PluginIFDemo_About::~PluginIFDemo_About() +{ + delete ui; +} + +void PluginIFDemo_About::on_buttonBox_clicked(QAbstractButton *) +{ + this->close(); +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/pluginifdemo/ui/pluginifdemo_about.h b/plugins/epan/pluginifdemo/ui/pluginifdemo_about.h new file mode 100644 index 00000000..e7266849 --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/pluginifdemo_about.h @@ -0,0 +1,53 @@ +/* pluginifdemo_about.h + * + * Author: Roland Knall + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef PLUGINIFDEMO_ABOUT_H_ +#define PLUGINIFDEMO_ABOUT_H_ + +#include +#include +#include +#include +#include + +namespace Ui { +class PluginIFDemo_About; +} + +class PluginIFDemo_About : public QDialog +{ + Q_OBJECT + +public: + explicit PluginIFDemo_About(QWidget *parent = 0); + ~PluginIFDemo_About(); + +private slots: + void on_buttonBox_clicked(QAbstractButton *button); + +private: + Ui::PluginIFDemo_About *ui; +}; + +#endif /* PLUGINIFDEMO_ABOUT_H_ */ + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/pluginifdemo/ui/pluginifdemo_about.ui b/plugins/epan/pluginifdemo/ui/pluginifdemo_about.ui new file mode 100644 index 00000000..c31f0583 --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/pluginifdemo_about.ui @@ -0,0 +1,156 @@ + + + PluginIFDemo_About + + + + 0 + 0 + 545 + 401 + + + + + 0 + 0 + + + + + 545 + 401 + + + + + 545 + 401 + + + + Qt::NoContextMenu + + + About Plugin Interface Demonstrator + + + true + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 10 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + <html><head/><body><p><span style=" font-size:10pt;"><br/></span><span style=" font-size:10pt; font-weight:600;">PlugIn Interface Demonstration</span><span style=" font-size:10pt;"><br/>Version: </span><span style=" font-size:10pt; font-weight:600;">0.0.2 </span></p><p><span style=" font-size:10pt;">Copyright © </span><span style=" font-size:10pt; font-style:italic;">Wireshark Foundation</span><span style=" font-size:10pt;"><br/></span><a href="https://www.wireshark.org"><span style=" text-decoration: underline; color:#0000ff;">www.wireshark.org</span></a></p></body></html> + + + true + + + + + + + + License Information + + + + + 10 + 0 + 511 + 102 + + + + <html><head/><body><p>This PlugIn demonstrates functionality of the interface API for plugins and extcap interfaces.</p></body></html> + + + true + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + false + + + + + + + + + + + + diff --git a/plugins/epan/pluginifdemo/ui/pluginifdemo_main.cpp b/plugins/epan/pluginifdemo/ui/pluginifdemo_main.cpp new file mode 100644 index 00000000..a4823817 --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/pluginifdemo_main.cpp @@ -0,0 +1,382 @@ +/* pluginifdemo_main.cpp + * + * Author: Roland Knall + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include +#include + +#include + +#include "uihandler.h" + +#include +#include +#include +#include + +PluginIfType::PluginIfType(const QString &label, const ext_toolbar_item_t &itemType) + : m_label(label), m_itemType(itemType) +{} + +QString PluginIfType::label() const { return m_label; } +ext_toolbar_item_t PluginIfType::itemType() const { return m_itemType; } + +PluginIfTypeModel::PluginIfTypeModel(QObject * parent) + :QAbstractListModel(parent) +{ +} + +void PluginIfTypeModel::addPluginIfType(const PluginIfType &ifType) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_pluginIfTypes << ifType; + endInsertRows(); +} + +int PluginIfTypeModel::rowCount(const QModelIndex &) const +{ + return static_cast(m_pluginIfTypes.count()); +} + +QVariant PluginIfTypeModel::data(const QModelIndex & idx, int role) const +{ + if ( idx.row() < 0 || idx.row() >= m_pluginIfTypes.count() ) + return QVariant(); + + const PluginIfType &ifType = m_pluginIfTypes[idx.row()]; + if ( role == Qt::UserRole ) + { + return ifType.itemType(); + } else if ( role == Qt::DisplayRole ) { + return ifType.label(); + } + + return QVariant(); +} + +PluginIfTypeSortFilterProxyModel::PluginIfTypeSortFilterProxyModel(QObject * parent) +:QSortFilterProxyModel(parent) +{ + m_filterType = EXT_TOOLBAR_BOOLEAN; +} + +void PluginIfTypeSortFilterProxyModel::setFilterElement(ext_toolbar_item_t filterType) +{ + m_filterType = filterType; + invalidateFilter(); +} + +bool PluginIfTypeSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QModelIndex dataIndex = sourceModel()->index(sourceRow, 0, sourceParent); + QVariant varData = sourceModel()->data(dataIndex, Qt::UserRole); + if ( varData.isValid() && varData.toInt() == (int) m_filterType ) + return true; + + return false; +} + +PluginIFDemo_Main::PluginIFDemo_Main(QWidget *parent) : + QDialog(parent), + ui(new Ui::PluginIFDemo_Main) +{ + ui->setupUi(this); + + _toolbar = 0; + sourceModel = new PluginIfTypeModel(this); + proxyModel = new PluginIfTypeSortFilterProxyModel(this); + proxyModel->setSourceModel(sourceModel); + ui->cmbElements->setModel(proxyModel); + + listModel = new QStandardItemModel(this); + ui->lstItems->setModel(listModel); + + indexModel = new QStandardItemModel(this); + ui->cmbEntryIndex->setModel(indexModel); + + ui->logView->setModel(new QStandardItemModel(ui->logView)); + + ui->tabInterfaceTypes->setCurrentIndex(0); + + connect ( GuiHandler::getInstance(), SIGNAL(reset(void)), this, SLOT(closeDialog()) ); + connect ( GuiHandler::getInstance(), SIGNAL(logChanged(QString)), this, SLOT(logChanged(QString)) ); +} + +PluginIFDemo_Main::~PluginIFDemo_Main() +{ + delete ui; +} + +void PluginIFDemo_Main::setToolbar(ext_toolbar_t * &toolbar) +{ + _toolbar = toolbar; + + GList * walker = toolbar->children; + while ( walker && walker->data ) + { + ext_toolbar_t * entry = (ext_toolbar_t *)walker->data; + if ( entry && entry->type == EXT_TOOLBAR_ITEM && entry->name ) + sourceModel->addPluginIfType(PluginIfType(QString(entry->name), entry->item_type)); + walker = g_list_next(walker); + } +} + +void PluginIFDemo_Main::closeDialog() +{ + this->close(); +} + +void PluginIFDemo_Main::on_buttonBox_clicked(QAbstractButton *button _U_) +{ + this->close(); +} + +void PluginIFDemo_Main::logChanged(QString message) +{ + QStandardItemModel * model = (QStandardItemModel *) ui->logView->model(); + model->appendRow(new QStandardItem(message)); +} + +void PluginIFDemo_Main::on_btnSendButtonText_clicked() +{ + if ( ! _toolbar ) + return; + + ext_toolbar_t *item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item ) + return; + + QString entryText = ui->txtButtonName->text(); + bool silent = ui->chkSilent->checkState() == Qt::Checked ? true : false; + + ext_toolbar_update_value(item, (gpointer) entryText.toStdString().c_str(), silent); +} + +void PluginIFDemo_Main::on_btnSendText_clicked() +{ + if ( ! _toolbar ) + return; + + ext_toolbar_t *item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item ) + return; + + QString entryText = ui->txtEdit->text(); + bool silent = ui->chkSilent->checkState() == Qt::Checked ? true : false; + + ext_toolbar_update_value(item, (gpointer) entryText.toStdString().c_str(), silent); +} + +void PluginIFDemo_Main::on_chkTestCheckbox_stateChanged(int newState) +{ + if ( ! _toolbar ) + return; + + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item ) + return; + bool silent = ui->chkSilent->checkState() == Qt::Checked ? true : false; + + ext_toolbar_update_value(item, GINT_TO_POINTER(newState == Qt::Checked ? 1 : 0), silent); +} + +void PluginIFDemo_Main::on_tabInterfaceTypes_currentChanged(int newTab) +{ + proxyModel->setFilterElement((ext_toolbar_item_t) newTab); +} + +void PluginIFDemo_Main::on_cmbElements_currentTextChanged(const QString & newText) +{ + if ( ! _toolbar ) + return; + + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, newText.toStdString().c_str()); + if ( ! item || item->item_type != EXT_TOOLBAR_SELECTOR ) + return; + + listModel->clear(); + indexModel->clear(); + + GList * walker = item->values; + while ( walker && walker->data ) + { + ext_toolbar_value_t * listItem = (ext_toolbar_value_t *)walker->data; + QString content = QString("%1: %2").arg(listItem->value).arg(listItem->display); + listModel->appendRow(new QStandardItem(content)); + indexModel->appendRow(new QStandardItem(listItem->value)); + + walker = g_list_next(walker); + } + +} + +void PluginIFDemo_Main::on_btnEnable_clicked() +{ + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item ) + return; + + ext_toolbar_update_data_set_active(item, true); +} + +void PluginIFDemo_Main::on_btnDisable_clicked() +{ + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item ) + return; + + ext_toolbar_update_data_set_active(item, false); +} + +void PluginIFDemo_Main::on_btnAddItem_clicked() +{ + if ( ui->txtNewItemDisplay->text().length() <= 0 || ui->txtNewItemValue->text().length() <= 0 ) + return; + + QString content = QString("%1: %2").arg(ui->txtNewItemValue->text()).arg(ui->txtNewItemDisplay->text()); + + QList items = listModel->findItems(content); + if ( items.count() > 0 ) + return; + items = listModel->findItems(QString("%1: ").arg(ui->txtNewItemValue->text()), Qt::MatchStartsWith); + if ( items.count() > 0 ) + return; + + listModel->appendRow(new QStandardItem(content)); + + if ( ui->chkAddRemoveImmediate->checkState() == Qt::Checked ) + { + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item || item->item_type != EXT_TOOLBAR_SELECTOR ) + return; + + bool silent = ui->chkSilent->checkState() == Qt::Checked ? true : false; + + gchar * value = g_strdup(ui->txtNewItemValue->text().toUtf8().constData()); + gchar * display = g_strdup(ui->txtNewItemDisplay->text().toUtf8().constData()); + ext_toolbar_update_data_add_entry(item, display, value, silent); + g_free(value); + g_free(display); + } +} + +void PluginIFDemo_Main::on_btnRemoveItem_clicked() +{ + QItemSelectionModel * selModel = ui->lstItems->selectionModel(); + + if ( selModel->selectedIndexes().count() == 0 ) + return; + + QModelIndexList selIndeces = selModel-> selectedIndexes(); + foreach(QModelIndex idx, selIndeces) + { + if ( ui->chkAddRemoveImmediate->checkState() == Qt::Checked ) + { + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item || item->item_type != EXT_TOOLBAR_SELECTOR ) + return; + + bool silent = ui->chkSilent->checkState() == Qt::Checked ? true : false; + + QString content = listModel->data(idx).toString(); + int pos = static_cast(content.indexOf(":")); + + gchar * value = g_strdup(content.left(pos).toUtf8().constData() ); + /* -2 because removal of : and space */ + gchar * display = g_strdup(content.right(content.size() - pos - 2).toUtf8().constData()); + ext_toolbar_update_data_remove_entry(item, display, value, silent); + g_free(value); + g_free(display); + } + + listModel->removeRow(idx.row()); + } +} + +void PluginIFDemo_Main::on_btnSendList_clicked() +{ + if ( ! _toolbar ) + return; + + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item || item->item_type != EXT_TOOLBAR_SELECTOR ) + return; + + GList * items = NULL; + + for( int i = 0; i < listModel->rowCount(); i++ ) + { + QString content = listModel->data(listModel->index(i, 0)).toString(); + int pos = static_cast(content.indexOf(":")); + + ext_toolbar_value_t * valEntry = g_new0(ext_toolbar_value_t, 1); + valEntry->value = g_strdup(content.left(pos).toUtf8().constData()); + valEntry->display = g_strdup(content.right(content.size() - pos + 1).toUtf8().constData()); + + items = g_list_append(items, valEntry); + } + + bool silent = ui->chkSilent->checkState() == Qt::Checked ? true : false; + + ext_toolbar_update_data(item, items , silent); +} + +void PluginIFDemo_Main::on_btnSendUpdateItem_clicked() +{ + if ( ! _toolbar ) + return; + + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item || item->item_type != EXT_TOOLBAR_SELECTOR ) + return; + + QString cmbIndexText = ui->cmbEntryIndex->currentText(); + QString displayValue = ui->txtUpdateDisplayValue->text(); + if ( displayValue.length() == 0 ) + return; + + bool silent = ui->chkSilent->checkState() == Qt::Checked ? true : false; + + ext_toolbar_update_data_by_index(item, + (gpointer) displayValue.toStdString().c_str(), (gpointer) cmbIndexText.toStdString().c_str(), silent ); +} + +void PluginIFDemo_Main::on_lstItems_clicked(const QModelIndex &idx) +{ + if ( ! _toolbar || ! idx.isValid() ) + return; + + ext_toolbar_t * item = ext_toolbar_entry_by_label(_toolbar, ui->cmbElements->currentText().toStdString().c_str()); + if ( ! item || item->item_type != EXT_TOOLBAR_SELECTOR ) + return; + + bool silent = ui->chkSilent->checkState() == Qt::Checked ? true : false; + + QString content = listModel->data(listModel->index(idx.row(), 0)).toString(); + int pos = static_cast(content.indexOf(":")); + + gchar * idxData = g_strdup(content.left(pos).toUtf8().constData() ); + + ext_toolbar_update_value(item, idxData, silent); + g_free(idxData); + +} +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/pluginifdemo/ui/pluginifdemo_main.h b/plugins/epan/pluginifdemo/ui/pluginifdemo_main.h new file mode 100644 index 00000000..e0bafaab --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/pluginifdemo_main.h @@ -0,0 +1,124 @@ +/* pluginifdemo_main.h + * + * Author: Roland Knall + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef PLUGINIFDEMO_MAIN_H_ +#define PLUGINIFDEMO_MAIN_H_ + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace Ui { +class PluginIFDemo_Main; +} + +class PluginIfType +{ +public: + PluginIfType(const QString &label, const ext_toolbar_item_t &itemType); + + QString label() const; + ext_toolbar_item_t itemType() const; +private: + QString m_label; + ext_toolbar_item_t m_itemType; +}; + +class PluginIfTypeModel : public QAbstractListModel +{ + Q_OBJECT +public: + PluginIfTypeModel(QObject * parent = 0); + + void addPluginIfType(const PluginIfType & pluginIfType); + + int rowCount(const QModelIndex & parent = QModelIndex()) const; + QVariant data(const QModelIndex & idx, int role = Qt::DisplayRole) const; + +private: + QList m_pluginIfTypes; + +}; + +class PluginIfTypeSortFilterProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + PluginIfTypeSortFilterProxyModel(QObject * parent = 0); + + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; + + void setFilterElement(ext_toolbar_item_t filterType); + +private: + ext_toolbar_item_t m_filterType; +}; + +class PluginIFDemo_Main : public QDialog +{ + Q_OBJECT + +public: + explicit PluginIFDemo_Main(QWidget *parent = 0); + ~PluginIFDemo_Main(); + + void setToolbar(ext_toolbar_t * &toolbar); + +private slots: + void on_buttonBox_clicked(QAbstractButton *button); + void on_btnSendButtonText_clicked(); + void on_btnSendText_clicked(); + void on_btnSendUpdateItem_clicked(); + void on_chkTestCheckbox_stateChanged(int newState); + void on_tabInterfaceTypes_currentChanged(int newTab); + void on_btnAddItem_clicked(); + void on_btnRemoveItem_clicked(); + void on_btnSendList_clicked(); + void on_cmbElements_currentTextChanged(const QString & newText); + void on_lstItems_clicked(const QModelIndex &idx); + void on_btnEnable_clicked(); + void on_btnDisable_clicked(); + + void logChanged(QString message); + void closeDialog(); + +private: + Ui::PluginIFDemo_Main *ui; + + PluginIfTypeModel * sourceModel; + PluginIfTypeSortFilterProxyModel * proxyModel; + QStandardItemModel * listModel; + QStandardItemModel * indexModel; + + ext_toolbar_t * _toolbar; +}; + + +#endif /* PLUGINIFDEMO_MAIN_H_ */ + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/pluginifdemo/ui/pluginifdemo_main.ui b/plugins/epan/pluginifdemo/ui/pluginifdemo_main.ui new file mode 100644 index 00000000..467ec85e --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/pluginifdemo_main.ui @@ -0,0 +1,369 @@ + + + PluginIFDemo_Main + + + + 0 + 0 + 500 + 570 + + + + + 500 + 570 + + + + MainWindow + + + + + + 3 + + + + Boolean + + + + + + Check the value in the toolbar checkbox + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Button + + + + + + + + Text to be sent to toolbar + + + + + + + Send Text + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + String + + + + + + + + Text to be sent to toolbar + + + + + + + Send Text + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Selector + + + + + + + + Display: + + + txtNewItemDisplay + + + + + + + Enter display text + + + + + + + Value: + + + txtNewItemValue + + + + + + + Enter value text + + + + + + + Add + + + + + + + + + + + + + + + + Remove + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Send List + + + + + + + + + + + Add and remove will immediately be send to interface + + + true + + + + + + + Update interface with selection + + + true + + + + + + + Qt::Horizontal + + + + + + + + + Update + + + cmbEntryIndex + + + + + + + + + + with + + + txtUpdateDisplayValue + + + + + + + Enter value text + + + + + + + Send + + + + + + + + + + + + + QFrame::Plain + + + 1 + + + Qt::Horizontal + + + + + + + + + Element to be updated + + + cmbElements + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Enable element + + + + + + + Disable element + + + + + + + + + + + + Activate updates silently + + + + + + + + + + QDialogButtonBox::Close + + + + + + + + diff --git a/plugins/epan/pluginifdemo/ui/uiclasshandler.cpp b/plugins/epan/pluginifdemo/ui/uiclasshandler.cpp new file mode 100644 index 00000000..6550bf2f --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/uiclasshandler.cpp @@ -0,0 +1,116 @@ +/* uiclasshandler.cpp + * + * Author: Roland Knall + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include + +#include + +#include +#include +#include + +#include + +#if defined(_WIN32) +#define _WINSOCKAPI_ +#endif + +#include + +#include "uihandler.h" +#include "pluginifdemo_main.h" +#include "pluginifdemo_about.h" + +QMutex * GuiHandler::singletonMutex = new QMutex(); + +GuiHandler::GuiHandler() +{ +} + +GuiHandler * GuiHandler::getInstance() +{ + static GuiHandler * instance = 0; + + QMutexLocker locker(singletonMutex); + + if ( instance == 0 ) + { + instance = new GuiHandler(); + } + + return instance; +} + +void GuiHandler::showAboutDialog(ext_menubar_gui_type gui_type _U_, gpointer gui_data _U_) +{ + PluginIFDemo_About * mainwindow = new PluginIFDemo_About(); + executeDialog((QDialog*)mainwindow); +} + +void GuiHandler::showMainDialog(ext_menubar_gui_type gui_type _U_, gpointer gui_data _U_) +{ + PluginIFDemo_Main * mainwindow = new PluginIFDemo_Main(); + mainwindow->setToolbar(_toolbar); + executeDialog((QDialog*)mainwindow); +} + +void GuiHandler::executeDialog(QDialog * dialog) +{ + bool hasGuiApp = (qobject_cast(QCoreApplication::instance())!=0); + + if ( ! hasGuiApp ) + { + /* Necessity for creating the correct app context */ + int argc = 1; + char * argv = (char *) "Test"; + + /* In Gtk there is no application context, must be created and displayed */ + QApplication app(argc, &argv); + + dialog->show(); + + app.exec(); + } + else + { + /* With Wireshark Qt, an application context already exists, therefore just + * displaying the dialog using show to have it non-modal */ + dialog->show(); + } +} + +void GuiHandler::doReset() +{ + emit reset(); +} + +void GuiHandler::addLogMessage(QString message) +{ + emit logChanged(message); +} + +void GuiHandler::setToolbar(ext_toolbar_t * toolbar) +{ + _toolbar = toolbar; +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/pluginifdemo/ui/uihandler.cpp b/plugins/epan/pluginifdemo/ui/uihandler.cpp new file mode 100644 index 00000000..34d9c68b --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/uihandler.cpp @@ -0,0 +1,74 @@ +/* uihandler.cpp + * Author: Roland Knall + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include + +#include + +#include +#include + +#include +#include + +#if defined(_WIN32) +#define _WINSOCKAPI_ +#endif + +#include + +#include "uihandler.h" +#include + +static void +reset_dialog(void *data _U_) +{ + GuiHandler::getInstance()->doReset(); +} + +void pluginifdemo_ui_main(ext_menubar_gui_type gui_type, gpointer gui_data) +{ + /* ensures, that the dialog is closing, if scm udid is set or a filter is applied */ + GString *error_string = register_tap_listener("frame", NULL, NULL, 0, reset_dialog, NULL, NULL, NULL); + + if (error_string != NULL) { + fprintf(stderr, "%s ", error_string->str); + g_string_free(error_string, TRUE); + } + GuiHandler::getInstance()->showMainDialog(gui_type, gui_data); +} + +void pluginifdemo_ui_about(ext_menubar_gui_type gui_type, gpointer gui_data) +{ + GuiHandler::getInstance()->showAboutDialog(gui_type, gui_data); +} + +void pluginifdemo_toolbar_log(const gchar * message) +{ + GuiHandler::getInstance()->addLogMessage(QString(message)); +} + +void pluginifdemo_toolbar_register(ext_toolbar_t * toolbar) +{ + GuiHandler::getInstance()->setToolbar(toolbar); +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/pluginifdemo/ui/uihandler.h b/plugins/epan/pluginifdemo/ui/uihandler.h new file mode 100644 index 00000000..34536029 --- /dev/null +++ b/plugins/epan/pluginifdemo/ui/uihandler.h @@ -0,0 +1,89 @@ +/* uihandler.h + * Author: Roland Knall + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef PLUGINIFDEMO_UI_UIHANDLER_H_ +#define PLUGINIFDEMO_UI_UIHANDLER_H_ + +#ifdef __cplusplus + +#include +#include +#include + +#include + +#include "ws_symbol_export.h" + +class GuiHandler : public QObject +{ + Q_OBJECT + +public: + + static GuiHandler * getInstance(); + + void showAboutDialog(ext_menubar_gui_type gui_type, gpointer gui_data); + void showMainDialog(ext_menubar_gui_type gui_type, gpointer gui_data); + + void doReset(); + + void addLogMessage(QString message); + + void setToolbar(ext_toolbar_t * toolbar); + ext_toolbar_t * toolBar(); + +signals: + void reset(); + void logChanged(QString newEntry); + +protected: + + GuiHandler(); + + // Stop the compiler generating methods of "copy the object" + GuiHandler(GuiHandler const& copy); // Not implemented + GuiHandler& operator=(GuiHandler const& copy); // Not implemented + +private: + + static QMutex * singletonMutex; + + ext_toolbar_t * _toolbar; + + void executeDialog(QDialog * object); +}; + +extern "C" { +#endif + +extern void pluginifdemo_ui_about(ext_menubar_gui_type gui_type, gpointer gui_data); +extern void pluginifdemo_ui_main(ext_menubar_gui_type gui_type, gpointer gui_data); +extern void pluginifdemo_toolbar_log(const gchar * message); + +extern void pluginifdemo_toolbar_register(ext_toolbar_t * toolbar); + +#ifdef __cplusplus +} +#endif + +#endif /* BURANALYZER_UI_UIHANDLER_H_ */ + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/AUTHORS b/plugins/epan/profinet/AUTHORS new file mode 100644 index 00000000..4979d260 --- /dev/null +++ b/plugins/epan/profinet/AUTHORS @@ -0,0 +1,4 @@ +Author : +Ulf Lamping +Tobias Scholz +Birol Capa \ No newline at end of file diff --git a/plugins/epan/profinet/CMakeLists.txt b/plugins/epan/profinet/CMakeLists.txt new file mode 100644 index 00000000..7e6ca56b --- /dev/null +++ b/plugins/epan/profinet/CMakeLists.txt @@ -0,0 +1,80 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(profinet 0 2 4 0) + +set(DISSECTOR_SRC + packet-dcerpc-pn-io.c + packet-dcom-cba.c + packet-dcom-cba-acco.c + packet-pn-dcp.c + packet-pn-mrp.c + packet-pn-mrrt.c + packet-pn-ptcp.c + packet-pn-rt.c + packet-pn-rtc-one.c + packet-pn-rsi.c +) + +set(DISSECTOR_SUPPORT_SRC + packet-pn.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +add_wireshark_plugin_library(profinet epan) + +target_link_libraries(profinet epan) + +install_plugin(profinet epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + profinet + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/profinet/ChangeLog b/plugins/epan/profinet/ChangeLog new file mode 100644 index 00000000..5298f567 --- /dev/null +++ b/plugins/epan/profinet/ChangeLog @@ -0,0 +1,33 @@ +Overview of changes in Art-Net Ethereal plugin: + +Version 0.0.0: + +* initial implementation + +Version 0.0.1: + +* some experiments + +Version 0.1.0: + +* first official plugin + +Version 0.1.1: + +* fixed some bugs in the PN-IO dissection found with fuzz-test.sh + +Version 0.1.2: + +* PN-DCP: dissection of "DHCP/DHCP client identifier" suboption was added + +Version 0.2.0: + +* PN-PTCP: add whole new Precision Time Control Protocol dissector + +Version 0.2.1: + +* PN-MRP and PN-MRRT: add new Media Redundancy Protocol and Media Redundacy for RealTime Protocol dissector + +Version 0.2.2: + +* PN-IO: RT class 3 packets and some more blocks diff --git a/plugins/epan/profinet/packet-dcerpc-pn-io.c b/plugins/epan/profinet/packet-dcerpc-pn-io.c new file mode 100644 index 00000000..34e08aee --- /dev/null +++ b/plugins/epan/profinet/packet-dcerpc-pn-io.c @@ -0,0 +1,17887 @@ +/* packet-dcerpc-pn-io.c + * Routines for PROFINET IO dissection. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * The PN-IO protocol is a field bus protocol related to decentralized + * periphery and is developed by the PROFIBUS Nutzerorganisation e.V. (PNO), + * see: www.profibus.com + * + * + * PN-IO is based on the common DCE-RPC and the "lightweight" PN-RT + * (ethernet type 0x8892) protocols. + * + * The context manager (CM) part is handling context information + * (like establishing, ...) and is using DCE-RPC as its underlying + * protocol. + * + * The actual cyclic data transfer and acyclic notification uses the + * "lightweight" PN-RT protocol. + * + * There are some other related PROFINET protocols (e.g. PN-DCP, which is + * handling addressing topics). + * + * Please note: the PROFINET CBA protocol is independent of the PN-IO protocol! + */ + +/* + * Cyclic PNIO RTC1 Data Dissection: + * + * To dissect cyclic PNIO RTC1 frames, this plug-in has to collect important module + * information out of "Ident OK", "Connect Request" and "Write Response" + * frames first. This information will be used within "packet-pn-rtc-one.c" to + * dissect PNIO and PROFIsafe RTC1 frames. + * + * The data of Stationname-, -type and -id will be gained out of + * packet-pn-dcp.c. The header packet-pn.h will save those data. + * + * Overview for cyclic PNIO RTC1 data dissection functions: + * -> dissect_IOCRBlockReq_block (Save amount of IODataObjects, IOCS) + * -> dissect_DataDescription (Save important values for cyclic data) + * -> dissect_ExpectedSubmoduleBlockReq_block (Get GSD information) + * -> dissect_ModuleDiffBlock_block (Module has different ID) + * -> dissect_ProfiSafeParameterRequest (Save PROFIsafe parameters) + * -> dissect_RecordDataWrite (Call ProfiSafeParameterRequest) + * -> pnio_rtc1_cleanup (Reset routine of saved RTC1 information) + */ + + +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "packet-pn.h" + +#include +#include + +void proto_register_pn_io(void); +void proto_reg_handoff_pn_io(void); + + +#define MAX_NAMELENGTH 200 /* max. length of the given paths */ +#define F_MESSAGE_TRAILER_4BYTE 4 /* PROFIsafe: Defines the Amount of Bytes for CRC and Status-/Controlbyte */ +#define PN_INPUT_CR 1 /* PROFINET Input Connect Request value */ +#define PN_INPUT_DATADESCRITPION 1 /* PROFINET Input Data Description value */ + +#define PA_PROFILE_API 0x9700u +#define PA_PROFILE_DAP_MASK 0xFFFF0000u +#define PA_PROFILE_DAP_IDENT 0x00FD0000u + +#define PA_PROFILE_BLOCK_DAP 0u +#define PA_PROFILE_BLOCK_PB 1u +#define PA_PROFILE_BLOCK_FB 2u +#define PA_PROFILE_BLOCK_TB 3u + +#define PA_PROFILE_TB_PARENT_PRESSURE 1u +#define PA_PROFILE_TB_PARENT_TEMPERATURE 2u +#define PA_PROFILE_TB_PARENT_FLOW 3u +#define PA_PROFILE_TB_PARENT_LEVEL 1u +#define PA_PROFILE_TB_PARENT_ACTUATOR 1u +#define PA_PROFILE_TB_PARENT_DISCRETE_IO 1u +#define PA_PROFILE_TB_PARENT_LIQUID_ANALYZER 1u +#define PA_PROFILE_TB_PARENT_GAS_ANALYZER 1u +#define PA_PROFILE_TB_PARENT_ENUMERATED_IO 1u +#define PA_PROFILE_TB_PARENT_BINARY_IO 1u + + + +static int proto_pn_io = -1; +static int proto_pn_io_device = -1; +static int proto_pn_io_controller = -1; +static int proto_pn_io_supervisor = -1; +static int proto_pn_io_parameterserver = -1; +static int proto_pn_io_implicitar = -1; +int proto_pn_io_apdu_status = -1; +int proto_pn_io_time_aware_status = -1; + +static int hf_pn_io_opnum = -1; +static int hf_pn_io_reserved16 = -1; + +static int hf_pn_io_array = -1; +static int hf_pn_io_args_max = -1; +static int hf_pn_io_args_len = -1; +static int hf_pn_io_array_max_count = -1; +static int hf_pn_io_array_offset = -1; +static int hf_pn_io_array_act_count = -1; + +static int hf_pn_io_ar_type = -1; +static int hf_pn_io_artype_req = -1; +static int hf_pn_io_cminitiator_macadd = -1; +static int hf_pn_io_cminitiator_objectuuid = -1; +static int hf_pn_io_parameter_server_objectuuid = -1; +static int hf_pn_io_ar_data = -1; +static int hf_pn_io_ar_properties = -1; +static int hf_pn_io_ar_properties_state = -1; +static int hf_pn_io_ar_properties_supervisor_takeover_allowed = -1; +static int hf_pn_io_ar_properties_parameterization_server = -1; +/* removed within 2.3 +static int hf_pn_io_ar_properties_data_rate = -1; +*/ +static int hf_pn_io_ar_properties_reserved_1 = -1; +static int hf_pn_io_ar_properties_device_access = -1; +static int hf_pn_io_ar_properties_companion_ar = -1; +static int hf_pn_io_ar_properties_achnowledge_companion_ar = -1; +static int hf_pn_io_ar_properties_reserved = -1; +static int hf_pn_io_ar_properties_time_aware_system = -1; +static int hf_pn_io_ar_properties_combined_object_container_with_legacy_startupmode = -1; +static int hf_pn_io_ar_properties_combined_object_container_with_advanced_startupmode = -1; +static int hf_pn_io_ar_properties_pull_module_alarm_allowed = -1; + +static int hf_pn_RedundancyInfo = -1; +static int hf_pn_RedundancyInfo_reserved = -1; +static int hf_pn_io_number_of_ARDATAInfo = -1; + +static int hf_pn_io_cminitiator_activitytimeoutfactor = -1; +static int hf_pn_io_cminitiator_udprtport = -1; +static int hf_pn_io_station_name_length = -1; +static int hf_pn_io_cminitiator_station_name = -1; +/* static int hf_pn_io_responder_station_name = -1; */ +static int hf_pn_io_arproperties_StartupMode = -1; + +static int hf_pn_io_parameter_server_station_name = -1; + +static int hf_pn_io_cmresponder_macadd = -1; +static int hf_pn_io_cmresponder_udprtport = -1; + +static int hf_pn_io_number_of_iocrs = -1; +static int hf_pn_io_iocr_tree = -1; +static int hf_pn_io_iocr_type = -1; +static int hf_pn_io_iocr_reference = -1; +static int hf_pn_io_iocr_SubframeOffset = -1; +static int hf_pn_io_iocr_SubframeData =-1; +/* static int hf_pn_io_iocr_txports_port = -1; */ +/* static int hf_pn_io_iocr_txports_redundantport = -1; */ +static int hf_pn_io_sr_properties_Reserved_1 = -1; +static int hf_pn_io_sr_properties_Mode = -1; +static int hf_pn_io_sr_properties_Reserved_2 = -1; +static int hf_pn_io_sr_properties_Reserved_3 = -1; +static int hf_pn_io_RedundancyDataHoldFactor = -1; +static int hf_pn_io_sr_properties = -1; +static int hf_pn_io_sr_properties_InputValidOnBackupAR_with_SRProperties_Mode_0 = -1; +static int hf_pn_io_sr_properties_InputValidOnBackupAR_with_SRProperties_Mode_1 = -1; + +static int hf_pn_io_arvendor_strucidentifier_if0_low = -1; +static int hf_pn_io_arvendor_strucidentifier_if0_high = -1; +static int hf_pn_io_arvendor_strucidentifier_if0_is8000= -1; +static int hf_pn_io_arvendor_strucidentifier_not0 = -1; + +static int hf_pn_io_lt = -1; +static int hf_pn_io_iocr_properties = -1; +static int hf_pn_io_iocr_properties_rtclass = -1; +static int hf_pn_io_iocr_properties_reserved_1 = -1; +static int hf_pn_io_iocr_properties_media_redundancy = -1; +static int hf_pn_io_iocr_properties_reserved_2 = -1; +static int hf_pn_io_iocr_properties_reserved_3 = -1; +static int hf_pn_io_iocr_properties_fast_forwarding_mac_adr = -1; +static int hf_pn_io_iocr_properties_distributed_subframe_watchdog = -1; +static int hf_pn_io_iocr_properties_full_subframe_structure = -1; + + +static int hf_pn_io_data_length = -1; +static int hf_pn_io_ir_frame_data = -1; +static int hf_pn_io_frame_id = -1; +static int hf_pn_io_send_clock_factor = -1; +static int hf_pn_io_reduction_ratio = -1; +static int hf_pn_io_phase = -1; +static int hf_pn_io_sequence = -1; +static int hf_pn_io_frame_send_offset = -1; +static int hf_pn_io_frame_data_properties = -1; +static int hf_pn_io_frame_data_properties_forwarding_Mode = -1; +static int hf_pn_io_frame_data_properties_FastForwardingMulticastMACAdd = -1; +static int hf_pn_io_frame_data_properties_FragmentMode = -1; +static int hf_pn_io_frame_data_properties_reserved_1 = -1; +static int hf_pn_io_frame_data_properties_reserved_2 = -1; +static int hf_pn_io_watchdog_factor = -1; +static int hf_pn_io_data_hold_factor = -1; +static int hf_pn_io_iocr_tag_header = -1; +static int hf_pn_io_iocr_multicast_mac_add = -1; +static int hf_pn_io_number_of_apis = -1; +static int hf_pn_io_number_of_io_data_objects = -1; +static int hf_pn_io_io_data_object_frame_offset = -1; +static int hf_pn_io_number_of_iocs = -1; +static int hf_pn_io_iocs_frame_offset = -1; + +static int hf_pn_io_SFIOCRProperties = -1; +static int hf_pn_io_DistributedWatchDogFactor = -1; +static int hf_pn_io_RestartFactorForDistributedWD = -1; +static int hf_pn_io_SFIOCRProperties_DFPmode = -1; +static int hf_pn_io_SFIOCRProperties_reserved_1 = -1; +static int hf_pn_io_SFIOCRProperties_reserved_2 = -1; +static int hf_pn_io_SFIOCRProperties_DFPType =-1; +static int hf_pn_io_SFIOCRProperties_DFPRedundantPathLayout = -1; +static int hf_pn_io_SFIOCRProperties_SFCRC16 = -1; + +static int hf_pn_io_subframe_data = -1; +static int hf_pn_io_subframe_data_reserved1 = -1; +static int hf_pn_io_subframe_data_reserved2 = -1; + +static int hf_pn_io_subframe_data_position = -1; +static int hf_pn_io_subframe_reserved1 = -1; +static int hf_pn_io_subframe_data_length = -1; +static int hf_pn_io_subframe_reserved2 = -1; + +static int hf_pn_io_alarmcr_type = -1; +static int hf_pn_io_alarmcr_properties = -1; +static int hf_pn_io_alarmcr_properties_priority = -1; +static int hf_pn_io_alarmcr_properties_transport = -1; +static int hf_pn_io_alarmcr_properties_reserved = -1; + +static int hf_pn_io_rta_timeoutfactor = -1; +static int hf_pn_io_rta_retries = -1; +static int hf_pn_io_localalarmref = -1; +static int hf_pn_io_remotealarmref = -1; +static int hf_pn_io_maxalarmdatalength = -1; +static int hf_pn_io_alarmcr_tagheaderhigh = -1; +static int hf_pn_io_alarmcr_tagheaderlow = -1; + +static int hf_pn_io_IRData_uuid = -1; +static int hf_pn_io_ar_uuid = -1; +static int hf_pn_io_target_ar_uuid = -1; +static int hf_pn_io_ar_discriminator = -1; +static int hf_pn_io_ar_configid = -1; +static int hf_pn_io_ar_arnumber = -1; +static int hf_pn_io_ar_arresource = -1; +static int hf_pn_io_ar_arreserved = -1; +static int hf_pn_io_ar_selector = -1; +static int hf_pn_io_api_tree = -1; +static int hf_pn_io_module_tree = -1; +static int hf_pn_io_submodule_tree = -1; +static int hf_pn_io_io_data_object = -1; +/* General module information */ +static int hf_pn_io_io_cs = -1; + +static int hf_pn_io_substitutionmode = -1; + +static int hf_pn_io_api = -1; +static int hf_pn_io_slot_nr = -1; +static int hf_pn_io_subslot_nr = -1; +static int hf_pn_io_index = -1; +static int hf_pn_io_seq_number = -1; +static int hf_pn_io_record_data_length = -1; +static int hf_pn_io_add_val1 = -1; +static int hf_pn_io_add_val2 = -1; + +static int hf_pn_io_block = -1; +static int hf_pn_io_block_header = -1; +static int hf_pn_io_block_type = -1; +static int hf_pn_io_block_length = -1; +static int hf_pn_io_block_version_high = -1; +static int hf_pn_io_block_version_low = -1; + +static int hf_pn_io_sessionkey = -1; +static int hf_pn_io_control_alarm_sequence_number = -1; +static int hf_pn_io_control_command = -1; +static int hf_pn_io_control_command_prmend = -1; +static int hf_pn_io_control_command_applready = -1; +static int hf_pn_io_control_command_release = -1; +static int hf_pn_io_control_command_done = -1; +static int hf_pn_io_control_command_ready_for_companion = -1; +static int hf_pn_io_control_command_ready_for_rt_class3 = -1; +static int hf_pn_io_control_command_prmbegin = -1; +static int hf_pn_io_control_command_reserved_7_15 = -1; +static int hf_pn_io_control_block_properties = -1; +static int hf_pn_io_control_block_properties_applready = -1; +static int hf_pn_io_control_block_properties_applready_bit0 = -1; +static int hf_pn_io_control_block_properties_applready_bit1 = -1; +static int hf_pn_io_control_block_properties_applready_otherbits = -1; + +/* static int hf_pn_io_AlarmSequenceNumber = -1; */ +static int hf_pn_io_control_command_reserved = -1; +static int hf_pn_io_SubmoduleListEntries = -1; + +static int hf_pn_io_alarm_type = -1; +static int hf_pn_io_alarm_specifier = -1; +static int hf_pn_io_alarm_specifier_sequence = -1; +static int hf_pn_io_alarm_specifier_channel = -1; +static int hf_pn_io_alarm_specifier_manufacturer = -1; +static int hf_pn_io_alarm_specifier_submodule = -1; +static int hf_pn_io_alarm_specifier_ardiagnosis = -1; + +static int hf_pn_io_alarm_dst_endpoint = -1; +static int hf_pn_io_alarm_src_endpoint = -1; +static int hf_pn_io_pdu_type = -1; +static int hf_pn_io_pdu_type_type = -1; +static int hf_pn_io_pdu_type_version = -1; +static int hf_pn_io_add_flags = -1; +static int hf_pn_io_window_size = -1; +static int hf_pn_io_tack = -1; +static int hf_pn_io_send_seq_num = -1; +static int hf_pn_io_ack_seq_num = -1; +static int hf_pn_io_var_part_len = -1; + +static int hf_pn_io_number_of_modules = -1; +static int hf_pn_io_module_ident_number = -1; +static int hf_pn_io_module_properties = -1; +static int hf_pn_io_module_state = -1; +static int hf_pn_io_number_of_submodules = -1; +static int hf_pn_io_submodule_ident_number = -1; +static int hf_pn_io_submodule_properties = -1; +static int hf_pn_io_submodule_properties_type = -1; +static int hf_pn_io_submodule_properties_shared_input = -1; +static int hf_pn_io_submodule_properties_reduce_input_submodule_data_length = -1; +static int hf_pn_io_submodule_properties_reduce_output_submodule_data_length = -1; +static int hf_pn_io_submodule_properties_discard_ioxs = -1; +static int hf_pn_io_submodule_properties_reserved = -1; + +static int hf_pn_io_submodule_state = -1; +static int hf_pn_io_submodule_state_format_indicator = -1; +static int hf_pn_io_submodule_state_add_info = -1; +static int hf_pn_io_submodule_state_advice = -1; +static int hf_pn_io_submodule_state_maintenance_required = -1; +static int hf_pn_io_submodule_state_maintenance_demanded = -1; +static int hf_pn_io_submodule_state_fault = -1; +static int hf_pn_io_submodule_state_ar_info = -1; +static int hf_pn_io_submodule_state_ident_info = -1; +static int hf_pn_io_submodule_state_detail = -1; + +static int hf_pn_io_data_description_tree = -1; +static int hf_pn_io_data_description = -1; +static int hf_pn_io_submodule_data_length = -1; +static int hf_pn_io_length_iocs = -1; +static int hf_pn_io_length_iops = -1; + +static int hf_pn_io_iocs = -1; +static int hf_pn_io_iops = -1; +static int hf_pn_io_ioxs_extension = -1; +static int hf_pn_io_ioxs_res14 = -1; +static int hf_pn_io_ioxs_instance = -1; +static int hf_pn_io_ioxs_datastate = -1; + +static int hf_pn_io_address_resolution_properties = -1; +static int hf_pn_io_mci_timeout_factor = -1; +static int hf_pn_io_provider_station_name = -1; + +static int hf_pn_io_user_structure_identifier = -1; +static int hf_pn_io_user_structure_identifier_manf = -1; + +static int hf_pn_io_channel_number = -1; +static int hf_pn_io_channel_properties = -1; +static int hf_pn_io_channel_properties_type = -1; +static int hf_pn_io_channel_properties_accumulative = -1; +static int hf_pn_io_channel_properties_maintenance = -1; + + +static int hf_pn_io_NumberOfSubframeBlocks = -1; +static int hf_pn_io_channel_properties_specifier = -1; +static int hf_pn_io_channel_properties_direction = -1; + +static int hf_pn_io_channel_error_type = -1; +static int hf_pn_io_ext_channel_error_type0 = -1; +static int hf_pn_io_ext_channel_error_type0x8000 = -1; +static int hf_pn_io_ext_channel_error_type0x8001 = -1; +static int hf_pn_io_ext_channel_error_type0x8002 = -1; +static int hf_pn_io_ext_channel_error_type0x8003 = -1; +static int hf_pn_io_ext_channel_error_type0x8004 = -1; +static int hf_pn_io_ext_channel_error_type0x8005 = -1; +static int hf_pn_io_ext_channel_error_type0x8007 = -1; +static int hf_pn_io_ext_channel_error_type0x8008 = -1; +static int hf_pn_io_ext_channel_error_type0x800A = -1; +static int hf_pn_io_ext_channel_error_type0x800B = -1; +static int hf_pn_io_ext_channel_error_type0x800C = -1; +static int hf_pn_io_ext_channel_error_type0x8010 = -1; + +static int hf_pn_io_ext_channel_error_type = -1; + +static int hf_pn_io_ext_channel_add_value = -1; +static int hf_pn_io_qualified_channel_qualifier = -1; + +static int hf_pn_io_ptcp_subdomain_id = -1; +static int hf_pn_io_ir_data_id = -1; +static int hf_pn_io_max_bridge_delay = -1; +static int hf_pn_io_number_of_ports = -1; +static int hf_pn_io_max_port_tx_delay = -1; +static int hf_pn_io_max_port_rx_delay = -1; + +static int hf_pn_io_max_line_rx_delay = -1; +static int hf_pn_io_yellowtime = -1; +static int hf_pn_io_reserved_interval_begin = -1; +static int hf_pn_io_reserved_interval_end = -1; +static int hf_pn_io_pllwindow = -1; +static int hf_pn_io_sync_send_factor = -1; +static int hf_pn_io_sync_properties = -1; +static int hf_pn_io_sync_frame_address = -1; +static int hf_pn_io_ptcp_timeout_factor = -1; +static int hf_pn_io_ptcp_takeover_timeout_factor = -1; +static int hf_pn_io_ptcp_master_startup_time = -1; +static int hf_pn_io_ptcp_master_priority_1 = -1; +static int hf_pn_io_ptcp_master_priority_2 = -1; +static int hf_pn_io_ptcp_length_subdomain_name = -1; +static int hf_pn_io_ptcp_subdomain_name = -1; + +static int hf_pn_io_MultipleInterfaceMode_NameOfDevice = -1; +static int hf_pn_io_MultipleInterfaceMode_reserved_1 = -1; +static int hf_pn_io_MultipleInterfaceMode_reserved_2 = -1; +/* added Portstatistics */ +static int hf_pn_io_pdportstatistic_counter_status = -1; +static int hf_pn_io_pdportstatistic_counter_status_ifInOctets = -1; +static int hf_pn_io_pdportstatistic_counter_status_ifOutOctets = -1; +static int hf_pn_io_pdportstatistic_counter_status_ifInDiscards = -1; +static int hf_pn_io_pdportstatistic_counter_status_ifOutDiscards = -1; +static int hf_pn_io_pdportstatistic_counter_status_ifInErrors = -1; +static int hf_pn_io_pdportstatistic_counter_status_ifOutErrors = -1; +static int hf_pn_io_pdportstatistic_counter_status_reserved = -1; +static int hf_pn_io_pdportstatistic_ifInOctets = -1; +static int hf_pn_io_pdportstatistic_ifOutOctets = -1; +static int hf_pn_io_pdportstatistic_ifInDiscards = -1; +static int hf_pn_io_pdportstatistic_ifOutDiscards = -1; +static int hf_pn_io_pdportstatistic_ifInErrors = -1; +static int hf_pn_io_pdportstatistic_ifOutErrors = -1; +/* end of port statistics */ + +static int hf_pn_io_domain_boundary = -1; +static int hf_pn_io_domain_boundary_ingress = -1; +static int hf_pn_io_domain_boundary_egress = -1; +static int hf_pn_io_multicast_boundary = -1; +static int hf_pn_io_adjust_properties = -1; +static int hf_pn_io_PreambleLength = -1; +static int hf_pn_io_mau_type = -1; +static int hf_pn_io_mau_type_mode = -1; +static int hf_pn_io_port_state = -1; +static int hf_pn_io_link_state_port = -1; +static int hf_pn_io_link_state_link = -1; +static int hf_pn_io_line_delay = -1; +static int hf_pn_io_line_delay_value = -1; +static int hf_pn_io_cable_delay_value = -1; +static int hf_pn_io_line_delay_format_indicator = -1; +static int hf_pn_io_number_of_peers = -1; +static int hf_pn_io_length_peer_port_id = -1; +static int hf_pn_io_peer_port_id = -1; +static int hf_pn_io_length_peer_chassis_id = -1; +static int hf_pn_io_peer_chassis_id = -1; +static int hf_pn_io_neighbor = -1; +static int hf_pn_io_length_peer_port_name = -1; +static int hf_pn_io_peer_port_name = -1; +static int hf_pn_io_length_peer_station_name = -1; +static int hf_pn_io_peer_station_name = -1; +static int hf_pn_io_length_own_port_id = -1; +static int hf_pn_io_own_port_id = -1; +static int hf_pn_io_peer_macadd = -1; +static int hf_pn_io_media_type = -1; +static int hf_pn_io_macadd = -1; +static int hf_pn_io_length_own_chassis_id = -1; +static int hf_pn_io_own_chassis_id = -1; +static int hf_pn_io_rtclass3_port_status = -1; + +static int hf_pn_io_ethertype = -1; +static int hf_pn_io_rx_port = -1; +static int hf_pn_io_frame_details = -1; +static int hf_pn_io_frame_details_sync_frame = -1; +static int hf_pn_io_frame_details_meaning_frame_send_offset = -1; +static int hf_pn_io_frame_details_reserved = -1; +static int hf_pn_io_nr_of_tx_port_groups = -1; +static int hf_pn_io_TxPortGroupProperties = -1; +static int hf_pn_io_TxPortGroupProperties_bit0 = -1; +static int hf_pn_io_TxPortGroupProperties_bit1 = -1; +static int hf_pn_io_TxPortGroupProperties_bit2 = -1; +static int hf_pn_io_TxPortGroupProperties_bit3 = -1; +static int hf_pn_io_TxPortGroupProperties_bit4 = -1; +static int hf_pn_io_TxPortGroupProperties_bit5 = -1; +static int hf_pn_io_TxPortGroupProperties_bit6 = -1; +static int hf_pn_io_TxPortGroupProperties_bit7 = -1; + +static int hf_pn_io_start_of_red_frame_id = -1; +static int hf_pn_io_end_of_red_frame_id = -1; +static int hf_pn_io_ir_begin_end_port = -1; +static int hf_pn_io_number_of_assignments = -1; +static int hf_pn_io_number_of_phases = -1; +static int hf_pn_io_red_orange_period_begin_tx = -1; +static int hf_pn_io_orange_period_begin_tx = -1; +static int hf_pn_io_green_period_begin_tx = -1; +static int hf_pn_io_red_orange_period_begin_rx = -1; +static int hf_pn_io_orange_period_begin_rx = -1; +static int hf_pn_io_green_period_begin_rx = -1; +/* static int hf_pn_io_tx_phase_assignment = -1; */ +static int hf_pn_ir_tx_phase_assignment = -1; +static int hf_pn_ir_rx_phase_assignment = -1; +static int hf_pn_io_tx_phase_assignment_begin_value = -1; +static int hf_pn_io_tx_phase_assignment_orange_begin = -1; +static int hf_pn_io_tx_phase_assignment_end_reserved = -1; +static int hf_pn_io_tx_phase_assignment_reserved = -1; +/* static int hf_pn_io_rx_phase_assignment = -1; */ + +static int hf_pn_io_slot = -1; +static int hf_pn_io_subslot = -1; +static int hf_pn_io_number_of_slots = -1; +static int hf_pn_io_number_of_subslots = -1; + +/* static int hf_pn_io_maintenance_required_drop_budget = -1; */ +/* static int hf_pn_io_maintenance_demanded_drop_budget = -1; */ +/* static int hf_pn_io_error_drop_budget = -1; */ + +static int hf_pn_io_tsn_number_of_queues = -1; +static int hf_pn_io_tsn_max_supported_record_size = -1; +static int hf_pn_io_tsn_transfer_time_tx = -1; +static int hf_pn_io_tsn_transfer_time_rx = -1; +static int hf_pn_io_tsn_port_capabilities_time_aware = -1; +static int hf_pn_io_tsn_port_capabilities_preemption = -1; +static int hf_pn_io_tsn_port_capabilities_queue_masking = -1; +static int hf_pn_io_tsn_port_capabilities_reserved = -1; +static int hf_pn_io_tsn_forwarding_group = -1; +static int hf_pn_io_tsn_forwarding_group_ingress = -1; +static int hf_pn_io_tsn_forwarding_group_egress = -1; +static int hf_pn_io_tsn_stream_class = -1; +static int hf_pn_io_tsn_dependent_forwarding_delay = -1; +static int hf_pn_io_tsn_independent_forwarding_delay = -1; +static int hf_pn_io_tsn_forwarding_delay_block_number_of_entries = -1; +static int hf_pn_io_tsn_expected_neighbor_block_number_of_entries = -1; +static int hf_pn_io_tsn_port_id_block_number_of_entries = -1; + +static int hf_pn_io_tsn_nme_parameter_uuid = -1; +static int hf_pn_io_tsn_domain_vid_config = -1; +static int hf_pn_io_tsn_domain_vid_config_stream_high_vid = -1; +static int hf_pn_io_tsn_domain_vid_config_stream_high_red_vid = -1; +static int hf_pn_io_tsn_domain_vid_config_stream_low_vid = -1; +static int hf_pn_io_tsn_domain_vid_config_stream_low_red_vid = -1; +static int hf_pn_io_tsn_domain_vid_config_non_stream_vid = -1; +static int hf_pn_io_tsn_domain_vid_config_non_stream_vid_B = -1; +static int hf_pn_io_tsn_domain_vid_config_non_stream_vid_C = -1; +static int hf_pn_io_tsn_domain_vid_config_non_stream_vid_D = -1; +static int hf_pn_io_tsn_domain_vid_config_reserved = -1; +static int hf_pn_io_number_of_tsn_time_data_block_entries = -1; +static int hf_pn_io_number_of_tsn_domain_queue_rate_limiter_entries = -1; +static int hf_pn_io_number_of_tsn_domain_port_ingress_rate_limiter_entries = -1; +static int hf_pn_io_number_of_tsn_domain_port_config_entries = -1; + +static int hf_pn_io_tsn_domain_port_config = -1; +static int hf_pn_io_tsn_domain_port_config_preemption_enabled = -1; +static int hf_pn_io_tsn_domain_port_config_boundary_port_config = -1; +static int hf_pn_io_tsn_domain_port_config_reserved = -1; + +static int hf_pn_io_tsn_domain_port_ingress_rate_limiter = -1; +static int hf_pn_io_tsn_domain_port_ingress_rate_limiter_cir = -1; +static int hf_pn_io_tsn_domain_port_ingress_rate_limiter_cbs = -1; +static int hf_pn_io_tsn_domain_port_ingress_rate_limiter_envelope = -1; +static int hf_pn_io_tsn_domain_port_ingress_rate_limiter_rank = -1; + +static int hf_pn_io_tsn_domain_queue_rate_limiter = -1; +static int hf_pn_io_tsn_domain_queue_rate_limiter_cir = -1; +static int hf_pn_io_tsn_domain_queue_rate_limiter_cbs = -1; +static int hf_pn_io_tsn_domain_queue_rate_limiter_envelope = -1; +static int hf_pn_io_tsn_domain_queue_rate_limiter_rank = -1; +static int hf_pn_io_tsn_domain_queue_rate_limiter_queue_id = -1; +static int hf_pn_io_tsn_domain_queue_rate_limiter_reserved = -1; + +static int hf_pn_io_number_of_tsn_domain_queue_config_entries = -1; +static int hf_pn_io_tsn_domain_queue_config = -1; +static int hf_pn_io_tsn_domain_queue_config_queue_id = -1; +static int hf_pn_io_tsn_domain_queue_config_tci_pcp = -1; +static int hf_pn_io_tsn_domain_queue_config_shaper = -1; +static int hf_pn_io_tsn_domain_queue_config_preemption_mode = -1; +static int hf_pn_io_tsn_domain_queue_config_unmask_time_offset = -1; +static int hf_pn_io_tsn_domain_queue_config_mask_time_offset = -1; + +static int hf_pn_io_network_deadline = -1; +static int hf_pn_io_time_domain_number = -1; +static int hf_pn_io_time_pll_window = -1; +static int hf_pn_io_message_interval_factor = -1; +static int hf_pn_io_message_timeout_factor = -1; +static int hf_pn_io_time_sync_properties = -1; +static int hf_pn_io_time_sync_properties_role = -1; +static int hf_pn_io_time_sync_properties_reserved = -1; +static int hf_pn_io_time_domain_uuid = -1; +static int hf_pn_io_time_domain_name_length = -1; +static int hf_pn_io_time_domain_name = -1; +static int hf_pn_io_tsn_nme_name_uuid = -1; +static int hf_pn_io_tsn_nme_name_length = -1; +static int hf_pn_io_tsn_nme_name = -1; +static int hf_pn_io_tsn_domain_uuid = -1; +static int hf_pn_io_tsn_domain_name_length = -1; +static int hf_pn_io_tsn_domain_name = -1; + +static int hf_pn_io_tsn_fdb_command = -1; +static int hf_pn_io_tsn_dst_add = -1; + +static int hf_pn_io_number_of_tsn_domain_sync_tree_entries = -1; +static int hf_pn_io_tsn_domain_sync_port_role = -1; +static int hf_pn_io_tsn_domain_port_id = -1; + +static int hf_pn_io_maintenance_required_power_budget = -1; +static int hf_pn_io_maintenance_demanded_power_budget = -1; +static int hf_pn_io_error_power_budget = -1; + +static int hf_pn_io_fiber_optic_type = -1; +static int hf_pn_io_fiber_optic_cable_type = -1; + +static int hf_pn_io_controller_appl_cycle_factor = -1; +static int hf_pn_io_time_data_cycle = -1; +static int hf_pn_io_time_io_input = -1; +static int hf_pn_io_time_io_output = -1; +static int hf_pn_io_time_io_input_valid = -1; +static int hf_pn_io_time_io_output_valid = -1; + +static int hf_pn_io_maintenance_status = -1; +static int hf_pn_io_maintenance_status_required = -1; +static int hf_pn_io_maintenance_status_demanded = -1; + +static int hf_pn_io_vendor_id_high = -1; +static int hf_pn_io_vendor_id_low = -1; +static int hf_pn_io_vendor_block_type = -1; +static int hf_pn_io_order_id = -1; +static int hf_pn_io_im_serial_number = -1; +static int hf_pn_io_im_hardware_revision = -1; +static int hf_pn_io_im_revision_prefix = -1; +static int hf_pn_io_im_sw_revision_functional_enhancement = -1; +static int hf_pn_io_im_revision_bugfix = -1; +static int hf_pn_io_im_sw_revision_internal_change = -1; +static int hf_pn_io_im_revision_counter = -1; +static int hf_pn_io_im_profile_id = -1; +static int hf_pn_io_im_profile_specific_type = -1; +static int hf_pn_io_im_version_major = -1; +static int hf_pn_io_im_version_minor = -1; +static int hf_pn_io_im_supported = -1; +static int hf_pn_io_im_numberofentries = -1; +static int hf_pn_io_im_annotation = -1; +static int hf_pn_io_im_order_id = -1; + +static int hf_pn_io_number_of_ars = -1; + +static int hf_pn_io_cycle_counter = -1; +static int hf_pn_io_data_status = -1; +static int hf_pn_io_data_status_res67 = -1; +static int hf_pn_io_data_status_ok = -1; +static int hf_pn_io_data_status_operate = -1; +static int hf_pn_io_data_status_res3 = -1; +static int hf_pn_io_data_status_valid = -1; +static int hf_pn_io_data_status_res1 = -1; +static int hf_pn_io_data_status_primary = -1; +static int hf_pn_io_transfer_status = -1; + +static int hf_pn_io_actual_local_time_stamp = -1; +static int hf_pn_io_number_of_log_entries = -1; +static int hf_pn_io_local_time_stamp = -1; +static int hf_pn_io_entry_detail = -1; + +static int hf_pn_io_ip_address = -1; +static int hf_pn_io_subnetmask = -1; +static int hf_pn_io_standard_gateway = -1; + +static int hf_pn_io_mrp_domain_uuid = -1; +static int hf_pn_io_mrp_role = -1; +static int hf_pn_io_mrp_length_domain_name = -1; +static int hf_pn_io_mrp_domain_name = -1; +static int hf_pn_io_mrp_instances = -1; +static int hf_pn_io_mrp_instance = -1; + +static int hf_pn_io_mrp_prio = -1; +static int hf_pn_io_mrp_topchgt = -1; +static int hf_pn_io_mrp_topnrmax = -1; +static int hf_pn_io_mrp_tstshortt = -1; +static int hf_pn_io_mrp_tstdefaultt = -1; +static int hf_pn_io_mrp_tstnrmax = -1; +static int hf_pn_io_mrp_check = -1; +static int hf_pn_io_mrp_check_mrm = -1; +static int hf_pn_io_mrp_check_mrpdomain = -1; +static int hf_pn_io_mrp_check_reserved_1 = -1; +static int hf_pn_io_mrp_check_reserved_2 = -1; + +static int hf_pn_io_mrp_rtmode = -1; +static int hf_pn_io_mrp_rtmode_rtclass12 = -1; +static int hf_pn_io_mrp_rtmode_rtclass3 = -1; +static int hf_pn_io_mrp_rtmode_reserved1 = -1; +static int hf_pn_io_mrp_rtmode_reserved2 = -1; + +static int hf_pn_io_mrp_lnkdownt = -1; +static int hf_pn_io_mrp_lnkupt = -1; +static int hf_pn_io_mrp_lnknrmax = -1; +static int hf_pn_io_mrp_version = -1; + +static int hf_pn_io_substitute_active_flag = -1; +static int hf_pn_io_length_data = -1; + +static int hf_pn_io_mrp_ring_state = -1; +static int hf_pn_io_mrp_rt_state = -1; + +static int hf_pn_io_im_tag_function = -1; +static int hf_pn_io_im_tag_location = -1; +static int hf_pn_io_im_date = -1; +static int hf_pn_io_im_descriptor = -1; + +static int hf_pn_io_fs_hello_mode = -1; +static int hf_pn_io_fs_hello_interval = -1; +static int hf_pn_io_fs_hello_retry = -1; +static int hf_pn_io_fs_hello_delay = -1; + +static int hf_pn_io_fs_parameter_mode = -1; +static int hf_pn_io_fs_parameter_uuid = -1; + + +static int hf_pn_io_check_sync_mode = -1; +static int hf_pn_io_check_sync_mode_reserved = -1; +static int hf_pn_io_check_sync_mode_sync_master = -1; +static int hf_pn_io_check_sync_mode_cable_delay = -1; + +/* PROFIsafe fParameters */ +static int hf_pn_io_ps_f_prm_flag1 = -1; +static int hf_pn_io_ps_f_prm_flag1_chck_seq = -1; +static int hf_pn_io_ps_f_prm_flag1_chck_ipar = -1; +static int hf_pn_io_ps_f_prm_flag1_sil = -1; +static int hf_pn_io_ps_f_prm_flag1_crc_len = -1; +static int hf_pn_io_ps_f_prm_flag1_crc_seed = -1; +static int hf_pn_io_ps_f_prm_flag1_reserved = -1; +static int hf_pn_io_ps_f_prm_flag2 = -1; +static int hf_pn_io_ps_f_wd_time = -1; +static int hf_pn_io_ps_f_ipar_crc = -1; +static int hf_pn_io_ps_f_par_crc = -1; +static int hf_pn_io_ps_f_src_adr = -1; +static int hf_pn_io_ps_f_dest_adr = -1; +static int hf_pn_io_ps_f_prm_flag2_reserved = -1; +static int hf_pn_io_ps_f_prm_flag2_f_block_id = -1; +static int hf_pn_io_ps_f_prm_flag2_f_par_version = -1; + +static int hf_pn_io_profidrive_request_reference = -1; +static int hf_pn_io_profidrive_request_id = -1; +static int hf_pn_io_profidrive_do_id = -1; +static int hf_pn_io_profidrive_no_of_parameters = -1; +static int hf_pn_io_profidrive_response_id = -1; +static int hf_pn_io_profidrive_param_attribute = -1; +static int hf_pn_io_profidrive_param_no_of_elems = -1; +static int hf_pn_io_profidrive_param_number = -1; +static int hf_pn_io_profidrive_param_subindex = -1; +static int hf_pn_io_profidrive_param_format = -1; +static int hf_pn_io_profidrive_param_no_of_values = -1; +static int hf_pn_io_profidrive_param_value_byte = -1; +static int hf_pn_io_profidrive_param_value_word = -1; +static int hf_pn_io_profidrive_param_value_dword = -1; +static int hf_pn_io_profidrive_param_value_float = -1; +static int hf_pn_io_profidrive_param_value_string = -1; +static int hf_pn_io_profidrive_param_value_error = -1; +static int hf_pn_io_profidrive_param_value_error_sub = -1; + + +/* Sequence of Events - Reporting System Alarm/Event Information */ +static int hf_pn_io_rs_alarm_info_reserved_0_7 = -1; +static int hf_pn_io_rs_alarm_info_reserved_8_15 = -1; +static int hf_pn_io_rs_alarm_info = -1; +static int hf_pn_io_rs_event_info = -1; +static int hf_pn_io_rs_event_block = -1; +static int hf_pn_io_rs_adjust_block = -1; +static int hf_pn_io_rs_event_data_extension = -1; +static int hf_pn_io_number_of_rs_event_info = -1; +static int hf_pn_io_rs_block_type = -1; +static int hf_pn_io_rs_block_length = -1; +static int hf_pn_io_rs_specifier = -1; +static int hf_pn_io_rs_specifier_sequence = -1; +static int hf_pn_io_rs_specifier_reserved = -1; +static int hf_pn_io_rs_specifier_specifier = -1; +static int hf_pn_io_rs_time_stamp = -1; +static int hf_pn_io_rs_time_stamp_status = -1; +static int hf_pn_io_rs_time_stamp_value = -1; +static int hf_pn_io_rs_minus_error = -1; +static int hf_pn_io_rs_plus_error = -1; +static int hf_pn_io_rs_extension_block_type = -1; +static int hf_pn_io_rs_extension_block_length = -1; +static int hf_pn_io_rs_reason_code = -1; +static int hf_pn_io_rs_reason_code_reason = -1; +static int hf_pn_io_rs_reason_code_detail = -1; +static int hf_pn_io_rs_domain_identification = -1; +static int hf_pn_io_rs_master_identification = -1; +static int hf_pn_io_soe_digital_input_current_value = -1; +static int hf_pn_io_soe_digital_input_current_value_value = -1; +static int hf_pn_io_soe_digital_input_current_value_reserved = -1; +static int hf_pn_io_am_device_identification = -1; +static int hf_pn_io_am_device_identification_device_sub_id = -1; +static int hf_pn_io_am_device_identification_device_id = -1; +static int hf_pn_io_am_device_identification_vendor_id = -1; +static int hf_pn_io_am_device_identification_organization = -1; +static int hf_pn_io_rs_adjust_info = -1; +static int hf_pn_io_soe_max_scan_delay = -1; +static int hf_pn_io_soe_adjust_specifier = -1; +static int hf_pn_io_soe_adjust_specifier_reserved = -1; +static int hf_pn_io_soe_adjust_specifier_incident = -1; +static int hf_pn_io_rs_properties = -1; +static int hf_pn_io_rs_properties_alarm_transport = -1; +static int hf_pn_io_rs_properties_reserved1 = -1; +static int hf_pn_io_rs_properties_reserved2 = -1; + +static int hf_pn_io_asset_management_info = -1; +static int hf_pn_io_number_of_asset_management_info = -1; +static int hf_pn_io_im_uniqueidentifier = -1; +static int hf_pn_io_am_location_structure = -1; +static int hf_pn_io_am_location_level_0 = -1; +static int hf_pn_io_am_location_level_1 = -1; +static int hf_pn_io_am_location_level_2 = -1; +static int hf_pn_io_am_location_level_3 = -1; +static int hf_pn_io_am_location_level_4 = -1; +static int hf_pn_io_am_location_level_5 = -1; +static int hf_pn_io_am_location_level_6 = -1; +static int hf_pn_io_am_location_level_7 = -1; +static int hf_pn_io_am_location_level_8 = -1; +static int hf_pn_io_am_location_level_9 = -1; +static int hf_pn_io_am_location_level_10 = -1; +static int hf_pn_io_am_location_level_11 = -1; +static int hf_pn_io_am_location = -1; +static int hf_pn_io_am_location_reserved1 = -1; +static int hf_pn_io_am_location_reserved2 = -1; +static int hf_pn_io_am_location_reserved3 = -1; +static int hf_pn_io_am_location_reserved4 = -1; +static int hf_pn_io_am_location_beginslotnum = -1; +static int hf_pn_io_am_location_beginsubslotnum = -1; +static int hf_pn_io_am_location_endslotnum = -1; +static int hf_pn_io_am_location_endsubslotnum = -1; +static int hf_pn_io_am_software_revision = -1; +static int hf_pn_io_am_hardware_revision = -1; +static int hf_pn_io_am_type_identification = -1; +static int hf_pn_io_am_reserved = -1; + +static int hf_pn_io_dcp_boundary_value = -1; +static int hf_pn_io_dcp_boundary_value_bit0 = -1; +static int hf_pn_io_dcp_boundary_value_bit1 = -1; +static int hf_pn_io_dcp_boundary_value_otherbits = -1; + +static int hf_pn_io_peer_to_peer_boundary_value = -1; +static int hf_pn_io_peer_to_peer_boundary_value_bit0 = -1; +static int hf_pn_io_peer_to_peer_boundary_value_bit1 = -1; +static int hf_pn_io_peer_to_peer_boundary_value_bit2 = -1; +static int hf_pn_io_peer_to_peer_boundary_value_otherbits = -1; + +static int hf_pn_io_mau_type_extension = -1; + +static int hf_pn_io_pe_operational_mode = -1; + +static int hf_pn_io_snmp_community_name_length = -1; +static int hf_pn_io_snmp_community_name = -1; +static int hf_pn_io_snmp_read_community_name = -1; +static int hf_pn_io_snmp_write_community_name = -1; + +static int hf_pn_io_snmp_control = -1; + +/* static int hf_pn_io_packedframe_SFCRC = -1; */ +static gint ett_pn_io = -1; +static gint ett_pn_io_block = -1; +static gint ett_pn_io_block_header = -1; +static gint ett_pn_io_rtc = -1; +static gint ett_pn_io_rta = -1; +static gint ett_pn_io_pdu_type = -1; +static gint ett_pn_io_add_flags = -1; +static gint ett_pn_io_control_command = -1; +static gint ett_pn_io_ioxs = -1; +static gint ett_pn_io_api = -1; +static gint ett_pn_io_data_description = -1; +static gint ett_pn_io_module = -1; +static gint ett_pn_io_submodule = -1; +static gint ett_pn_io_io_data_object = -1; +static gint ett_pn_io_io_cs = -1; +static gint ett_pn_io_ar_properties = -1; +static gint ett_pn_io_iocr_properties = -1; +static gint ett_pn_io_submodule_properties = -1; +static gint ett_pn_io_alarmcr_properties = -1; +static gint ett_pn_io_submodule_state = -1; +static gint ett_pn_io_channel_properties = -1; +static gint ett_pn_io_slot = -1; +static gint ett_pn_io_subslot = -1; +static gint ett_pn_io_maintenance_status = -1; +static gint ett_pn_io_data_status = -1; +static gint ett_pn_io_iocr = -1; +static gint ett_pn_io_mrp_rtmode = -1; +static gint ett_pn_io_control_block_properties = -1; +static gint ett_pn_io_check_sync_mode = -1; +static gint ett_pn_io_ir_frame_data = -1; +static gint ett_pn_FrameDataProperties = -1; +static gint ett_pn_io_ar_info = -1; +static gint ett_pn_io_ar_data = -1; +static gint ett_pn_io_ir_begin_end_port = -1; +static gint ett_pn_io_ir_tx_phase = -1; +static gint ett_pn_io_ir_rx_phase = -1; +static gint ett_pn_io_subframe_data =-1; +static gint ett_pn_io_SFIOCRProperties = -1; +static gint ett_pn_io_frame_defails = -1; +static gint ett_pn_io_profisafe_f_parameter = -1; +static gint ett_pn_io_profisafe_f_parameter_prm_flag1 = -1; +static gint ett_pn_io_profisafe_f_parameter_prm_flag2 = -1; +static gint ett_pn_io_profidrive_parameter_request = -1; +static gint ett_pn_io_profidrive_parameter_response = -1; +static gint ett_pn_io_profidrive_parameter_address = -1; +static gint ett_pn_io_profidrive_parameter_value = -1; +static gint ett_pn_io_rs_alarm_info = -1; +static gint ett_pn_io_rs_event_info = -1; +static gint ett_pn_io_rs_event_block = -1; +static gint ett_pn_io_rs_adjust_block = -1; +static gint ett_pn_io_rs_event_data_extension = -1; +static gint ett_pn_io_rs_specifier = -1; +static gint ett_pn_io_rs_time_stamp = -1; +static gint ett_pn_io_am_device_identification = -1; +static gint ett_pn_io_rs_reason_code = -1; +static gint ett_pn_io_soe_digital_input_current_value = -1; +static gint ett_pn_io_rs_adjust_info = -1; +static gint ett_pn_io_soe_adjust_specifier = -1; +static gint ett_pn_io_sr_properties = -1; +static gint ett_pn_io_line_delay = -1; +static gint ett_pn_io_counter_status = -1; +static gint ett_pn_io_neighbor = -1; + +static gint ett_pn_io_GroupProperties = -1; + +static gint ett_pn_io_asset_management_info = -1; +static gint ett_pn_io_asset_management_block = -1; +static gint ett_pn_io_am_location = -1; + +static gint ett_pn_io_dcp_boundary = -1; +static gint ett_pn_io_peer_to_peer_boundary = -1; + +static gint ett_pn_io_mau_type_extension = -1; + +static gint ett_pn_io_pe_operational_mode = -1; + +static gint ett_pn_io_tsn_domain_port_config = -1; +static gint ett_pn_io_tsn_domain_port_ingress_rate_limiter = -1; +static gint ett_pn_io_tsn_domain_queue_rate_limiter = -1; +static gint ett_pn_io_tsn_domain_vid_config = -1; +static gint ett_pn_io_tsn_domain_queue_config = -1; +static gint ett_pn_io_time_sync_properties = -1; +static gint ett_pn_io_tsn_domain_port_id = -1; + +static gint ett_pn_io_snmp_command_name = -1; + + +#define PD_SUB_FRAME_BLOCK_FIOCR_PROPERTIES_LENGTH 4 +#define PD_SUB_FRAME_BLOCK_FRAME_ID_LENGTH 2 +#define PD_SUB_FRAME_BLOCK_SUB_FRAME_DATA_LENGTH 4 + +static expert_field ei_pn_io_block_version = EI_INIT; +static expert_field ei_pn_io_block_length = EI_INIT; +static expert_field ei_pn_io_unsupported = EI_INIT; +static expert_field ei_pn_io_localalarmref = EI_INIT; +static expert_field ei_pn_io_mrp_instances = EI_INIT; +static expert_field ei_pn_io_ar_info_not_found = EI_INIT; +static expert_field ei_pn_io_iocr_type = EI_INIT; +static expert_field ei_pn_io_frame_id = EI_INIT; +static expert_field ei_pn_io_nr_of_tx_port_groups = EI_INIT; +static expert_field ei_pn_io_max_recursion_depth_reached = EI_INIT; + +static e_guid_t uuid_pn_io_device = { 0xDEA00001, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } }; +static guint16 ver_pn_io_device = 1; + +static e_guid_t uuid_pn_io_controller = { 0xDEA00002, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } }; +static guint16 ver_pn_io_controller = 1; + +static e_guid_t uuid_pn_io_supervisor = { 0xDEA00003, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } }; +static guint16 ver_pn_io_supervisor = 1; + +static e_guid_t uuid_pn_io_parameterserver = { 0xDEA00004, 0x6C97, 0x11D1, { 0x82, 0x71, 0x00, 0xA0, 0x24, 0x42, 0xDF, 0x7D } }; +static guint16 ver_pn_io_parameterserver = 1; + +/* According to specification: + * Value(UUID): 00000000-0000-0000-0000-000000000000 + * Meaning: Reserved + * Use: The value NIL indicates the usage of the implicit AR. + */ +static e_guid_t uuid_pn_io_implicitar = { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; +static guint16 ver_pn_io_implicitar = 1; + +/* PNIO Preference Variables */ +gboolean pnio_ps_selection = TRUE; +static const char *pnio_ps_networkpath = ""; + +wmem_list_t *aruuid_frame_setup_list = NULL; +static wmem_map_t *pnio_time_aware_frame_map = NULL; + + +/* Allow heuristic dissection */ +static heur_dissector_list_t heur_pn_subdissector_list; + +static const value_string pn_io_block_type[] = { + { 0x0000, "Reserved" }, + { 0x0001, "Alarm Notification High"}, + { 0x8001, "Alarm Ack High"}, + { 0x0002, "Alarm Notification Low"}, + { 0x8002, "Alarm Ack Low"}, + { 0x0008, "IODWriteReqHeader"}, + { 0x8008, "IODWriteResHeader"}, + { 0x0009, "IODReadReqHeader"}, + { 0x8009, "IODReadResHeader"}, + { 0x0010, "DiagnosisData"}, + { 0x0011, "Reserved"}, + { 0x0012, "ExpectedIdentificationData"}, + { 0x0013, "RealIdentificationData"}, + { 0x0014, "SubstituteValue"}, + { 0x0015, "RecordInputDataObjectElement"}, + { 0x0016, "RecordOutputDataObjectElement"}, + { 0x0017, "reserved"}, + { 0x0018, "ARData"}, + { 0x0019, "LogData"}, + { 0x001A, "APIData"}, + { 0x001b, "SRLData"}, + { 0x0020, "I&M0"}, + { 0x0021, "I&M1"}, + { 0x0022, "I&M2"}, + { 0x0023, "I&M3"}, + { 0x0024, "I&M4"}, + { 0x0025, "I&M5"}, + { 0x0026, "I&M6"}, + { 0x0027, "I&M7"}, + { 0x0028, "I&M8"}, + { 0x0029, "I&M9"}, + { 0x002A, "I&M10"}, + { 0x002B, "I&M11"}, + { 0x002C, "I&M12"}, + { 0x002D, "I&M13"}, + { 0x002E, "I&M14"}, + { 0x002F, "I&M15"}, + { 0x0030, "I&M0FilterDataSubmodul"}, + { 0x0031, "I&M0FilterDataModul"}, + { 0x0032, "I&M0FilterDataDevice"}, + { 0x0033, "Reserved" }, + { 0x0034, "I&M5Data"}, + { 0x0035, "AssetManagementData"}, + { 0x0036, "AM_FullInformation"}, + { 0x0037, "AM_HardwareOnlyInformation"}, + { 0x0038, "AM_FirmwareOnlyInformation" }, + { 0x8001, "Alarm Ack High"}, + { 0x8002, "Alarm Ack Low"}, + { 0x0101, "ARBlockReq"}, + { 0x8101, "ARBlockRes"}, + { 0x0102, "IOCRBlockReq"}, + { 0x8102, "IOCRBlockRes"}, + { 0x0103, "AlarmCRBlockReq"}, + { 0x8103, "AlarmCRBlockRes"}, + { 0x0104, "ExpectedSubmoduleBlockReq"}, + { 0x8104, "ModuleDiffBlock"}, + { 0x0105, "PrmServerBlockReq"}, + { 0x8105, "PrmServerBlockRes"}, + { 0x0106, "MCRBlockReq"}, + { 0x8106, "ARServerBlockRes"}, + { 0x0107, "SubFrameBlock"}, + { 0x8107, "ARRPCBlockRes"}, + { 0x0108, "ARVendorBlockReq"}, + { 0x8108, "ARVendorBlockRes"}, + { 0x0109, "IRInfoBlock"}, + { 0x010A, "SRInfoBlock"}, + { 0x010B, "ARFSUBlock"}, + { 0x010C, "RSInfoBlock"}, + { 0x0110, "IODControlReq Prm End.req"}, + { 0x8110, "IODControlRes Prm End.rsp"}, + { 0x0111, "IODControlReq Plug Prm End.req"}, + { 0x8111, "IODControlRes Plug Prm End.rsp"}, + { 0x0112, "IOXBlockReq Application Ready.req"}, + { 0x8112, "IOXBlockRes Application Ready.rsp"}, + { 0x0113, "IOXBlockReq Plug Application Ready.req"}, + { 0x8113, "IOXBlockRes Plug Application Ready.rsp"}, + { 0x0114, "IODReleaseReq"}, + { 0x8114, "IODReleaseRes"}, + { 0x0115, "ARRPCServerBlockReq"}, + { 0x8115, "ARRPCServerBlockRes"}, + { 0x0116, "IOXControlReq Ready for Companion.req"}, + { 0x8116, "IOXControlRes Ready for Companion.rsp"}, + { 0x0117, "IOXControlReq Ready for RT_CLASS_3.req"}, + { 0x8117, "IOXControlRes Ready for RT_CLASS_3.rsp"}, + { 0x0118, "PrmBeginReq"}, + { 0x8118, "PrmBeginRes"}, + { 0x0119, "SubmoduleListBlock"}, + + { 0x0200, "PDPortDataCheck"}, + { 0x0201, "PDevData"}, + { 0x0202, "PDPortDataAdjust"}, + { 0x0203, "PDSyncData"}, + { 0x0204, "IsochronousModeData"}, + { 0x0205, "PDIRData"}, + { 0x0206, "PDIRGlobalData"}, + { 0x0207, "PDIRFrameData"}, + { 0x0208, "PDIRBeginEndData"}, + { 0x0209, "AdjustDomainBoundary"}, + { 0x020A, "CheckPeers"}, + { 0x020B, "CheckLineDelay"}, + { 0x020C, "Checking MAUType"}, + { 0x020E, "Adjusting MAUType"}, + { 0x020F, "PDPortDataReal"}, + { 0x0210, "AdjustMulticastBoundary"}, + { 0x0211, "PDInterfaceMrpDataAdjust"}, + { 0x0212, "PDInterfaceMrpDataReal"}, + { 0x0213, "PDInterfaceMrpDataCheck"}, + { 0x0214, "PDPortMrpDataAdjust"}, + { 0x0215, "PDPortMrpDataReal"}, + { 0x0216, "Media redundancy manager parameters"}, + { 0x0217, "Media redundancy client parameters"}, + { 0x0218, "Media redundancy RT mode for manager"}, + { 0x0219, "Media redundancy ring state data"}, + { 0x021A, "Media redundancy RT ring state data"}, + { 0x021B, "Adjust LinkState"}, + { 0x021C, "Checking LinkState"}, + { 0x021D, "Media redundancy RT mode for clients"}, + { 0x021E, "CheckSyncDifference"}, + { 0x021F, "CheckMAUTypeDifference"}, + { 0x0220, "PDPortFODataReal"}, + { 0x0221, "Reading real fiber optic manufacturerspecific data"}, + { 0x0222, "PDPortFODataAdjust"}, + { 0x0223, "PDPortFODataCheck"}, + { 0x0224, "Adjust PeerToPeerBoundary"}, + { 0x0225, "Adjust DCPBoundary"}, + { 0x0226, "Adjust PreambleLength"}, + { 0x0227, "CheckMAUType-Extension"}, + { 0x0228, "Reading real fiber optic diagnosis data"}, + { 0x0229, "AdjustMAUType-Extension"}, + { 0x022A, "PDIRSubframeData"}, + { 0x022B, "SubframeBlock"}, + { 0x022C, "PDPortDataRealExtended"}, + { 0x022D, "PDTimeData"}, + { 0x022E, "PDPortSFPDataCheck"}, + { 0x0230, "PDNCDataCheck"}, + { 0x0231, "MrpInstanceDataAdjust"}, + { 0x0232, "MrpInstanceDataReal"}, + { 0x0233, "MrpInstanceDataCheck"}, + { 0x0234, "PDPortMrpIcDataAdjust"}, + { 0x0235, "PDPortMrpIcDataCheck"}, + { 0x0236, "PDPortMrpIcDataReal"}, + { 0x0240, "PDInterfaceDataReal"}, + { 0x0241, "PDRsiInstances"}, + { 0x0250, "PDInterfaceAdjust"}, + { 0x0251, "PDPortStatistic"}, + { 0x0260, "OwnPort"}, + { 0x0261, "Neighbors"}, + { 0x0270, "TSNNetworkControlDataReal"}, + { 0x0271, "TSNNetworkControlDataAdjust"}, + { 0x0272, "TSNDomainPortConfigBlock"}, + { 0x0273, "TSNDomainQueueConfigBlock"}, + { 0x0274, "TSNTimeDataBlock"}, + { 0x0275, "TSNStreamPathData"}, + { 0x0276, "TSNSyncTreeData"}, + { 0x0277, "TSNUploadNetworkAttributes"}, + { 0x0278, "ForwardingDelayBlock"}, + { 0x0279, "TSNExpectedNetworkAttributes"}, + { 0x027A, "TSNStreamPathDataReal"}, + { 0x027B, "TSNDomainPortIngressRateLimiterBlock"}, + { 0x027C, "TSNDomainQueueRateLimiterBlock"}, + { 0x027D, "TSNPortIDBlock"}, + { 0x027E, "TSNExpectedNeighborBlock" }, + { 0x0300, "CIMSNMPAdjust"}, + { 0x0400, "MultipleBlockHeader"}, + { 0x0401, "COContainerContent"}, + { 0x0500, "RecordDataReadQuery"}, + { 0x0501, "TSNAddStreamReq"}, + { 0x0502, "TSNAddStreamRsp"}, + { 0x0503, "TSNRemoveStreamReq"}, + { 0x0504, "TSNRemoveStreamRsp"}, + { 0x0505, "TSNRenewStreamReq"}, + { 0x0506, "TSNRenewStreamRsp"}, + { 0x0600, "FSHelloBlock"}, + { 0x0601, "FSParameterBlock"}, + { 0x0602, "FastStartUpBlock"}, + { 0x0608, "PDInterfaceFSUDataAdjust"}, + { 0x0609, "ARFSUDataAdjust"}, + { 0x0700, "AutoConfiguration"}, + { 0x0701, "AutoConfiguration Communication"}, + { 0x0702, "AutoConfiguration Configuration"}, + { 0x0703, "AutoConfiguration Isochronous"}, + { 0x0810, "PE_EntityFilterData"}, + { 0x0811, "PE_EntityStatusData"}, + { 0x0900, "RS_AdjustObserver" }, + { 0x0901, "RS_GetEvent" }, + { 0x0902, "RS_AckEvent" }, + { 0x0A00, "Upload BLOB Query" }, + { 0x0A01, "Upload BLOB" }, + { 0xB050, "Ext-PLL Control / RTC+RTA SyncID 0 (EDD)" }, + { 0xB051, "Ext-PLL Control / RTA SyncID 1 (GSY)" }, + + { 0xB060, "EDD Trace Unit (EDD)" }, + { 0xB061, "EDD Trace Unit (EDD)" }, + + { 0xB070, "OHA Info (OHA)" }, + + { 0x0F00, "MaintenanceItem"}, + { 0x0F01, "Upload selected Records within Upload&RetrievalItem"}, + { 0x0F02, "iParameterItem"}, + { 0x0F03, "Retrieve selected Records within Upload&RetrievalItem"}, + { 0x0F04, "Retrieve all Records within Upload&RetrievalItem"}, + { 0x0F05, "Signal a PE_OperationalMode change within PE_EnergySavingStatus" }, + { 0, NULL } +}; + +static const value_string pn_io_alarm_type[] = { + { 0x0000, "Reserved" }, + { 0x0001, "Diagnosis" }, + { 0x0002, "Process" }, + { 0x0003, "Pull" }, + { 0x0004, "Plug" }, + { 0x0005, "Status" }, + { 0x0006, "Update" }, + { 0x0007, "Redundancy" }, + { 0x0008, "Controlled by supervisor" }, + { 0x0009, "Released" }, + { 0x000A, "Plug wrong submodule" }, + { 0x000B, "Return of submodule" }, + { 0x000C, "Diagnosis disappears" }, + { 0x000D, "Multicast communication mismatch notification" }, + { 0x000E, "Port data change notification" }, + { 0x000F, "Sync data changed notification" }, + { 0x0010, "Isochronous mode problem notification" }, + { 0x0011, "Network component problem notification" }, + { 0x0012, "Time data changed notification" }, + { 0x0013, "Dynamic Frame Packing problem notification" }, + /*0x0014 - 0x001D reserved */ + { 0x001E, "Upload and retrieval notification" }, + { 0x001F, "Pull module" }, + /*0x0020 - 0x007F manufacturer specific */ + /*0x0080 - 0x00FF reserved for profiles */ + /*0x0100 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_pdu_type[] = { + { 0x01, "Data-RTA-PDU" }, + { 0x02, "NACK-RTA-PDU" }, + { 0x03, "ACK-RTA-PDU" }, + { 0x04, "ERR-RTA-PDU" }, + { 0, NULL } +}; + +static const value_string hf_pn_io_frame_data_properties_forwardingMode[] = { + { 0x00, "absolute mode" }, + { 0x01, "relative mode"}, + { 0, NULL } +}; +static const value_string hf_pn_io_frame_data_properties_FFMulticastMACAdd[] = { + { 0x00, "Use interface MAC destination unicast address" }, + { 0x01, "Use RT_CLASS_3 destination multicast address"}, + { 0x02, "Use FastForwardingMulticastMACAdd"}, + { 0x03, "reserved"}, + { 0, NULL }}; + +static const value_string hf_pn_io_frame_data_properties_FragMode[] = { + { 0x00, "No fragmentation" }, + { 0x01, "Fragmentation enabled maximum size for static fragmentation 128 bytes"}, + { 0x02, "Fragmentation enabled maximum size for static fragmentation 256 bytes"}, + { 0x03, "reserved"}, + { 0, NULL }}; + +static const value_string pn_io_SFIOCRProperties_DFPType_vals[] = { + { 0x00, "DFP_INBOUND" }, + { 0x01, "DFP_OUTBOUND" }, + { 0, NULL } +}; + +static const value_string pn_io_DFPRedundantPathLayout_decode[] = { + { 0x00, "The Frame for the redundant path contains the ordering shown by SubframeData" }, + { 0x01, "The Frame for the redundant path contains the inverse ordering shown by SubframeData" }, + { 0, NULL } +}; + +static const value_string pn_io_SFCRC16_Decode[] = { + { 0x00, "SFCRC16 and SFCycleCounter shall be created or set to zero by the sender and not checked by the receiver" }, + { 0x01, "SFCRC16 and SFCycleCounter shall be created by the sender and checked by the receiver." }, + { 0, NULL } +}; + +static const value_string pn_io_txgroup_state[] = { + { 0x00, "Transmission off" }, + { 0x01, "Transmission on " }, + { 0, NULL } +}; + +static const value_string pn_io_ioxs[] = { + { 0x00 /* 0*/, "detected by subslot" }, + { 0x01 /* 1*/, "detected by slot" }, + { 0x02 /* 2*/, "detected by IO device" }, + { 0x03 /* 3*/, "detected by IO controller" }, + { 0, NULL } +}; + + +static const value_string pn_io_ar_type[] = { + { 0x0000, "reserved" }, + { 0x0001, "IO Controller AR"}, + { 0x0002, "reserved" }, + { 0x0003, "IOCARCIR" }, + { 0x0004, "reserved" }, + { 0x0005, "reserved" }, + { 0x0006, "IO Supervisor AR / DeviceAccess AR" }, + /*0x0007 - 0x000F reserved */ + { 0x0010, "IO Controller AR (RT_CLASS_3)" }, + /*0x0011 - 0x001F reserved */ + { 0x0020, "IO Controller AR (sysred/CiR)" }, + /*0x0007 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_iocr_type[] = { + { 0x0000, "reserved" }, + { 0x0001, "Input CR" }, + { 0x0002, "Output CR" }, + { 0x0003, "Multicast Provider CR" }, + { 0x0004, "Multicast Consumer CR" }, + /*0x0005 - 0xFFFF reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_data_description[] = { + { 0x0000, "reserved" }, + { 0x0001, "Input" }, + { 0x0002, "Output" }, + { 0x0003, "reserved" }, + /*0x0004 - 0xFFFF reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_module_state[] = { + { 0x0000, "no module" }, + { 0x0001, "wrong module" }, + { 0x0002, "proper module" }, + { 0x0003, "substitute" }, + /*0x0004 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_arproperties_state[] = { + { 0x00000000, "Reserved" }, + { 0x00000001, "Active" }, + { 0x00000002, "reserved" }, + { 0x00000003, "reserved" }, + { 0x00000004, "reserved" }, + { 0x00000005, "reserved" }, + { 0x00000006, "reserved" }, + { 0x00000007, "reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_arproperties_supervisor_takeover_allowed[] = { + { 0x00000000, "not allowed" }, + { 0x00000001, "allowed" }, + { 0, NULL } +}; + +static const value_string pn_io_arproperties_parameterization_server[] = { + { 0x00000000, "External PrmServer" }, + { 0x00000001, "CM Initiator" }, + { 0, NULL } +}; +/* BIT 8 */ +static const value_string pn_io_arproperties_DeviceAccess[] = { + { 0x00000000, "Only the submodules from the ExpectedSubmoduleBlock are accessible" }, + { 0x00000001, "Submodule access is controlled by IO device application" }, + { 0, NULL } +}; + +/* Bit 9 - 10 */ +static const value_string pn_io_arproperties_companion_ar[] = { + { 0x00000000, "Single AR" }, + { 0x00000001, "First AR of a companion pair and a companion AR shall follow" }, + { 0x00000002, "Companion AR" }, + { 0x00000003, "Reserved" }, + { 0, NULL } +}; +/* REMOVED with 2.3 +static const value_string pn_io_arproperties_data_rate[] = { + { 0x00000000, "at least 100 MB/s or more" }, + { 0x00000001, "100 MB/s" }, + { 0x00000002, "1 GB/s" }, + { 0x00000003, "10 GB/s" }, + { 0, NULL } +}; +*/ + +/* BIT 11 */ +static const value_string pn_io_arproperties_acknowldege_companion_ar[] = { + { 0x00000000, "No companion AR or no acknowledge for the companion AR required" }, + { 0x00000001, "Companion AR with acknowledge" }, + { 0, NULL } +}; + +/* Bit 28 */ +static const value_string pn_io_arproperties_time_aware_system[] = { + { 0x00000000, "NonTimeAware" }, + { 0x00000001, "TimeAware" }, + { 0, NULL } +}; + +/* bit 29 for legacy startup mode*/ +static const value_string pn_io_arproperties_combined_object_container_with_legacy_startupmode[] = { + { 0x00000000, "CombinedObjectContainer not used" }, + { 0x00000001, "Reserved" }, + { 0, NULL } +}; + +/* bit 29 for advanced statup mode*/ +static const value_string pn_io_arproperties_combined_object_container_with_advanced_startupmode[] = { + { 0x00000000, "CombinedObjectContainer not used" }, + { 0x00000001, "Usage of CombinedObjectContainer required" }, + { 0, NULL } +}; + +/* bit 30 */ +static const value_string pn_io_arpropertiesStartupMode[] = { + { 0x00000000, "Legacy" }, + { 0x00000001, "Advanced" }, + { 0, NULL } +}; + +/* bit 31 */ +static const value_string pn_io_arproperties_pull_module_alarm_allowed[] = { + { 0x00000000, "AlarmType(=Pull) shall signal pulling of submodule and module" }, + { 0x00000001, "AlarmType(=Pull) shall signal pulling of submodule" }, + { 0, NULL } +}; + +static const value_string pn_io_RedundancyInfo[] = { + { 0x00000000, "Reserved" }, + { 0x00000001, "The delivering node is the left or below one" }, + { 0x00000002, "The delivering node is the right or above one" }, + { 0x00000003, "Reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_iocr_properties_rtclass[] = { + { 0x00000000, "reserved" }, + { 0x00000001, "RT_CLASS_1" }, + { 0x00000002, "RT_CLASS_2" }, + { 0x00000003, "RT_CLASS_3" }, + { 0x00000004, "RT_CLASS_UDP" }, + /*0x00000005 - 0x00000007 reserved */ + { 0, NULL } +}; + +static const value_string pn_io_MultipleInterfaceMode_NameOfDevice[] = { + { 0x00000000, "PortID of LLDP contains name of port (Default)" }, + { 0x00000001, "PortID of LLDP contains name of port and NameOfStation" }, + { 0, NULL } +}; + +static const true_false_string tfs_pn_io_sr_properties_BackupAR_with_SRProperties_Mode_0 = + { "The device shall deliver valid input data", "The IO controller shall not evaluate the input data." }; + +static const true_false_string tfs_pn_io_sr_properties_BackupAR_with_SRProperties_Mode_1 = + { "The device shall deliver valid input data", "The IO device shall mark the data as invalid using APDU_Status.DataStatus.DataValid == Invalid." }; + +static const true_false_string tfs_pn_io_sr_properties_Mode = + { "Default The IO device shall use APDU_Status.DataStatus.DataValid == Invalid if input data is request as not valid.", + "The IO controller do not support APDU_Status.DataStatus.DataValid == Invalid if input data is request as not valid." }; + +static const true_false_string tfs_pn_io_sr_properties_Reserved1 = + { "Legacy mode", "Shall be set to zero for this standard." }; + +static const value_string pn_io_iocr_properties_media_redundancy[] = { + { 0x00000000, "No media redundant frame transfer" }, + { 0x00000001, "Media redundant frame transfer" }, + { 0, NULL } +}; + + +static const value_string pn_io_submodule_properties_type[] = { + { 0x0000, "no input and no output data" }, + { 0x0001, "input data" }, + { 0x0002, "output data" }, + { 0x0003, "input and output data" }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_properties_shared_input[] = { + { 0x0000, "IO controller" }, + { 0x0001, "IO controller shared" }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_properties_reduce_input_submodule_data_length[] = { + { 0x0000, "Expected" }, + { 0x0001, "Zero" }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_properties_reduce_output_submodule_data_length[] = { + { 0x0000, "Expected" }, + { 0x0001, "Zero" }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_properties_discard_ioxs[] = { + { 0x0000, "Expected" }, + { 0x0001, "Zero" }, + { 0, NULL } +}; + +static const value_string pn_io_alarmcr_properties_priority[] = { + { 0x0000, "user priority (default)" }, + { 0x0001, "use only low priority" }, + { 0, NULL } +}; + +static const value_string pn_io_alarmcr_properties_transport[] = { + { 0x0000, "RTA_CLASS_1" }, + { 0x0001, "RTA_CLASS_UDP" }, + { 0, NULL } +}; + + +static const value_string pn_io_submodule_state_format_indicator[] = { + { 0x0000, "Coding uses Detail" }, + { 0x0001, "Coding uses .IdentInfo, ..." }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_state_add_info[] = { + { 0x0000, "None" }, + { 0x0001, "Takeover not allowed" }, + /*0x0002 - 0x0007 reserved */ + { 0, NULL } +}; + +static const value_string pn_io_submodule_state_advice[] = { + { 0x0000, "No Advice available" }, + { 0x0001, "Advice available" }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_state_maintenance_required[] = { + { 0x0000, "No MaintenanceRequired available" }, + { 0x0001, "MaintenanceRequired available" }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_state_maintenance_demanded[] = { + { 0x0000, "No MaintenanceDemanded available" }, + { 0x0001, "MaintenanceDemanded available" }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_state_fault[] = { + { 0x0000, "No Fault available" }, + { 0x0001, "Fault available" }, + { 0, NULL } +}; + +static const value_string pn_io_submodule_state_ar_info[] = { + { 0x0000, "Own" }, + { 0x0001, "ApplicationReadyPending (ARP)" }, + { 0x0002, "Superordinated Locked (SO)" }, + { 0x0003, "Locked By IO Controller (IOC)" }, + { 0x0004, "Locked By IO Supervisor (IOS)" }, + /*0x0005 - 0x000F reserved */ + { 0, NULL } +}; + +static const value_string pn_io_submodule_state_ident_info[] = { + { 0x0000, "OK" }, + { 0x0001, "Substitute (SU)" }, + { 0x0002, "Wrong (WR)" }, + { 0x0003, "NoSubmodule (NO)" }, + /*0x0004 - 0x000F reserved */ + { 0, NULL } +}; + +static const value_string pn_io_submodule_state_detail[] = { + { 0x0000, "no submodule" }, + { 0x0001, "wrong submodule" }, + { 0x0002, "locked by IO controller" }, + { 0x0003, "reserved" }, + { 0x0004, "application ready pending" }, + { 0x0005, "reserved" }, + { 0x0006, "reserved" }, + { 0x0007, "Substitute" }, + /*0x0008 - 0x7FFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_substitutionmode[] = { + { 0x0000, "ZERO" }, + { 0x0001, "Last value" }, + { 0x0002, "Replacement value" }, + /*0x0003 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_index[] = { + /*0x0008 - 0x7FFF user specific */ + + /* PROFISafe */ + { 0x0100, "PROFISafe" }, + + /* subslot specific */ + { 0x8000, "ExpectedIdentificationData for one subslot" }, + { 0x8001, "RealIdentificationData for one subslot" }, + /*0x8002 - 0x8009 reserved */ + { 0x800A, "Diagnosis in channel coding for one subslot" }, + { 0x800B, "Diagnosis in all codings for one subslot" }, + { 0x800C, "Diagnosis, Maintenance, Qualified and Status for one subslot" }, + /*0x800D - 0x800F reserved */ + { 0x8010, "Maintenance required in channel coding for one subslot" }, + { 0x8011, "Maintenance demanded in channel coding for one subslot" }, + { 0x8012, "Maintenance required in all codings for one subslot" }, + { 0x8013, "Maintenance demanded in all codings for one subslot" }, + /*0x8014 - 0x801D reserved */ + { 0x801E, "SubstituteValues for one subslot" }, + /*0x801F reserved */ + { 0x8020, "PDIRSubframeData for one subslot" }, + /*0x8021 - 0x8026 reserved */ + { 0x8027, "PDPortDataRealExtended for one subslot" }, + { 0x8028, "RecordInputDataObjectElement for one subslot" }, + { 0x8029, "RecordOutputDataObjectElement for one subslot" }, + { 0x802A, "PDPortDataReal for one subslot" }, + { 0x802B, "PDPortDataCheck for one subslot" }, + { 0x802C, "PDIRData for one subslot" }, + { 0x802D, "PDSyncData for one subslot with SyncID value 0" }, + /*0x802E reserved */ + { 0x802F, "PDPortDataAdjust for one subslot" }, + { 0x8030, "IsochronousModeData for one subslot" }, + { 0x8031, "PDTimeData for one subslot" }, + /*0x8032 - 0x804F reserved */ + { 0x8050, "PDInterfaceMrpDataReal for one subslot" }, + { 0x8051, "PDInterfaceMrpDataCheck for one subslot" }, + { 0x8052, "PDInterfaceMrpDataAdjust for one subslot" }, + { 0x8053, "PDPortMrpDataAdjust for one subslot" }, + { 0x8054, "PDPortMrpDataReal for one subslot" }, + { 0x8055, "PDPortMrpIcDataAdjust for one subslot" }, + { 0x8056, "PDPortMrpIcDataCheck for one subslot" }, + { 0x8057, "PDPortMrpIcDataReal for one subslot" }, + /*0x8058 - 0x805F reserved */ + { 0x8060, "PDPortFODataReal for one subslot" }, + { 0x8061, "PDPortFODataCheck for one subslot" }, + { 0x8062, "PDPortFODataAdjust for one subslot" }, + { 0x8063, "PDPortSFPDataCheck for one subslot" }, + /*0x8064 - 0x806F reserved */ + { 0x8070, "PDNCDataCheck for one subslot" }, + { 0x8071, "PDInterfaceAdjust for one subslot" }, + { 0x8072, "PDPortStatistic for one subslot" }, + /*0x8071 - 0x807F reserved */ + { 0x8080, "PDInterfaceDataReal" }, + /*0x8081 - 0x808F reserved */ + { 0x8090, "PDInterfaceFSUDataAdjust" }, + /*0x8091 - 0x809F reserved */ + { 0x80A0, "Profiles covering energy saving - Record_0" }, + /*0x80A1 - 0x80AE reserved */ + { 0x80AF, "PE_EntityStatusData for one subslot" }, + { 0x80B0, "CombinedObjectContainer" }, + /*0x80B1 - 0x80CE reserved */ + { 0x80CF, "RS_AdjustObserver" }, + { 0x80D0, "Profiles covering condition monitoring - Record_0" }, + /*0x80D1 - 0x80DF reserved */ + { 0x80F0, "TSNNetworkControlDataReal" }, + { 0x80F1, "TSNStreamPathData" }, + { 0x80F2, "TSNSyncTreeData" }, + { 0x80F3, "TSNUploadNetworkAttributes" }, + { 0x80F4, "TSNExpectedNetworkAttributes" }, + { 0x80F5, "TSNNetworkControlDataAdjust" }, + { 0x80F6, "TSNStreamPathDataReal for stream class High" }, + { 0x80F7, "TSNStreamPathDataReal for stream class High Redundant" }, + { 0x80F8, "TSNStreamPathDataReal for stream class Low" }, + { 0x80F9, "TSNStreamPathDataReal for stream class Low Redundant" }, + /*0x80FA - 0x80FF reserved for CIM data */ + /*0x8100 - 0x81FF reserved */ + { 0x8200, "CIMSNMPAdjust" }, + /*0x8201 - 0xAFEF reserved */ + { 0xAFF0, "I&M0" }, + { 0xAFF1, "I&M1" }, + { 0xAFF2, "I&M2" }, + { 0xAFF3, "I&M3" }, + { 0xAFF4, "I&M4" }, + { 0xAFF5, "I&M5" }, + { 0xAFF6, "I&M6" }, + { 0xAFF7, "I&M7" }, + { 0xAFF8, "I&M8" }, + { 0xAFF9, "I&M9" }, + { 0xAFFA, "I&M10" }, + { 0xAFFB, "I&M11" }, + { 0xAFFC, "I&M12" }, + { 0xAFFD, "I&M13" }, + { 0xAFFE, "I&M14" }, + { 0xAFFF, "I&M15" }, + /*0xB000 - 0xB02D reserved for profiles */ + { 0xB000, "Sync-Log / RTA SyncID 0 (GSY)" }, + { 0xB001, "Sync-Log / RTA SyncID 1 (GSY)" }, + { 0xB002, "reserved for profiles" }, + { 0xB003, "reserved for profiles" }, + { 0xB004, "reserved for profiles" }, + { 0xB005, "reserved for profiles" }, + { 0xB006, "reserved for profiles" }, + { 0xB007, "reserved for profiles" }, + { 0xB008, "reserved for profiles" }, + { 0xB009, "reserved for profiles" }, + { 0xB00A, "reserved for profiles" }, + { 0xB00B, "reserved for profiles" }, + { 0xB00C, "reserved for profiles" }, + { 0xB00D, "reserved for profiles" }, + { 0xB00E, "reserved for profiles" }, + { 0xB00F, "reserved for profiles" }, + { 0xB010, "reserved for profiles" }, + { 0xB011, "reserved for profiles" }, + { 0xB012, "reserved for profiles" }, + { 0xB013, "reserved for profiles" }, + { 0xB014, "reserved for profiles" }, + { 0xB015, "reserved for profiles" }, + { 0xB016, "reserved for profiles" }, + { 0xB017, "reserved for profiles" }, + { 0xB018, "reserved for profiles" }, + { 0xB019, "reserved for profiles" }, + { 0xB01A, "reserved for profiles" }, + { 0xB01B, "reserved for profiles" }, + { 0xB01C, "reserved for profiles" }, + { 0xB01D, "reserved for profiles" }, + { 0xB01E, "reserved for profiles" }, + { 0xB01F, "reserved for profiles" }, + { 0xB020, "reserved for profiles" }, + { 0xB021, "reserved for profiles" }, + { 0xB022, "reserved for profiles" }, + { 0xB023, "reserved for profiles" }, + { 0xB024, "reserved for profiles" }, + { 0xB025, "reserved for profiles" }, + { 0xB026, "reserved for profiles" }, + { 0xB027, "reserved for profiles" }, + { 0xB028, "reserved for profiles" }, + { 0xB029, "reserved for profiles" }, + { 0xB02A, "reserved for profiles" }, + { 0xB02B, "reserved for profiles" }, + { 0xB02C, "reserved for profiles" }, + { 0xB02D, "reserved for profiles" }, + /* PROFIDrive */ + { 0xB02E, "PROFIDrive Parameter Access - Local"}, + { 0xB02F, "PROFIDrive Parameter Access - Global"}, + + /*0xB030 - 0xBFFF reserved for profiles */ + { 0xB050, "Ext-PLL Control / RTC+RTA SyncID 0 (EDD)" }, + { 0xB051, "Ext-PLL Control / RTA SyncID 1 (GSY)" }, + + { 0xB060, "EDD Trace Unit (EDD" }, + { 0xB061, "EDD Trace Unit (EDD" }, + + { 0xB070, "OHA Info (OHA)" }, + + + /* slot specific */ + { 0xC000, "ExpectedIdentificationData for one slot" }, + { 0xC001, "RealIdentificationData for one slot" }, + /*0xC002 - 0xC009 reserved */ + { 0xC00A, "Diagnosis in channel coding for one slot" }, + { 0xC00B, "Diagnosis in all codings for one slot" }, + { 0xC00C, "Diagnosis, Maintenance, Qualified and Status for one slot" }, + /*0xC00D - 0xC00F reserved */ + { 0xC010, "Maintenance required in channel coding for one slot" }, + { 0xC011, "Maintenance demanded in channel coding for one slot" }, + { 0xC012, "Maintenance required in all codings for one slot" }, + { 0xC013, "Maintenance demanded in all codings for one slot" }, + /*0xC014 - 0xCFFF reserved */ + /*0xD000 - 0xDFFF reserved for profiles */ + + /* AR specific */ + { 0xE000, "ExpectedIdentificationData for one AR" }, + { 0xE001, "RealIdentificationData for one AR" }, + { 0xE002, "ModuleDiffBlock for one AR" }, + /*0xE003 - 0xE009 reserved */ + { 0xE00A, "Diagnosis in channel coding for one AR" }, + { 0xE00B, "Diagnosis in all codings for one AR" }, + { 0xE00C, "Diagnosis, Maintenance, Qualified and Status for one AR" }, + /*0xE00D - 0xE00F reserved */ + { 0xE010, "Maintenance required in channel coding for one AR" }, + { 0xE011, "Maintenance demanded in channel coding for one AR" }, + { 0xE012, "Maintenance required in all codings for one AR" }, + { 0xE013, "Maintenance demanded in all codings for one AR" }, + /*0xE014 - 0xE02F reserved */ + { 0xE030, "PE_EntityFilterData for one AR" }, + { 0xE031, "PE_EntityStatusData for one AR" }, + /*0xE032 - 0xE03F reserved */ + { 0xE040, "MultipleWrite" }, + { 0xE041, "ApplicationReadyBlock" }, + /*0xE042 - 0xE04F reserved */ + { 0xE050, "ARFSUDataAdjust data for one AR" }, + /*0xE051 - 0xE05F reserved */ + { 0xE060, "RS_GetEvent (using RecordDataRead service)" }, + { 0xE061, "RS_AckEvent (using RecordDataWrite service)" }, + /*0xEC00 - 0xEFFF reserved */ + + /* API specific */ + { 0xF000, "RealIdentificationData for one API" }, + /*0xF001 - 0xF009 reserved */ + { 0xF00A, "Diagnosis in channel coding for one API" }, + { 0xF00B, "Diagnosis in all codings for one API" }, + { 0xF00C, "Diagnosis, Maintenance, Qualified and Status for one API" }, + /*0xF00D - 0xF00F reserved */ + { 0xF010, "Maintenance required in channel coding for one API" }, + { 0xF011, "Maintenance demanded in channel coding for one API" }, + { 0xF012, "Maintenance required in all codings for one API" }, + { 0xF013, "Maintenance demanded in all codings for one API" }, + /*0xF014 - 0xF01F reserved */ + { 0xF020, "ARData for one API" }, + /*0xF021 - 0xF3FF reserved */ + /*0xF400 - 0xF7FF reserved */ + + /* device specific */ + /*0xF800 - 0xF80B reserved */ + { 0xF80C, "Diagnosis, Maintenance, Qualified and Status for one device" }, + /*0xF80D - 0xF81F reserved */ + { 0xF820, "ARData" }, + { 0xF821, "APIData" }, + /*0xF822 - 0xF82F reserved */ + { 0xF830, "LogData" }, + { 0xF831, "PDevData" }, + /*0xF832 - 0xF83F reserved */ + { 0xF840, "I&M0FilterData" }, + { 0xF841, "PDRealData" }, + { 0xF842, "PDExpectedData" }, + /*0xF843 - 0xF84F reserved */ + { 0xF850, "AutoConfiguration" }, + { 0xF860, "GSD upload using UploadBLOBQuery and UploadBLOB" }, + { 0xF870, "PE_EntityFilterData" }, + { 0xF871, "PE_EntityStatusData" }, + { 0xF880, "AssetManagementData - contains all or first chunk of complete assets" }, + { 0xF881, "AssetManagementData - second chunk" }, + { 0xF882, "AssetManagementData - third chunk" }, + { 0xF883, "AssetManagementData - fourth chunk" }, + { 0xF884, "AssetManagementData - fifth chunk" }, + { 0xF885, "AssetManagementData - sixth chunk" }, + { 0xF886, "AssetManagementData - seventh chunk" }, + { 0xF887, "AssetManagementData - eighth chunk" }, + { 0xF888, "AssetManagementData - ninth chunk" }, + { 0xF889, "AssetManagementData - tenth chunk" }, + { 0xF8F0, "Stream Add using TSNAddStreamReq and TSNAddStreamRsp" }, + { 0xF8F1, "PDRsiInstances" }, + { 0xF8F2, "Stream Remove using TSNRemoveStreamReq and TSNRemoveStreamRsp" }, + { 0xF8F3, "Stream Renew using TSNRenewStreamReq and TSNRenewStreamRsp" }, + { 0xFBFF, "Trigger index for RPC connection monitoring" }, + /*0xFC00 - 0xFFFF reserved for profiles */ + { 0, NULL } +}; + +static const value_string pn_io_user_structure_identifier[] = { + /*0x0000 - 0x7FFF manufacturer specific */ + { 0x8000, "ChannelDiagnosis" }, + { 0x8001, "Multiple" }, + { 0x8002, "ExtChannelDiagnosis" }, + { 0x8003, "QualifiedChannelDiagnosis" }, + /*0x8004 - 0x80FF reserved */ + { 0x8100, "Maintenance" }, + /*0x8101 - 0x8FFF reserved except 8200, 8201, 8300, 8301, 8302, 8303, 8310, 8320 */ + { 0x8200, "Upload&Retrieval" }, + { 0x8201, "iParameter" }, + { 0x8300, "Reporting system RS_LowWatermark" }, + { 0x8301, "Reporting system RS_Timeout" }, + { 0x8302, "Reporting system RS_Overflow" }, + { 0x8303, "Reporting system RS_Event" }, + { 0x8310, "PE_EnergySavingStatus" }, + { 0x8320, "Channel related Process Alarm reasons" }, + /*0x9000 - 0x9FFF reserved for profiles */ + /*0xA000 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_channel_error_type[] = { + { 0x0000, "reserved" }, + { 0x0001, "short circuit" }, + { 0x0002, "Undervoltage" }, + { 0x0003, "Overvoltage" }, + { 0x0004, "Overload" }, + { 0x0005, "Overtemperature" }, + { 0x0006, "Wire break" }, + { 0x0007, "Upper limit value exceeded" }, + { 0x0008, "Lower limit value exceeded" }, + { 0x0009, "Error" }, + { 0x000A, "Simulation active" }, + /*0x000B - 0x000E reserved */ + { 0x000F, "Parameter missing" }, + { 0x0010, "Parameterization fault" }, + { 0x0011, "Power supply fault" }, + { 0x0012, "Fuse blown / open" }, + { 0x0013, "Manufacturer specific" }, + { 0x0014, "Ground fault" }, + { 0x0015, "Reference point lost" }, + { 0x0016, "Process event lost / sampling error" }, + { 0x0017, "Threshold warning" }, + { 0x0018, "Output disabled" }, + { 0x0019, "FunctionalSafety event" }, + { 0x001A, "External fault" }, + /*0x001B - 0x001F manufacturer specific */ + { 0x001F, "Temporary fault" }, + /*0x0020 - 0x00FF reserved for common profiles */ + { 0x0040, "Mismatch of safety destination address" }, + { 0x0041, "Safety destination address not valid" }, + { 0x0042, "Safety source address not valid" }, + { 0x0043, "Safety watchdog time value is 0ms" }, + { 0x0044, "Parameter F_SIL exceeds SIL of specific application" }, + { 0x0045, "Parameter F_CRC_Length does not match generated values" }, + { 0x0046, "Version of F-Parameter set incorrect" }, + { 0x0047, "Data inconsistent in received F-Parameter block (CRC1 error)" }, + { 0x0048, "Device specific or unspecific diagnosis information, see manual" }, + { 0x0049, "Save iParameter watchdog time exceeded" }, + { 0x004A, "Restore iParameter watchdog time exceeded" }, + { 0x004B, "Inconsistent iParameters (iParCRC error)" }, + { 0x004C, "F_Block_ID not supported" }, + { 0x004D, "Transmission error: data inconsistent (CRC2 error)" }, + { 0x004E, "Transmission error: timeout" }, + { 0x004F, "Acknowledge needed to enable the channel(s)" }, + /*0x0100 - 0x7FFF manufacturer specific */ + { 0x8000, "Data transmission impossible" }, + { 0x8001, "Remote mismatch" }, + { 0x8002, "Media redundancy mismatch - Ring" }, + { 0x8003, "Sync mismatch" }, + { 0x8004, "IsochronousMode mismatch" }, + { 0x8005, "Multicast CR mismatch" }, + { 0x8006, "reserved" }, + { 0x8007, "Fiber optic mismatch" }, + { 0x8008, "Network component function mismatch" }, + { 0x8009, "Time mismatch" }, + /* added values for IEC version 2.3: */ + { 0x800A, "Dynamic frame packing function mismatch" }, + { 0x800B, "Media redundancy with planned duplication mismatch"}, + { 0x800C, "System redundancy mismatch"}, + { 0x800D, "Multiple interface mismatch"}, + { 0x8010, "Power failure over Single Pair Ethernet"}, + /* ends */ + /*0x800D - 0x8FFF reserved */ + /*0x9000 - 0x9FFF reserved for profile */ + /*0x9000 - 0x902F NE107 common (PA Profile 4.02) */ + { 0x9000, "Sensor element exciter faulty" }, + { 0x9001, "Error in evaluation electronics" }, + { 0x9002, "Error in internal energy supply" }, + { 0x9003, "Error in sensor element" }, + { 0x9004, "Error in actuator element" }, + { 0x9005, "Faulty installation e.g. dead space" }, + { 0x9006, "Parameter setting error" }, + { 0x9008, "Overloading" }, + { 0x9009, "Wrong polarity of aux power" }, + { 0x900A, "Maximum line length exceeded" }, + { 0x900B, "Corrosion/abrasion by medium" }, + { 0x900C, "Fouling on sensor element" }, + { 0x900D, "Auxil medium missing or insufficient" }, + { 0x900E, "Wear reserve used up (operation)" }, + { 0x900F, "Wear reserve used up (wear)" }, + { 0x9010, "Error in peripherals" }, + { 0x9011, "Electromag interference too high" }, + { 0x9012, "Temperature of medium too high" }, + { 0x9013, "Ambient temperature too high" }, + { 0x9014, "Vibration/Impact load too high" }, + { 0x9015, "Auxiliary power range off-spec" }, + { 0x9016, "Auxiliary medium missing" }, + { 0x9017, "Excessive temperature shock" }, + { 0x9018, "Deviation from measurement" }, + { 0x9019, "Humidity in electronics area" }, + { 0x901A, "Medium in electronics area" }, + { 0x901B, "Mechanical damage" }, + { 0x901C, "Communication error" }, + { 0x901D, "Foreign material in electro area" }, + /*0x9030 - 0x906F NE107 contact thermometer (PA Profile 4.02) */ + { 0x9030, "Immersion depth too limited" }, + { 0x9031, "Unequate medium around sensor" }, + { 0x9032, "Temp distrib not representative" }, + { 0x9033, "Inadequate thermal contact" }, + { 0x9034, "Sensor close to heat source/sink" }, + { 0x9035, "External temperature influence" }, + { 0x9036, "Insufficient thermocoupling" }, + { 0x9037, "Thermocoupling too high" }, + { 0x9038, "Friction heat by flowing gases" }, + { 0x9039, "Thermalcapac of sensor too high" }, + { 0x903A, "Deposits" }, + { 0x903B, "Systemrelated resonant vibration" }, + { 0x903C, "Resonantvibrat excited by flow" }, + { 0x903D, "Leakage" }, + { 0x903E, "Abrasion" }, + { 0x903F, "Corrosion" }, + { 0x9040, "Flow approach speed too high" }, + { 0x9041, "Insulation to ground too low" }, + { 0x9042, "Insulation betw. lines too low" }, + { 0x9043, "Parasitic thermal elements" }, + { 0x9044, "Parasitic galvanic elements" }, + { 0x9045, "Short circuit" }, + { 0x9046, "Shorted coil and break" }, + { 0x9047, "Line/contact resistance too high" }, + { 0x9048, "Compression spring failure" }, + { 0x9049, "Drift of sensor charact curve" }, + { 0x904A, "Insuff contact of meas insert" }, + { 0x904B, "Meas insert mechanical seized" }, + { 0x904C, "Measuring insert in thermowell" }, + { 0x904D, "Measuring insert too short" }, + { 0x904E, "Resistance wire abrasion" }, + { 0x904F, "Mechanic stress character curve" }, + { 0x9050, "Thermal stress character curve" }, + { 0x9051, "Intrinsic heating too severe" }, + { 0x9052, "EMI on measuring circuit" }, + { 0x9053, "Faulty linearisation" }, + { 0x9054, "Incorrect sensor position" }, + { 0x9055, "Faulty comparative point temp" }, + { 0x9056, "Faulty compar of line resistance" }, + { 0x9057, "Unsymmet supply line resistance" }, + { 0x9058, "Wrong material of compens line" }, + { 0x9059, "Damage to supply lines" }, + { 0x905A, "Capacitive feedback" }, + { 0x905B, "Potential transfer" }, + { 0x905C, "Potential differences exceeded" }, + { 0x905D, "Impermiss mix of wire systems" }, + { 0x905E, "Reverse polarity of lines" }, + { 0x905F, "Reverse polarity of lines" }, + /*0x9070 - 0x90A7 NE107 pressure (PA Profile 4.02) */ + { 0x9070, "Pressure peaks outside range" }, + { 0x9071, "Deposits on the seal diaphragm" }, + { 0x9072, "Characteristic curve change" }, + { 0x9073, "Inc. measuring err. (turn down)" }, + { 0x9074, "Wear on the seal diaphragm" }, + { 0x9075, "Process seal at flush diaphragm" }, + { 0x9076, "Offset error due to inst. pos." }, + { 0x9077, "Seal diaphragm deformation" }, + { 0x9078, "Hydrogen penetration" }, + { 0x9079, "Mean value deviation" }, + { 0x907A, "Pressure sensor system leakage" }, + { 0x907B, "Hydrostatic offset" }, + { 0x907C, "Gas seepage from pressure sensor" }, + { 0x907D, "Add. measuring err. due to temp." }, + { 0x907E, "Delta T in capillary tubing" }, + { 0x907F, "Increase in compensation times" }, + { 0x9080, "Oleic acid leak" }, + { 0x9081, "Pulse lines blocked" }, + { 0x9082, "Gas inclusion in liquid medium" }, + { 0x9083, "Delta T in pulse lines" }, + { 0x9084, "Liquid inclusion in gas" }, + { 0x9088, "Sedimentation on sensor" }, + { 0x9089, "Change of density" }, + { 0x908A, "Wrong height / wrong adjustment" }, + { 0x908B, "Clogged membrane" }, + { 0x908C, "Error with pulse line" }, + { 0x908D, "Internal tank pressure influence" }, + { 0x908E, "Influence of temperature" }, + { 0x908F, "Hydrogen diffusion" }, + { 0x9090, "Absence of bubble gas" }, + { 0x9091, "Air-bubble feed line blocked" }, + { 0x9092, "Wear and tear of diaphragm" }, + { 0x9093, "Gas seepage" }, + { 0x9094, "Pressure rise at rel. of bubbles" }, + { 0x9095, "Pressure sensor overload" }, + { 0x9096, "Flow rate of bubble gas too high" }, + /*0x90F8 - 0x910F NE107 coriolis (PA Profile 4.02) */ + { 0x90F8, "Gas bubbles in the liquid" }, + { 0x90F9, "Fouling, clogging" }, + { 0x90FA, "Erosion, corrosion" }, + { 0x90FB, "Faulty mounting" }, + { 0x90FC, "Asymmetry of measuring tubes" }, + { 0x90FD, "External vibrations" }, + { 0x90FE, "Pulsating flow" }, + { 0x90FF, "Incomplete filling" }, + /*0x9110 - 0x9127 NE107 EMF (PA Profile 4.02) */ + { 0x9110, "Gas bubbles in the liquid" }, + { 0x9111, "Corrosion of electrodes" }, + { 0x9112, "Electrical conductivity too low" }, + { 0x9113, "Liner damage" }, + { 0x9114, "Electrode fouling" }, + { 0x9115, "External magnetic fields" }, + { 0x9116, "Electrode short circuit" }, + { 0x9117, "Incomplete filling" }, + /*0x9128 - 0x913F NE107 thermal mass (PA Profile 4.02) */ + /* empty */ + /*0x9140 - 0x915F NE107 ultrasonic (PA Profile 4.02) */ + { 0x9140, "Particle inclusions Check process" }, + { 0x9141, "Gas bubbles in the liquid" }, + { 0x9142, "Body fouling" }, + { 0x9143, "External ultrasonic waves" }, + { 0x9144, "Sensor fouling" }, + { 0x9145, "Erosion" }, + { 0x9146, "Faulty mounting (clamp on)" }, + { 0x9147, "Pulsating flow" }, + { 0x9148, "Sound conductivity" }, + { 0x9149, "Signal lost due to overrange" }, + { 0x914A, "Flow profile disturbance" }, + { 0x914B, "Incomplete filling" }, + /*0x9160 - 0x9177 NE107 variable area (PA Profile 4.02) */ + { 0x9160, "Blocked float" }, + { 0x9161, "Fouling" }, + { 0x9162, "Erosion, corrosion" }, + { 0x9163, "Gas bubbles in the liquid" }, + { 0x9164, "Pulsating flow" }, + { 0x9165, "External magnetic fields" }, + /*0x9178 - 0x9197 NE107 vortex (PA Profile 4.02) */ + { 0x9178, "Gas bubbles in the liquid" }, + { 0x9179, "External vibrations" }, + { 0x917A, "Pulsating flow" }, + { 0x917B, "Two phase flow" }, + { 0x917C, "Cavitation in device" }, + { 0x917D, "Out of linear range" }, + { 0x917E, "Sensor fouling" }, + { 0x917F, "Solid particles" }, + { 0x9180, "Flow profile disturbance" }, + { 0x9181, "Incomplete filling" }, + { 0x9182, "Bluff body fouling" }, + /*0x9198 - 0x91B7 NE107 buoyancy (PA Profile 4.02) */ + { 0x9198, "Gas density change above liquid" }, + { 0x9199, "Vibration/strokes from outside" }, + { 0x919A, "Displacer partly inside compartm" }, + { 0x919B, "Displacer too heavy/too light" }, + { 0x919C, "Density change or displac config" }, + { 0x919D, "Sticking of torque or spring" }, + { 0x919E, "Displacer swinging freedomly" }, + { 0x919F, "Displac mounting faulty" }, + { 0x91A0, "Displacer blocked or bended" }, + { 0x91A1, "Displacer too light, corrosion" }, + { 0x91A2, "Displacer leakage" }, + { 0x91A3, "Force sensor broken" }, + /*0x91B8 - 0x91FF NE107 radar (PA Profile 4.02) */ + { 0x91B8, "Change of running time, encrust?" }, + { 0x91B9, "False echoes, encrustation?" }, + { 0x91BA, "Wrong/no indication, foam" }, + { 0x91BB, "Poor reflection" }, + { 0x91BC, "Problems with tank wall" }, + { 0x91BD, "Surge tube or vent blocked" }, + { 0x91BE, "Nozzle too long/high" }, + { 0x91BF, "No metallic reflecting surface" }, + { 0x91C0, "Blocking distance underrun" }, + { 0x91C1, "Mechanical overloading of probe" }, + { 0x91C2, "Probe lost or torn off" }, + { 0x91C3, "Overload by external power" }, + { 0x91C4, "Product or moisture in coupler" }, + { 0x91C5, "Change of microwave speed" }, + { 0x91C6, "Corr,abras, coating detachment" }, + { 0x91C7, "Probe in filling flow" }, + { 0x91D8, "No clear interface Emulsion?" }, + { 0x91D9, "Wrong indication param setting" }, + { 0x91DA, "Diff dielecon too small" }, + { 0x91DB, "More than one interface" }, + { 0x91DC, "First phase thickness too small" }, + { 0x91E0, "Attenuation due to deposits" }, + { 0x91E1, "False echoes due to deposits" }, + { 0x91E2, "Corrosion surge tube (inside)" }, + { 0x91E3, "Impurity in wave coupler area" }, + { 0x91E4, "Antenna immersed in product" }, + { 0x91E5, "Wrong signal due to foam" }, + { 0x91E6, "Strong signal attenuation" }, + { 0x91E7, "Shift of radar signal speed" }, + { 0x91E8, "Reflection" }, + { 0x91E9, "False interpretation of the echo" }, + { 0x91EA, "Bad polarization of the signal" }, + { 0x91EB, "Surge tube or vent blocked" }, + { 0x91EC, "Nozzle too long for antenna" }, + { 0x91ED, "Wall clearance, not vertical" }, + { 0x91EE, "Corrosion on antenna" }, + { 0x91EF, "Attenuation due to fog or dust" }, + { 0x91F0, "Antenna signal blocked" }, + { 0x91F1, "Blocking distance under-run" }, + { 0x91F2, "Echo too strong (overmodulation)" }, + /*0x9208 - 0x9257 NE107 electro (PA Profile 4.02) */ + { 0x9208, "Faulty torque monitoring" }, + { 0x9209, "Worn gear/spindle" }, + { 0x920A, "Drive torque off-spec" }, + { 0x920B, "Device temperature too high" }, + { 0x920C, "Faulty limit position monitoring" }, + { 0x920D, "Motor overload" }, + { 0x920E, "Oil quality off-spec" }, + { 0x920F, "Oil loss" }, + { 0x9210, "Blocked drive" }, + { 0x9211, "Off-spec seat/plug leakage" }, + { 0x9212, "Off-spec spindle/shaft seal leak" }, + { 0x9213, "Alteration and wear on spindle" }, + { 0x9214, "Altered friction" }, + { 0x9215, "Wear in the valve" }, + { 0x9216, "Blocked valve" }, + { 0x9217, "Change in valve move performance" }, + { 0x9218, "Changed breakaway moment" }, + { 0x9219, "Spindle deformation" }, + { 0x921A, "Plug torn off" }, + { 0x921B, "Off-spec valve temperature" }, + { 0x921C, "Off-spec characteristic line" }, + { 0x921E, "Incorrect position sensing" }, + { 0x921F, "Input signal off-spec" }, + { 0x9220, "Vibration off-spec" }, + { 0x9221, "Temp in positioner too high/low" }, + { 0x9222, "Moisture in positioner" }, + { 0x9223, "Additional IO module defect" }, + { 0x9224, "Signal without end position" }, + { 0x9225, "No signal in end position" }, + { 0x9226, "Control loop oscillation" }, + { 0x9227, "Hysteresis" }, + { 0x9228, "Changed friction" }, + { 0x9229, "Backlash between drive and valve" }, + { 0x922A, "Persistent deviation of control" }, + { 0x922B, "Inadmissible dynamic stress" }, + { 0x922C, "Faulty mounting" }, + { 0x922D, "Faulty mount positioner to motor" }, + { 0x922E, "Leak in piping" }, + { 0x922F, "Insufficient drive power" }, + { 0x9231, "Operator error during operation" }, + { 0x9232, "Inadmissible static stress" }, + { 0x9233, "Recording of pers. control dev." }, + { 0x9234, "Parameter plausibility check" }, + { 0x9235, "Status report on operating mode" }, + { 0x9236, "Histogram for valve positions" }, + { 0x9237, "Zero point and endpoint shift" }, + { 0x9238, "Running time monitoring" }, + { 0x9239, "Evaluation of internal signals" }, + { 0x923A, "Operating hours counter" }, + { 0x923B, "Pressure-displacement diagram" }, + { 0x923C, "Total valve travel" }, + { 0x923D, "Step response diagnostics" }, + { 0x923E, "Internal temperature monitoring" }, + { 0x923F, "Counter for direction changes" }, + { 0x9240, "Operating archive" }, + { 0x9241, "Report archive" }, + { 0x9242, "Status reports on access control" }, + { 0x9243, "Cavitation / flashing" }, + { 0x9244, "Partial stroke test" }, + { 0x9245, "P dif measurement across valve" }, + { 0x9246, "Noise level measurement" }, + /*0x9258 - 0x92A7 NE107 electro pneumatic (PA Profile 4.02) */ + { 0x9258, "Minor drive leakage" }, + { 0x9259, "High friction" }, + { 0x925A, "Feed air pressure off-spec" }, + { 0x925B, "Vent blockage" }, + { 0x925C, "Diaphragm damage" }, + { 0x925D, "Broken spring" }, + { 0x925E, "Moist air in spring chamber" }, + { 0x925F, "Blocked drive" }, + { 0x9260, "Drive leakage too big" }, + { 0x9261, "Off-spec seat/plug leakage" }, + { 0x9262, "Off-spec spindle/shaft seal leak" }, + { 0x9263, "Alteration and wear on spindle" }, + { 0x9264, "Altered friction" }, + { 0x9265, "Wear in the valve" }, + { 0x9266, "Blocked valve" }, + { 0x9267, "Change in valve move performance" }, + { 0x9268, "Changed breakaway moment" }, + { 0x9269, "Spindle deformation" }, + { 0x926A, "Plug torn off" }, + { 0x926B, "Off-spec valve temperature" }, + { 0x926C, "Off-spec characteristic line" }, + { 0x926D, "Fault in the pneumatic unit" }, + { 0x926E, "Incorrect position sensing" }, + { 0x926F, "Input signal off-spec" }, + { 0x9270, "Vibration off-spec" }, + { 0x9271, "Temp in positioner too high/low" }, + { 0x9272, "Moisture in positioner" }, + { 0x9273, "Additional IO module defect" }, + { 0x9274, "Signal without end position" }, + { 0x9275, "No signal in end position" }, + { 0x9276, "Control loop oscillation" }, + { 0x9277, "Hysteresis" }, + { 0x9278, "Changed friction" }, + { 0x9279, "Backlash between drive and valve" }, + { 0x927A, "Persistent deviation of control" }, + { 0x927B, "Inadmissible dynamic stress" }, + { 0x927C, "Faulty mounting" }, + { 0x927D, "Faulty mount positioner to drive" }, + { 0x927E, "Leak in piping" }, + { 0x927F, "Insufficient drive power" }, + { 0x9280, "Quality of feed air off-spec" }, + { 0x9281, "Operator error during operation" }, + { 0x9282, "Inadmissible static stress" }, + { 0x9283, "Recording of pers. control dev." }, + { 0x9284, "Parameter plausibility check" }, + { 0x9285, "Status report on operating mode" }, + { 0x9286, "Histogram for valve positions" }, + { 0x9287, "Zero point and endpoint shift" }, + { 0x9288, "Running time monitoring" }, + { 0x9289, "Evaluation of internal signals" }, + { 0x928A, "Operating hours counter" }, + { 0x928B, "Pressure-displacement diagram" }, + { 0x928C, "Total valve travel" }, + { 0x928D, "Step response diagnostics" }, + { 0x928E, "Internal temperature monitoring" }, + { 0x928F, "Counter for direction changes" }, + { 0x9290, "Operating archive" }, + { 0x9291, "Report archive" }, + { 0x9292, "Status reports on access control" }, + { 0x9293, "Cavitation / flashing" }, + { 0x9294, "Partial stroke test" }, + { 0x9295, "P dif measurement across valve" }, + { 0x9296, "Noise level measurement" }, + /*0x92A8 - 0x92BF NE107 sol valve (PA Profile 4.02) */ + { 0x92A8, "Failure to reach safe position" }, + { 0x92A9, "Failure to reach operat position" }, + { 0x92AA, "High temperature in coil" }, + { 0x92AB, "Moisture, humidity" }, + { 0x92AC, "Signal outside of endposition" }, + { 0x92AD, "No signal at endposition" }, + /*0x92C0 - 0x92DF Physical block (PA Profile 4.02) */ + { 0x92CD, "Maintenance" }, + { 0x92D0, "Maintenance alarm" }, + { 0x92D1, "Maintenance demanded" }, + { 0x92D2, "Function check" }, + { 0x92D3, "Out of spec." }, + { 0x92D4, "Update event" }, + /*0xA000 - 0xFFFF reserved */ + { 0, NULL } +}; + /* ExtChannelErrorType for ChannelErrorType 0 - 0x7FFF */ + +static const value_string pn_io_ext_channel_error_type0[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "Accumulative Info"}, + /* 0x8001 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + + /* ExtChannelErrorType for ChannelErrorType "Data transmission impossible" */ +static const value_string pn_io_ext_channel_error_type0x8000[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "Link State mismatch - Link down"}, + { 0x8001, "MAUType mismatch"}, + { 0x8002, "Line Delay mismatch"}, + /* 0x8003 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Remote mismatch" */ +static const value_string pn_io_ext_channel_error_type0x8001[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "Peer name of station mismatch"}, + { 0x8001, "Peer name of port mismatch"}, + { 0x8002, "Peer RT_CLASS_3 mismatch a"}, + { 0x8003, "Peer MAUType mismatch"}, + { 0x8004, "Peer MRP domain mismatch"}, + { 0x8005, "No peer detected"}, + { 0x8006, "Reserved"}, + { 0x8007, "Peer Line Delay mismatch"}, + { 0x8008, "Peer PTCP mismatch b"}, + { 0x8009, "Peer Preamble Length mismatch"}, + { 0x800A, "Peer Fragmentation mismatch"}, + { 0x800B, "Peer MRP Interconnection domain mismatch"}, + /* 0x800C - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Media redundancy mismatch" 0x8002 */ +static const value_string pn_io_ext_channel_error_type0x8002[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "Manager role fail MRP-instance 1"}, + { 0x8001, "MRP-instance 1 ring open"}, + { 0x8002, "Reserved"}, + { 0x8003, "Multiple manager MRP-instance 1"}, + { 0x8010, "Manager role fail MRP-instance 2"}, + { 0x8011, "MRP-instance 2 ring open"}, + { 0x8012, "Reserved"}, + { 0x8013, "Multiple manager MRP-instance 2"}, + { 0x8020, "Manager role fail MRP-instance 3"}, + { 0x8021, "MRP-instance 3 ring open"}, + { 0x8023, "Multiple manager MRP-instance 3"}, + { 0x8030, "Manager role fail MRP-instance 4"}, + { 0x8031, "MRP-instance 4 ring open"}, + { 0x8033, "Multiple manager MRP-instance 4"}, + { 0x8040, "Manager role fail MRP-instance 5"}, + { 0x8041, "MRP-instance 5 ring open"}, + { 0x8043, "Multiple manager MRP-instance 5"}, + { 0x8050, "Manager role fail MRP-instance 6"}, + { 0x8051, "MRP-instance 6 ring open"}, + { 0x8053, "Multiple manager MRP-instance 6"}, + { 0x8060, "Manager role fail MRP-instance 7"}, + { 0x8061, "MRP-instance 7 ring open"}, + { 0x8063, "Multiple manager MRP-instance 7"}, + { 0x8070, "Manager role fail MRP-instance 8"}, + { 0x8071, "MRP-instance 8 ring open"}, + { 0x8073, "Multiple manager MRP-instance 8"}, + { 0x8080, "Manager role fail MRP-instance 9"}, + { 0x8081, "MRP-instance 9 ring open"}, + { 0x8083, "Multiple manager MRP-instance 9"}, + { 0x8090, "Manager role fail MRP-instance 10"}, + { 0x8091, "MRP-instance 10 ring open"}, + { 0x8093, "Multiple manager MRP-instance 10"}, + { 0x80A0, "Manager role fail MRP-instance 11"}, + { 0x80A1, "MRP-instance 11 ring open"}, + { 0x80A3, "Multiple manager MRP-instance 11"}, + { 0x80B0, "Manager role fail MRP-instance 12"}, + { 0x80B1, "MRP-instance 12 ring open"}, + { 0x80B3, "Multiple manager MRP-instance 12"}, + { 0x80C0, "Manager role fail MRP-instance 13"}, + { 0x80C1, "MRP-instance 13 ring open"}, + { 0x80C3, "Multiple manager MRP-instance 13"}, + { 0x80D0, "Manager role fail MRP-instance 14"}, + { 0x80D1, "MRP-instance 14 ring open"}, + { 0x80D3, "Multiple manager MRP-instance 14"}, + { 0x80E0, "Manager role fail MRP-instance 15"}, + { 0x80E1, "MRP-instance 15 ring open"}, + { 0x80E3, "Multiple manager MRP-instance 15"}, + { 0x80F0, "Manager role fail MRP-instance 16"}, + { 0x80F1, "MRP-instance 16 ring open"}, + { 0x80F3, "Multiple manager MRP-instance 16"}, + /* 0x8004 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Sync mismatch" and for ChannelErrorType "Time mismatch" 0x8003 and 0x8009*/ +static const value_string pn_io_ext_channel_error_type0x8003[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "No sync message received"}, + { 0x8001, "- 0x8002 Reserved"}, + { 0x8003, "Jitter out of boundary"}, + /* 0x8004 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /*ExtChannelErrorType for ChannelErrorType "Isochronous mode mismatch" 0x8004 */ +static const value_string pn_io_ext_channel_error_type0x8004[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "Output Time Failure - Output update missing or out of order"}, + { 0x8001, "Input Time Failure"}, + { 0x8002, "Master Life Sign Failure - Error in MLS update detected"}, + /* 0x8003 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Multicast CR mismatch" 0x8005 */ +static const value_string pn_io_ext_channel_error_type0x8005[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "Multicast Consumer CR timed out"}, + { 0x8001, "Address resolution failed"}, + /* 0x8002 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Fiber optic mismatch" 0x8007*/ +static const value_string pn_io_ext_channel_error_type0x8007[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "Power Budget"}, + { 0x8001, "SFP - Temperature threshold violation (High)"}, + { 0x8002, "SFP - TX Bias threshold violation (High)"}, + { 0x8003, "SFP - TX Bias threshold violation (Low)"}, + { 0x8004, "SFP - TX Power threshold violation (High)"}, + { 0x8005, "SFP - TX Power threshold violation (Low)"}, + { 0x8006, "SFP - RX Power threshold violation (High)"}, + { 0x8007, "SFP - RX Power threshold violation (Low)"}, + { 0x8008, "SFP - TX Fault State indication"}, + { 0x8009, "SFP - RX Loss State indication"}, + /* 0x800A - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Network component function mismatch" 0x8008 */ +static const value_string pn_io_ext_channel_error_type0x8008[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "Frame dropped - no resource"}, + /* 0x8001 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Dynamic Frame Packing function mismatch" 0x800A */ +static const value_string pn_io_ext_channel_error_type0x800A[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + /* 0x8000 - 0x80FF Reserved */ + { 0x8100, "Frame late error for FrameID (0x0100)"}, + /* 0x8101 + 0x8FFE See Equation (56) */ + { 0x8FFF, "Frame late error for FrameID (0x0FFF)"}, + /* 0x8001 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Media redundancy with planned duplication mismatch" 0x800B */ +static const value_string pn_io_ext_channel_error_type0x800B[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + /* 0x8000 - 0x86FF Reserved */ + { 0x8700, "MRPD duplication void for FrameID (0x0700)"}, + /* 0x8701 + 0x8FFE See Equation (57) */ + { 0x8FFF, "MRPD duplication void for FrameID (0x0FFF)"}, + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "System redundancy mismatch" 0x800C */ +static const value_string pn_io_ext_channel_error_type0x800C[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "System redundancy event"}, + /* 0x8001 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + + /* ExtChannelErrorType for ChannelErrorType "Power failure over Single Pair Ethernet" 0x8010 */ +static const value_string pn_io_ext_channel_error_type0x8010[] = { + /* 0x0000 Reserved */ + /* 0x0001 - 0x7FFF Manufacturer specific */ + { 0x8000, "SPE power supply - Short circuit"}, + { 0x8001, "SPE power supply - Open circuit"}, + { 0x8002, "SPE power supply - Voltage level"}, + { 0x8003, "SPE power supply - Current level"}, + /* 0x8004 - 0x8FFF Reserved */ + /* 0x9000 - 0x9FFF Reserved for profiles */ + /* 0xA000 - 0xFFFF Reserved */ + { 0, NULL } +}; + +/* QualifiedChannelQualifier */ +static const value_string pn_io_qualified_channel_qualifier[] = { + {0x00000001, "Reserved"}, + {0x00000002, "Reserved"}, + {0x00000004, "Reserved"}, + {0x00000008, "Qualifier_3 (Advice)"}, + {0x00000010, "Qualifier_4 (Advice, PA: UpdateEvent)"}, + {0x00000020, "Qualifier_5 (Advice, PA: OutOfSpecification)"}, + {0x00000040, "Qualifier_6 (Advice)"}, + {0x00000080, "Qualifier_7 (MaintenanceRequired)"}, + {0x00000100, "Qualifier_8 (MaintenanceRequired)"}, + {0x00000200, "Qualifier_9 (MaintenanceRequired)"}, + {0x00000400, "Qualifier_10 (MaintenanceRequired)"}, + {0x00000800, "Qualifier_11 (MaintenanceRequired)"}, + {0x00001000, "Qualifier_12 (MaintenanceRequired, PA: MaintenanceRequired)"}, + {0x00002000, "Qualifier_13 (MaintenanceRequired)"}, + {0x00004000, "Qualifier_14 (MaintenanceRequired)"}, + {0x00008000, "Qualifier_15 (MaintenanceRequired)"}, + {0x00010000, "Qualifier_16 (MaintenanceRequired)"}, + {0x00020000, "Qualifier_17 (MaintenanceDemanded)"}, + {0x00040000, "Qualifier_18 (MaintenanceDemanded)"}, + {0x00080000, "Qualifier_19 (MaintenanceDemanded)"}, + {0x00100000, "Qualifier_20 (MaintenanceDemanded)"}, + {0x00200000, "Qualifier_21 (MaintenanceDemanded)"}, + {0x00400000, "Qualifier_22 (MaintenanceDemanded, PA: MaintenanceDemanded)"}, + {0x00800000, "Qualifier_23 (MaintenanceDemanded)"}, + {0x01000000, "Qualifier_24 (MaintenanceDemanded, PA: FunctionCheck)"}, + {0x02000000, "Qualifier_25 (MaintenanceDemanded)"}, + {0x04000000, "Qualifier_26 (MaintenanceDemanded)"}, + {0x08000000, "Qualifier_27 (Fault)"}, + {0x10000000, "Qualifier_28 (Fault)"}, + {0x20000000, "Qualifier_29 (Fault)"}, + {0x40000000, "Qualifier_30 (Fault, PA: Fault)"}, + {0x80000000, "Qualifier_31 (Fault)"}, + {0, NULL}}; + +static const value_string pn_io_channel_properties_type[] = { + { 0x0000, "submodule or unspecified" }, + { 0x0001, "1 Bit" }, + { 0x0002, "2 Bit" }, + { 0x0003, "4 Bit" }, + { 0x0004, "8 Bit" }, + { 0x0005, "16 Bit" }, + { 0x0006, "32 Bit" }, + { 0x0007, "64 Bit" }, + /*0x0008 - 0x00FF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_channel_properties_accumulative_vals[] = { + { 0x0000, "Channel" }, + { 0x0001, "ChannelGroup" }, + { 0, NULL } +}; + +/* We are reading this as a two bit value, but the spec specifies each bit + * separately. Beware endianness when reading spec + */ +static const value_string pn_io_channel_properties_maintenance[] = { + { 0x0000, "Failure" }, + { 0x0001, "Maintenance required" }, + { 0x0002, "Maintenance demanded" }, + { 0x0003, "see QualifiedChannelQualifier" }, + { 0, NULL } +}; + +static const value_string pn_io_channel_properties_specifier[] = { + { 0x0000, "All subsequent disappears" }, + { 0x0001, "Appears" }, + { 0x0002, "Disappears" }, + { 0x0003, "Disappears but others remain" }, + { 0, NULL } +}; + +static const value_string pn_io_channel_properties_direction[] = { + { 0x0000, "Manufacturer-specific" }, + { 0x0001, "Input" }, + { 0x0002, "Output" }, + { 0x0003, "Input/Output" }, + /*0x0004 - 0x0007 reserved */ + { 0, NULL } +}; + +static const value_string pn_io_alarmcr_type[] = { + { 0x0000, "reserved" }, + { 0x0001, "Alarm CR" }, + /*0x0002 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_mau_type[] = { + /*0x0000 - 0x0004 reserved */ + { 0x0005, "10BASET" }, + /*0x0006 - 0x0009 reserved */ + { 0x000A, "10BASETXHD" }, + { 0x000B, "10BASETXFD" }, + { 0x000C, "10BASEFLHD" }, + { 0x000D, "10BASEFLFD" }, + { 0x000F, "100BASETXHD" }, + { 0x0010, "100BASETXFD" }, + { 0x0011, "100BASEFXHD" }, + { 0x0012, "100BASEFXFD" }, + /*0x0013 - 0x0014 reserved */ + { 0x0015, "1000BASEXHD" }, + { 0x0016, "1000BASEXFD" }, + { 0x0017, "1000BASELXHD" }, + { 0x0018, "1000BASELXFD" }, + { 0x0019, "1000BASESXHD" }, + { 0x001A, "1000BASESXFD" }, + /*0x001B - 0x001C reserved */ + { 0x001D, "1000BASETHD" }, + { 0x001E, "1000BASETFD" }, + { 0x001F, "10GigBASEFX" }, + /*0x0020 - 0x002D reserved */ + { 0x002E, "100BASELX10" }, + /*0x002F - 0x0035 reserved */ + { 0x0036, "100BASEPXFD" }, + /*0x0037 - 0x008C reserved */ + { 0x008D, "10BASET1L" }, + /*0x008E - 0xFFFF reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_preamble_length[] = { + { 0x0000, "Seven octets Preamble shall be used" }, + { 0x0001, "One octet Preamble shall be used" }, + /*0x0002 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_mau_type_mode[] = { + { 0x0000, "OFF" }, + { 0x0001, "ON" }, + /*0x0002 - 0xFFFF reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_dcp_boundary_value_bit0[] = { + { 0x00, "Do not block the multicast MAC address 01-0E-CF-00-00-00" }, + { 0x01, "Block an outgoing DCP_Identify frame (egress filter) with the multicast MAC address 01-0E-CF-00-00-00" }, + { 0, NULL } +}; + +static const value_string pn_io_dcp_boundary_value_bit1[] = { + { 0x00, "Do not block the multicast MAC address 01-0E-CF-00-00-01" }, + { 0x01, "Block an outgoing DCP_Hello frame (egress filter) with the multicast MAC address 01-0E-CF-00-00-01" }, + { 0, NULL } +}; + +static const value_string pn_io_peer_to_peer_boundary_value_bit0[] = { + { 0x00, "The LLDP agent shall send LLDP frames for this port." }, + { 0x01, "The LLDP agent shall not send LLDP frames (egress filter)." }, + { 0, NULL } +}; + +static const value_string pn_io_peer_to_peer_boundary_value_bit1[] = { + { 0x00, "The PTCP ASE shall send PTCP_DELAY request frames for this port." }, + { 0x01, "The PTCP ASE shall not send PTCP_DELAY request frames (egress filter)." }, + { 0, NULL } +}; + +static const value_string pn_io_peer_to_peer_boundary_value_bit2[] = { + { 0x00, "The Time ASE shall send PATH_DELAY request frames for this port." }, + { 0x01, "The Time ASE shall not send PATH_DELAY request frames (egress filter)." }, + { 0, NULL } +}; + +static const range_string pn_io_mau_type_extension[] = { + { 0x0000, 0x0000, "No SubMAUType" }, + { 0x0001, 0x00FF, "Reserved" }, + { 0x0100, 0x0100, "POF" }, + { 0x0101, 0x01FF, "Reserved for SubMAUType" }, + { 0x0200, 0x0200, "APL" }, + { 0x0201, 0xFFEF, "Reserved for SubMAUType" }, + { 0xFFF0, 0xFFFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const range_string pn_io_pe_operational_mode[] = { + { 0x00, 0x00, "PE_PowerOff" }, + { 0x01, 0x1F, "PE_EnergySavingMode" }, + { 0x20, 0xEF, "Reserved" }, + { 0xF0, 0xF0, "PE_Operate" }, + { 0xF1, 0xFD, "Reserved" }, + { 0xFE, 0xFE, "PE_SleepModeWOL" }, + { 0xFF, 0xFF, "PE_ReadyToOperate" }, + { 0, 0, NULL } +}; + +static const value_string pn_io_port_state[] = { + { 0x0000, "reserved" }, + { 0x0001, "up" }, + { 0x0002, "down" }, + { 0x0003, "testing" }, + { 0x0004, "unknown" }, + /*0x0005 - 0xFFFF reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_link_state_port[] = { + { 0x00, "unknown" }, + { 0x01, "disabled/discarding" }, + { 0x02, "blocking" }, + { 0x03, "listening" }, + { 0x04, "learning" }, + { 0x05, "forwarding" }, + { 0x06, "broken" }, + /*0x07 - 0xFF reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_link_state_link[] = { + { 0x00, "reserved" }, + { 0x01, "up" }, + { 0x02, "down" }, + { 0x03, "testing" }, + { 0x04, "unknown" }, + { 0x05, "dormant" }, + { 0x06, "notpresent" }, + { 0x07, "lowerlayerdown" }, + /*0x08 - 0xFF reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_media_type[] = { + { 0x0000, "Unknown" }, + { 0x0001, "Copper cable" }, + { 0x0002, "Fiber optic cable" }, + { 0x0003, "Radio communication" }, + /*0x0004 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_fiber_optic_type[] = { + { 0x0000, "No fiber type adjusted" }, + { 0x0001, "9 um single mode fiber" }, + { 0x0002, "50 um multi mode fiber" }, + { 0x0003, "62,5 um multi mode fiber" }, + { 0x0004, "SI-POF, NA=0.5" }, + { 0x0005, "SI-PCF, NA=0.36" }, + { 0x0006, "LowNA-POF, NA=0.3" }, + { 0x0007, "GI-POF" }, + /*0x0008 - 0xFFFF reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_fiber_optic_cable_type[] = { + { 0x0000, "No cable specified" }, + { 0x0001, "Inside/outside cable, fixed installation" }, + { 0x0002, "Inside/outside cable, flexible installation" }, + { 0x0003, "Outdoor cable, fixed installation" }, + /*0x0004 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_im_revision_prefix_vals[] = { + { 'V', "V - Officially released version" }, + { 'R', "R - Revision" }, + { 'P', "P - Prototype" }, + { 'U', "U - Under Test (Field Test)" }, + { 'T', "T - Test Device" }, + /*all others reserved */ + { 0, NULL } +}; + + +static const value_string pn_io_mrp_role_vals[] = { + { 0x0000, "Media Redundancy disabled" }, + { 0x0001, "Media Redundancy Client" }, + { 0x0002, "Media Redundancy Manager" }, + /*all others reserved */ + { 0, NULL } +}; + +static const value_string pn_io_mrp_instance_no[] = { + { 0x0000, "MRP_Instance 1" }, + { 0x0001, "MRP_Instance 2" }, + { 0x0002, "MRP_Instance 3" }, + { 0x0003, "MRP_Instance 4" }, + { 0x0004, "MRP_Instance 5" }, + { 0x0005, "MRP_Instance 6" }, + { 0x0006, "MRP_Instance 7" }, + { 0x0007, "MRP_Instance 8" }, + { 0x0008, "MRP_Instance 9" }, + { 0x0009, "MRP_Instance 10" }, + { 0x000A, "MRP_Instance 11" }, + { 0x000B, "MRP_Instance 12" }, + { 0x000C, "MRP_Instance 13" }, + { 0x000D, "MRP_Instance 14" }, + { 0x000E, "MRP_Instance 15" }, + { 0x000F, "MRP_Instance 16" }, + /*all others reserved */ + { 0, NULL } +}; + +static const value_string pn_io_mrp_mrm_on[] = { + { 0x0000, "Disable MediaRedundancyManager diagnosis" }, + { 0x0001, "Enable MediaRedundancyManager diagnosis"}, + { 0, NULL } +}; +static const value_string pn_io_mrp_checkUUID[] = { + { 0x0000, "Disable the check of the MRP_DomainUUID" }, + { 0x0001, "Enable the check of the MRP_DomainUUID"}, + { 0, NULL } +}; + +static const value_string pn_io_mrp_prio_vals[] = { + { 0x0000, "Highest priority redundancy manager" }, + /* 0x1000 - 0x7000 High priorities */ + { 0x8000, "Default priority for redundancy manager" }, + /* 0x9000 - 0xE000 Low priorities */ + { 0xF000, "Lowest priority redundancy manager" }, + /*all others reserved */ + { 0, NULL } +}; + +static const value_string pn_io_mrp_rtmode_rtclass12_vals[] = { + { 0x0000, "RT_CLASS_1 and RT_CLASS_2 redundancy mode deactivated" }, + { 0x0001, "RT_CLASS_1 and RT_CLASS_2 redundancy mode activated" }, + { 0, NULL } +}; + +static const value_string pn_io_mrp_rtmode_rtclass3_vals[] = { + { 0x0000, "RT_CLASS_3 redundancy mode deactivated" }, + { 0x0001, "RT_CLASS_3 redundancy mode activated" }, + { 0, NULL } +}; + +static const value_string pn_io_mrp_ring_state_vals[] = { + { 0x0000, "Ring open" }, + { 0x0001, "Ring closed" }, + { 0, NULL } +}; + +static const value_string pn_io_mrp_rt_state_vals[] = { + { 0x0000, "RT media redundancy lost" }, + { 0x0001, "RT media redundancy available" }, + { 0, NULL } +}; + +static const value_string pn_io_control_properties_vals[] = { + { 0x0000, "Reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_control_properties_prmbegin_vals[] = { + { 0x0000, "No PrmBegin" }, + { 0x0001, "The IO controller starts the transmission of the stored start-up parameter" }, + { 0, NULL } +}; +static const value_string pn_io_control_properties_application_ready_bit0_vals[] = { + { 0x0000, "Wait for explicit ControlCommand.ReadyForCompanion" }, + { 0x0001, "Implicit ControlCommand.ReadyForCompanion" }, + { 0, NULL } +}; +static const value_string pn_io_control_properties_application_ready_bit1_vals[] = { + { 0x0000, "Wait for explicit ControlCommand.ReadyForRT_CLASS_3" }, + { 0x0001, "Implicit ControlCommand.ReadyForRT_CLASS_3" }, + { 0, NULL } +}; +static const value_string pn_io_fs_hello_mode_vals[] = { + { 0x0000, "OFF" }, + { 0x0001, "Send req on LinkUp" }, + { 0x0002, "Send req on LinkUp after HelloDelay" }, + { 0, NULL } +}; + +static const value_string pn_io_fs_parameter_mode_vals[] = { + { 0x0000, "OFF" }, + { 0x0001, "ON" }, + { 0x0002, "Reserved" }, + { 0x0003, "Reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_frame_details_sync_master_vals[] = { + { 0x0000, "No Sync Frame" }, + { 0x0001, "Primary sync frame" }, + { 0x0002, "Secondary sync frame" }, + { 0x0003, "Reserved" }, + { 0, NULL } +}; +static const value_string pn_io_frame_details_meaning_frame_send_offset_vals[] = { + { 0x0000, "Field FrameSendOffset specifies the point of time for receiving or transmitting a frame " }, + { 0x0001, "Field FrameSendOffset specifies the beginning of the RT_CLASS_3 interval within a phase" }, + { 0x0002, "Field FrameSendOffset specifies the ending of the RT_CLASS_3 interval within a phase" }, + { 0x0003, "Reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_f_check_seqnr[] = { + { 0x00, "consecutive number not included in crc" }, + { 0x01, "consecutive number included in crc" }, + { 0, NULL } +}; + +static const value_string pn_io_f_check_ipar[] = { + { 0x00, "no check" }, + { 0x01, "check" }, + { 0, NULL } +}; + +static const value_string pn_io_f_sil[] = { + { 0x00, "SIL1" }, + { 0x01, "SIL2" }, + { 0x02, "SIL3" }, + { 0x03, "NoSIL" }, + { 0, NULL } +}; + +static const value_string pn_io_f_crc_len[] = { + { 0x00, "3 octet CRC" }, + { 0x01, "2 octet CRC" }, + { 0x02, "4 octet CRC" }, + { 0x03, "reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_f_crc_seed[] = { + { 0x00, "CRC-FP as seed value and counter" }, + { 0x01, "'1' as seed value and CRC-FP+/MNR" }, + { 0, NULL } +}; + +/* F_Block_ID dissection due to ver2.6 specifikation of PI */ +static const value_string pn_io_f_block_id[] = { + { 0x00, "No F_WD_Time_2, no F_iPar_CRC" }, + { 0x01, "No F_WD_Time_2, F_iPar_CRC" }, + { 0x02, "F_WD_Time_2, no F_iPar_CRC" }, + { 0x03, "F_WD_Time_2, F_iPar_CRC" }, + /* 0x04..0x07 reserved */ + /* { 0x00, "Parameter set for F-Host/F-Device relationship" }, */ + /* { 0x01, "Additional F_Address parameter block" }, */ + /* 0x02..0x07 reserved */ + { 0, NULL } +}; + +static const value_string pn_io_f_par_version[] = { + { 0x00, "Valid for V1-mode" }, + { 0x01, "Valid for V2-mode" }, + /* 0x02..0x03 reserved */ + { 0, NULL } +}; + +static const value_string pn_io_profidrive_request_id_vals[] = { + { 0x00, "Reserved" }, + { 0x01, "Read request" }, + { 0x02, "Change request" }, + { 0, NULL } +}; + +static const value_string pn_io_profidrive_response_id_vals[] = { + { 0x00, "Reserved" }, + { 0x01, "Positive read response" }, + { 0x02, "Positive change response" }, + { 0x81, "Negative read response" }, + { 0x82, "Negative change response" }, + { 0, NULL } +}; + +static const value_string pn_io_profidrive_attribute_vals[] = { + { 0x00, "Reserved" }, + { 0x10, "Value" }, + { 0x20, "Description" }, + { 0x30, "Text" }, + { 0, NULL } +}; + +static const value_string pn_io_profidrive_format_vals[] = { + {0x0, "Zero"}, + {0x01, "Boolean" }, + {0x02, "Integer8" }, + {0x03, "Integer16" }, + {0x04, "Integer32" }, + {0x05, "Unsigned8" }, + {0x06, "Unsigned16" }, + {0x07, "Unsigned32" }, + {0x08, "Float32" }, + {0x09, "VisibleString" }, + {0x0A, "OctetString" }, + {0x0B, "Binary Date"}, + {0x0C, "TimeOfDay" }, + {0x0D, "TimeDifference" }, + {0x0E, "BitString"}, + {0x0F, "Float64"}, + {0x10, "UniversalTime"}, + {0x11, "FieldbusTime"}, + {0x15, "Time Value"}, + {0x16, "Bitstring8"}, + {0x17, "Bitstring16"}, + {0x18, "Bitstring32"}, + {0x19, "VisibleString1"}, + {0x1A, "VisibleString2"}, + {0x1B, "VisibleString4"}, + {0x1C, "VisibleString8"}, + {0x1D, "VisibleString16"}, + {0x1E, "OctetString1"}, + {0x1F, "OctetString2"}, + {0x20, "OctetString4"}, + {0x21, "OctetString8"}, + {0x22, "OctetString16"}, + {0x23, "BCD"}, + {0x24, "UNICODE char"}, + {0x25, "CompactBoolean-Array"}, + {0x26, "CompactBCDArray"}, + {0x27, "UNICODEString"}, + {0x28, "BinaryTime0"}, + {0x29, "BinaryTime1"}, + {0x2A, "BinaryTime2"}, + {0x2B, "BinaryTime3"}, + {0x2C, "BinaryTime4"}, + {0x2D, "BinaryTime5"}, + {0x2E, "BinaryTime6"}, + {0x2F, "BinaryTime7"}, + {0x30, "BinaryTime8"}, + {0x31, "BinaryTime9"}, + {0x32, "Date"}, + {0x33, "BinaryDate2000"}, + {0x34, "TimeOfDay without date indication"}, + {0x35, "TimeDifference with date indication"}, + {0x36, "TimeDifference without date indication"}, + {0x37, "Integer64"}, + {0x38, "Unsigned64"}, + {0x39, "BitString64"}, + {0x3A, "NetworkTime"}, + {0x3B, "NetworkTime-Difference"}, + + {0x40, "Zero" }, + {0x41, "Byte" }, + {0x42, "Word" }, + {0x43, "Dword" }, + {0x44, "Error Type" }, + {0x65, "Float32+Unsigned8"}, + {0x66, "Unsigned8+Unsigned8"}, + {0x67, "OctetString2+Unsigned8"}, + {0x68, "Unsigned16_S"}, + {0x69, "Integer16_S"}, + {0x6A, "Unsigned8_S"}, + {0x6B, "OctetString_S"}, + {0x6E, "F message trailer with 4 octets"}, + {0x6F, "F message trailer with 5 octets"}, + {0x70, "F message trailer with 6 octets"}, + {0x71, "N2 Normalized value (16 bit)"}, + {0x72, "N4 Normalized value (32 bit)"}, + {0x73, "V2 Bit sequence" }, + {0x74, "L2 Nibble"}, + {0x75, "R2 Reciprocal time constant"}, + {0x76, "T2 Time constant (16 bit)"}, + {0x77, "T4 Time constant (32 bit)"}, + {0x78, "D2 Time constant"}, + {0x79, "E2 Fixed point value (16 bit)"}, + {0x7A, "C4 Fixed point value (32 bit)"}, + {0x7B, "X2 Normalized value, variable (16bit)"}, + {0x7C, "X4 Normalized value, variables (32bit)"}, + { 0, NULL } +}; + +static const value_string pn_io_profidrive_parameter_resp_errors[] = +{ + {0x0, "Disallowed parameter number" }, + {0x1, "The parameter value cannot be changed" }, + {0x2, "Exceed the upper or lower limit" }, + {0x3, "Sub-index error" }, + {0x4, "Non-array" }, + {0x5, "Incorrect data type" }, + {0x6, "Setting is not allowed (can only be reset)" }, + {0x7, "The description element cannot be modified" }, + {0x8, "Reserved" }, + {0x9, "Descriptive data does not exist" }, + {0xA, "Reserved" }, + {0xB, "No operation priority" }, + {0xC, "Reserved" }, + {0xD, "Reserved" }, + {0xE, "Reserved" }, + {0xF, "The text array does not save right" }, + {0x11, "The request cannot be executed because of the working status" }, + {0x12, "Reserved" }, + {0x13, "Reserved" }, + {0x14, "Value is not allowed" }, + {0x15, "Response timeout" }, + {0x16, "Illegal parameter address" }, + {0x17, "Illegal parameter format" }, + {0x18, "The number of values is inconsistent" }, + {0x19, "Axis/DO does not exist" }, + {0x20, "The parameter text element cannot be changed" }, + {0x21, "No support service" }, + {0x22, "Too many parameter requests" }, + {0x23, "Only support single parameter access" }, + { 0, NULL } +}; +static const range_string pn_io_rs_block_type[] = { + /* Following ranges are used for events */ + { 0x0000, 0x0000, "reserved" }, + { 0x0001, 0x3FFF, "Manufacturer specific" }, + { 0x4000, 0x4000, "Stop observer - Observer Status Observer" }, + { 0x4001, 0x4001, "Buffer observer - RS_BufferObserver" }, + { 0x4002, 0x4002, "Time status observer - RS_TimeStatus" }, + { 0x4003, 0x4003, "System redundancy layer observer - RS_SRLObserver" }, + { 0x4004, 0x4004, "Source identification observer - RS_SourceIdentification" }, + { 0x4005, 0x400F, "reserved" }, + { 0x4010, 0x4010, "Digital input observer - SoE_DigitalInputObserver" }, + { 0x4011, 0x6FFF, "Reserved for normative usage" }, + { 0x7000, 0x7FFF, "Reserved for profile usage" }, + /* Following ranges are used for adjust */ + { 0x8000, 0x8000, "reserved" }, + { 0x8001, 0xBFFF, "Manufacturer specific" }, + { 0xC000, 0xC00F, "Reserved for normative usage" }, + { 0xC010, 0xC010, "Digital input observer - SoE_DigitalInputObserver" }, + { 0xC011, 0xEFFF, "Reserved for normative usage"}, + { 0xF000, 0xFFFF, "Reserved for profile usage"}, + { 0, 0, NULL } +}; + +static const value_string pn_io_rs_specifier_specifier[] = { + { 0x0, "Current value" }, + { 0x1, "Appears" }, + { 0x2, "Disappears" }, + { 0x3, "Reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_rs_time_stamp_status[] = { + { 0x0, "TimeStamp related to global synchronized time" }, + { 0x1, "TimeStamp related to local time" }, + { 0x2, "TimeStamp related to local (arbitrary timescale) time" }, + { 0, NULL } +}; + +static const value_string pn_io_rs_reason_code_reason[] = { + { 0x00000000, "Reserved" }, + { 0x00000001, "Observed data status unclear" }, + { 0x00000002, "Buffer overrun" }, + /* 0x0003 - 0xFFFF Reserved */ + { 0, NULL } +}; + +static const value_string pn_io_rs_reason_code_detail[] = { + { 0x00000000, "No Detail" }, + /* 0x0001 - 0xFFFF Reserved */ + { 0, NULL } +}; + +static const value_string pn_io_soe_digital_input_current_value_value[] = { + { 0x0, "Digital input is zero" }, + { 0x1, "Digital input is one" }, + { 0, NULL } +}; + +static const value_string pn_io_soe_adjust_specifier_incident[] = { + { 0x00, "Reserved" }, + { 0x01, "Rising edge" }, + { 0x02, "Falling edge" }, + { 0x03, "Reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_rs_properties_alarm_transport[] = { + { 0x00000000, "Default Reporting system events need to be read by record " }, + { 0x00000001, "Reporting system events shall be forwarded to the IOC using the alarm transport" }, + { 0, NULL } +}; + +static const value_string pn_io_am_location_structure_vals[] = { + { 0x00, "Reserved" }, + { 0x01, "Twelve level tree format" }, + { 0x02, "Slot - and SubslotNumber format" }, + { 0, NULL } +}; + +static const range_string pn_io_am_location_level_vals[] = { + { 0x0000, 0x03FE, "Address information to identify a reported node" }, + { 0x03FF, 0x03FF, "Level not used" }, + { 0, 0, NULL } +}; + +static const value_string pn_io_am_location_reserved_vals[] = { + { 0x00, "Reserved" }, + { 0, NULL } +}; + +static const range_string pn_io_RedundancyDataHoldFactor[] = { + { 0x0000, 0x0002, "Reserved" }, + { 0x0003, 0x00C7, "Optional - An expiration of the time leads to an AR termination." }, + { 0x00C8, 0xFFFF, "Mandatory - An expiration of the time leads to an AR termination." }, + { 0, 0, NULL } +}; + +static const value_string pn_io_ar_arnumber[] = { + { 0x0000, "reserved" }, + { 0x0001, "1st AR of an ARset" }, + { 0x0002, "2nd AR of an ARset" }, + { 0x0003, "3rd AR of an ARset" }, + { 0x0004, "4th AR of an ARset" }, + /*0x0005 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const value_string pn_io_ar_arresource[] = { + { 0x0000, "reserved" }, + { 0x0002, "Communication endpoint shall allocate two ARs for the ARset" }, + /*0x0001 and 0x0003 - 0xFFFF reserved */ + { 0, NULL } +}; + +static const range_string pn_io_line_delay_value[] = { + { 0x00000000, 0x00000000, "Line delay and cable delay unknown" }, + { 0x00000001, 0x7FFFFFFF, "Line delay in nanoseconds" }, + { 0, 0, NULL } +}; + +static const range_string pn_io_cable_delay_value[] = { + { 0x00000000, 0x00000000, "Reserved" }, + { 0x00000001, 0x7FFFFFFF, "Cable delay in nanoseconds" }, + { 0, 0, NULL } +}; + +static const true_false_string pn_io_pdportstatistic_counter_status_contents = { + "The contents of the field are invalid. They shall be set to zero.", + "The contents of the field are valid" +}; + +static const value_string pn_io_pdportstatistic_counter_status_reserved[] = { + { 0x00, "Reserved" }, + { 0, NULL } +}; + +static const value_string pn_io_tsn_domain_vid_config_vals[] = { + { 0x00, "Reserved" }, + { 0x64, "NonStreamVID-Default" }, + { 0x65, "StreamHighVID-Default" }, + { 0x66, "StreamHighRedVID-Default" }, + { 0x67, "StreamLowVID-Default" }, + { 0x68, "StreamLowRedVID-Default" }, + { 0x69, "NonStreamVIDB-Default" }, + { 0x6A, "NonStreamVIDC-Default" }, + { 0x6B, "NonStreamVIDD-Default" }, + { 0, NULL } +}; + +static const value_string pn_io_tsn_domain_port_config_preemption_enabled_vals[] = { + { 0x00, "Preemption support is disabled for this port" }, + { 0x01, "Preemption support is enabled for this port" }, + { 0, NULL } +}; + +static const value_string pn_io_tsn_domain_port_config_boundary_port_config_vals[] = { + { 0x00, "No boundary port" }, + { 0x01, "Boundary port with Remapping1" }, + { 0x02, "Boundary port with Remapping2" }, + { 0, NULL } +}; + +static const range_string pn_io_tsn_domain_port_ingress_rate_limiter_cir[] = { + { 0x0000, 0x0000, "No Boundary Port" }, + { 0x0001, 0xFFFF, "Committed information rate in 0,1 Mbit/s"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_port_ingress_rate_limiter_cbs[] = { + { 0x0000, 0x0000, "No Boundary Port" }, + { 0x0001, 0xFFFF, "Committed burst size in octets"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_port_ingress_rate_limiter_envelope[] = { + { 0x0000, 0x0000, "No Boundary Port" }, + { 0x0001, 0x0001, "Best effort envelope"}, + { 0x0002, 0x0002, "RT_CLASS_X, RTA_CLASS_X envelope"}, + { 0x0003, 0xFFFF, "Reserved"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_port_ingress_rate_limiter_rank[] = { + { 0x0000, 0x0000, "No Boundary Port" }, + { 0x0001, 0x0001, "CF1"}, + { 0x0002, 0x0002, "CF2"}, + { 0x0003, 0x0003, "CF3"}, + { 0x0004, 0x0004, "CF4"}, + { 0x0005, 0x0005, "CF5"}, + { 0x0006, 0xFFFF, "Reserved"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_queue_rate_limiter_cir[] = { + { 0x0000, 0x0000, "Used in case of no rate limiter" }, + { 0x0001, 0xFFFF, "Committed information rate in 0,1 Mbit/s"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_queue_rate_limiter_cbs[] = { + { 0x0000, 0x0000, "Used in case of no rate limiter" }, + { 0x0001, 0xFFFF, "Committed burst size in octets"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_queue_rate_limiter_envelope[] = { + { 0x00, 0x00, "Used in case of no rate limiter" }, + { 0x01, 0x01, "Best effort envelope"}, + { 0x02, 0xFF, "Reserved"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_queue_rate_limiter_rank[] = { + { 0x00, 0x00, "Used in case of no boundary port" }, + { 0x01, 0x01, "CF1"}, + { 0x02, 0x02, "CF2"}, + { 0x03, 0x03, "CF3"}, + { 0x04, 0x04, "CF4"}, + { 0x05, 0x05, "CF5"}, + { 0x06, 0xFF, "Reserved"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_queue_rate_limiter_queue_id[] = { + { 0x00, 0x07, "Identifier of the queue" }, + { 0x08, 0xFF, "Reserved"}, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_queue_rate_limiter_reserved[] = { + { 0x00, 0xFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const range_string pn_io_network_domain[] = { + { 0x00000000, 0x00000000, "No Deadline" }, + { 0x00000001, 0xFFFFFFFF, "The Deadline in Microseconds"}, + { 0, 0, NULL } +}; + +static const value_string pn_io_time_domain_number_vals[] = { + { 0x0000, "Global Time" }, + { 0x0001, "Global Time Redundant" }, + { 0x0020, "Working Clock" }, + { 0x0021, "Working Clock Redundant" }, + { 0, NULL } +}; + +static const value_string pn_io_time_pll_window_vals[] = { + { 0x00000000, "Disabled" }, + { 0x000003E8, "Default" }, + { 0x00002710, "Default" }, + { 0x000186A0, "Default" }, + { 0x000F4240, "Default" }, + { 0x00989680, "Default" }, + { 0, NULL } +}; + +static const value_string pn_io_message_interval_factor_vals[] = { + { 0x0000, "Reserved" }, + { 0x03E8, "Default" }, + { 0x0FA0, "Default" }, + { 0, NULL } +}; + +static const range_string pn_io_message_timeout_factor[] = { + { 0x0000, 0x0000, "Disabled" }, + { 0x0001, 0x0002, "Optional" }, + { 0x0003, 0x0005, "Mandatory" }, + { 0x0006, 0x0006, "Default, mandatory" }, + { 0x0007, 0x000F, "Mandatory" }, + { 0x0010, 0x01FF, "Optional" }, + { 0x0200, 0xFFFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const value_string pn_io_time_sync_properties_vals[] = { + { 0x00, "Reserved" }, + { 0x01, "External Sync" }, + { 0x02, "Internal Sync" }, + { 0x03, "Reserved" }, + { 0, NULL } +}; + +static const range_string pn_io_tsn_domain_queue_config_shaper[] = { + { 0x00, 0x00, "Reserved" }, + { 0x01, 0x01, "Strict Priority" }, + { 0x02, 0xFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_domain_sync_port_role_vals[] = { + { 0x00,0x00, "The port is not part of the sync tree for this sync domain" }, + { 0x01,0x01, "Sync egress port for this sync domain" }, + { 0x02,0x02, "Sync ingress port for this sync domain" }, + { 0x02,0XFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const value_string pn_io_tsn_fdb_command[] = { + { 0x01, "AddStreamEntry" }, + { 0x02, "RemoveStreamEntry" }, + { 0x03, "RemoveAllStreamEntries" }, + /* all others reserved */ + { 0, NULL } +}; + +static const range_string pn_io_tsn_transfer_time_tx_vals[] = { + { 0x00000000, 0x00000000, "Reserved" }, + { 0x00000001, 0x05F5E100, "Egress transfer time for the local interface of an endstation" }, + { 0x05F5E101, 0xFFFFFFFF, "Reserved" }, + { 0, 0, NULL } + +}; + +static const range_string pn_io_tsn_transfer_time_rx_vals[] = { + + { 0x00000000, 0x00000000, "Reserved" }, + { 0x00000001, 0x05F5E100, "Ingress transfer time for the local interface of an endstation" }, + { 0x05F5E101, 0xFFFFFFFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_max_supported_record_size_vals[] = { + { 0x00000000,0x00000FE3, "Reserved" }, + { 0x00000FE4,0x0000FFFF, "Describes the maximum supported size of RecordDataWrite." }, + {0x00010000,0xFFFFFFFF,"Reserved"}, + { 0, 0, NULL } +}; +static const range_string pn_io_tsn_forwarding_group_vals[] = { + { 0x00,0x00, "Reserved" }, + { 0x01,0xFF, "Identifier of logical port grouping. Identifies ports with equal forwarding delay values." }, + { 0, 0, NULL } +}; + +static const value_string pn_io_tsn_stream_class_vals[] = { + + /*other reserved */ + { 0x01, "High" }, + { 0x02, "High Redundant" }, + { 0x03, "Low" }, + { 0x04, "Low Redundant" }, + { 0, NULL } +}; + +static const range_string pn_io_tsn_independent_forwarding_delay_vals[] = { + + { 0x00000000, 0x00000000, "Reserved" }, + { 0x00000001, 0x000F4240, "Independent bridge delay value used for calculation" }, + { 0, 0, NULL } +}; + +static const range_string pn_io_tsn_dependent_forwarding_delay_vals[] = { + + { 0x00000000, 0x00000000, "Reserved" }, + { 0x00000001, 0x000C3500, "Octet size dependent bridge delay value used for calculation" }, + { 0, 0, NULL } +}; + +static const value_string pn_io_tsn_number_of_queues_vals[] = { + + { 0x06, "The bridge supports six transmit queues at the port" }, + { 0x08, "The bridge supports eight transmit queues at the port" }, + { 0, NULL } +}; + +static const value_string pn_io_tsn_port_capabilities_time_aware_vals[] = { + { 0x00, "This port is not usable within a Time Aware System"}, + { 0x01, "This port is usable within a Time Aware System" }, + { 0, NULL } +}; +static const value_string pn_io_tsn_port_capabilities_preemption_vals[] = { + { 0x00, "Preemption is not supported at this port" }, + { 0x01, "Preemption is supported at this port"}, + { 0, NULL } +}; + +static const value_string pn_io_tsn_port_capabilities_queue_masking_vals[] = { + { 0x00, "Queue Masking is not supported at this port"}, + { 0x01, "Queue Masking is supported at this port" }, + { 0, NULL } +}; + +/* Format of submodule ident number as per PA Profile 4.02 specification: + [VariantOfSubmodule, Block_object, Parent_Class, Class] */ +static const value_string pn_io_pa_profile_block_object_vals[] = { + { 0, "DAP" }, + { 1, "PB" }, + { 2, "FB" }, + { 3, "TB" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_dap_submodule_vals[] = { + { 1, "DAP" }, + { 2, "Device Management" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_physical_block_parent_class_vals[] = { + { 1, "Transmitter" }, + { 2, "Actuator" }, + { 3, "Discrete I/O" }, + { 4, "Controller" }, + { 5, "Analyzer" }, + { 6, "Lab Device" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_function_block_class_vals[] = { + { 1, "Input" }, + { 2, "Output" }, + { 3, "Further Input" }, + { 4, "Further Output" }, + { 128, "Manuf. specific Input" }, + { 129, "Manuf. specific Output" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_function_block_parent_class_vals[] = { + {0, "Analog Temperature" }, + {1, "Analog Temperature Difference"}, + {2, "Analog Average Temperature"}, + {3, "Analog Electronics Temperature"}, + {4, "Analog Transmitter Temperature"}, + {5, "Analog Sensor Temperature"}, + {6, "Analog Frame Temperature"}, + {7, "Analog Auxiliary Temperature"}, + {8, "Analog Energy Supply Temperature"}, + {9, "Analog Energy Return Temperature"}, + {20, "Analog Pressure"}, + {21, "Analog Absolute Pressure"}, + {22, "Analog Gauge Pressure"}, + {23, "Analog Differential Pressure"}, + {30, "Analog Level"}, + {31, "Analog Distance"}, + {32, "Analog Interface Level"}, + {33, "Analog Interface Distance"}, + {40, "Analog Volume"}, + {41, "Analog Ullage"}, + {42, "Analog Interface Volume"}, + {43, "Analog Standard Volume"}, + {44, "Analog Fraction Substance 1 Volume"}, + {45, "Analog Fraction Substance 2 Volume"}, + {46, "Analog Fraction Substance 1 Std Volume"}, + {47, "Analog Fraction Substance 2 Std Volume"}, + {50, "Analog Mass"}, + {51, "Analog Net Mass"}, + {52, "Analog Fraction Substance 1 Mass"}, + {53, "Analog Fraction Substance 2 Mass"}, + {60, "Analog Volume Flow"}, + {61, "Analog Standard Volume Flow"}, + {62, "Analog Fraction Substance 1 Volume Flow"}, + {63, "Analog Fraction Substance 2 Volume Flow"}, + {70, "Analog Mass Flow"}, + {71, "Analog Fraction Substance 1 Mass Flow"}, + {72, "Analog Fraction Substance 2 Mass Flow"}, + {80, "Analog Density"}, + {81, "Analog Standard Density"}, + {82, "Analog Analog Api Gravity"}, + {83, "Analog Standard Api Gravity"}, + {84, "Analog Specific Gravity"}, + {85, "Analog Standard Specific Gravity"}, + {90, "Analog Flow Velocity"}, + {91, "Analog Sound Velocity"}, + {92, "Analog Rate Of Change"}, + {100, "Analog Kinematic Viscosity"}, + {101, "Analog Dynamic Viscosity"}, + {110, "Analog Energy"}, + {111, "Analog Power"}, + {120, "Analog Vortex Frequency"}, + {130, "Analog Concentration"}, + {131, "Analog Energy Efficiency Rating"}, + {132, "Analog Coefficient Of Performance"}, + {133, "Analog Fraction Substance 1%"}, + {134, "Analog Fraction Substance 2%"}, + {140, "Analog pH"}, + {141, "Analog Conductivity"}, + {142, "Analog Resistivity"}, + {143, "Analog Gas Concentration"}, + {149, "Flexible AI"}, + {150, "Totalizer"}, + {160, "Actuator"}, + {170, "Discrete"}, + {180, "Enumerated"}, + {190, "Binary(8 Bit)"}, + {191, "Binary(16 Bit)"}, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_parent_class_vals[] = { + { 1, "Pressure" }, + { 2, "Temperature" }, + { 3, "Flow" }, + { 4, "Level" }, + { 5, "Actuator" }, + { 6, "Discrete I/O" }, + { 7, "Liquid analyzer" }, + { 8, "Gas analyzer" }, + { 10, "Enumerated I/O" }, + { 11, "Binary I/O" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_pressure_class_vals[] = { + { 1, "Pressure" }, + { 2, "Pressure + level" }, + { 3, "Pressure + flow" }, + { 4, "Pressure + level + flow" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_temperature_class_vals[] = { + { 1, "Thermocouple (TC)" }, + { 2, "Resistance thermometer (RTD)" }, + { 3, "Pyrometer" }, + { 16, "TC + DC U (DC Voltage)" }, + { 17, "RTD + R (R-Resistance)" }, + { 18, "TC+RTD+r+DC U" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_flow_class_vals[] = { + { 1, "Electromagnetic" }, + { 2, "Vortex" }, + { 3, "Coriolis" }, + { 4, "Thermal mass" }, + { 5, "Ultrasonic" }, + { 6, "Variable area" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_level_class_vals[] = { + { 1, "Hydrostatic" }, + { 2, "Ultrasonic" }, + { 3, "Radiometric" }, + { 4, "Capacitance" }, + { 5, "Displacer" }, + { 6, "Float" }, + { 7, "Radar" }, + { 8, "Buoyancy" }, + { 9, "Air bubble system" }, + { 10, "Gravimetric" }, + { 11, "Optical" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_actuator_class_vals[] = { + { 1, "Electric" }, + { 2, "Electro-pneumatic" }, + { 3, "Electro-hydraulic" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_discrete_io_class_vals[] = { + { 1, "Input" }, + { 2, "Output" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_liquid_analyzer_class_vals[] = { + { 1, "pH" }, + { 2, "Conductivity" }, + { 3, "Oxygen" }, + { 4, "Chlorine" }, + { 5, "Resistivity" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_gas_analyzer_class_vals[] = { + { 1, "Standard" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_enumerated_io_class_vals[] = { + { 1, "Input" }, + { 2, "Output" }, + { 0, NULL } +}; + +static const value_string pn_io_pa_profile_transducer_block_binary_io_class_vals[] = { + { 2, "8 Bit output" }, + { 3, "8 Bit input" }, + { 4, "16 Bit output" }, + { 5, "16 Bit input" }, + { 0, NULL } +}; + +static const value_string* pn_io_pa_profile_transducer_block_class_vals[] = { + NULL, + pn_io_pa_profile_transducer_block_pressure_class_vals, + pn_io_pa_profile_transducer_block_temperature_class_vals, + pn_io_pa_profile_transducer_block_flow_class_vals, + pn_io_pa_profile_transducer_block_level_class_vals, + pn_io_pa_profile_transducer_block_actuator_class_vals, + pn_io_pa_profile_transducer_block_discrete_io_class_vals, + pn_io_pa_profile_transducer_block_liquid_analyzer_class_vals, + pn_io_pa_profile_transducer_block_gas_analyzer_class_vals, + NULL, + pn_io_pa_profile_transducer_block_enumerated_io_class_vals, + pn_io_pa_profile_transducer_block_binary_io_class_vals +}; + +static const value_string pn_io_snmp_control[] = { + { 0x00, "Disable SNMP" }, + { 0x01, "Enable SNMP read only" }, + { 0x02, "Enable SNMP read/write" }, + { 0x03, "Reserved" }, + { 0, NULL } +}; + +static int +dissect_profidrive_value(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep, guint8 format_val) +{ + guint32 value32; + guint16 value16; + guint8 value8; + + switch(format_val) + { + case 1: + case 2: + case 5: + case 0x0A: + case 0x41: + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_profidrive_param_value_byte, &value8); + break; + case 3: + case 6: + case 0x42: + case 0x73: + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_profidrive_param_value_word, &value16); + break; + case 4: + case 7: + case 0x43: + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_profidrive_param_value_dword, &value32); + break; + case 8: + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_profidrive_param_value_float, &value32); + break; + case 9: + { + gint sLen; + sLen = (gint)tvb_strnlen( tvb, offset, -1); + proto_tree_add_item(tree, hf_pn_io_profidrive_param_value_string, tvb, offset, sLen, ENC_ASCII); + offset = (offset + sLen); + break; + } + default: + offset = offset + 1; + expert_add_info_format(pinfo, tree, &ei_pn_io_unsupported, "Not supported or invalid format %u!", format_val); + break; + } + return(offset); +} + +static GList *pnio_ars; + +typedef struct pnio_ar_s { + /* generic */ + e_guid_t aruuid; + guint16 inputframeid; + guint16 outputframeid; + + /* controller only */ + /*const char controllername[33];*/ + guint8 controllermac[6]; + guint16 controlleralarmref; + + /* device only */ + guint8 devicemac[6]; + guint16 devicealarmref; + guint16 arType; +} pnio_ar_t; + + + +static void +pnio_ar_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, pnio_ar_t *ar) +{ + p_add_proto_data(wmem_file_scope(), pinfo, proto_pn_io, 0, ar ); + p_add_proto_data(pinfo->pool, pinfo, proto_pn_io, 0, GUINT_TO_POINTER(10)); + + if (tree) { + proto_item *item; + proto_item *sub_item; + proto_tree *sub_tree; + address controllermac_addr, devicemac_addr; + + set_address(&controllermac_addr, AT_ETHER, 6, ar->controllermac); + set_address(&devicemac_addr, AT_ETHER, 6, ar->devicemac); + + sub_tree = proto_tree_add_subtree_format(tree, tvb, 0, 0, ett_pn_io_ar_info, &sub_item, + "ARUUID:%s ContrMAC:%s ContrAlRef:0x%x DevMAC:%s DevAlRef:0x%x InCR:0x%x OutCR=0x%x", + guid_to_str(pinfo->pool, (const e_guid_t*) &ar->aruuid), + address_to_str(pinfo->pool, &controllermac_addr), ar->controlleralarmref, + address_to_str(pinfo->pool, &devicemac_addr), ar->devicealarmref, + ar->inputframeid, ar->outputframeid); + proto_item_set_generated(sub_item); + + item = proto_tree_add_guid(sub_tree, hf_pn_io_ar_uuid, tvb, 0, 0, (e_guid_t *) &ar->aruuid); + proto_item_set_generated(item); + + item = proto_tree_add_ether(sub_tree, hf_pn_io_cminitiator_macadd, tvb, 0, 0, ar->controllermac); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_pn_io_localalarmref, tvb, 0, 0, ar->controlleralarmref); + proto_item_set_generated(item); + + item = proto_tree_add_ether(sub_tree, hf_pn_io_cmresponder_macadd, tvb, 0, 0, ar->devicemac); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_pn_io_localalarmref, tvb, 0, 0, ar->devicealarmref); + proto_item_set_generated(item); + + item = proto_tree_add_uint(sub_tree, hf_pn_io_frame_id, tvb, 0, 0, ar->inputframeid); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_pn_io_frame_id, tvb, 0, 0, ar->outputframeid); + proto_item_set_generated(item); + } +} + + + + +static int dissect_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index, guint32 *u32RecDataLen, pnio_ar_t **ar); + +static int dissect_a_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep); + +static int dissect_PNIO_IOxS(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, int hfindex); + + + + + +static pnio_ar_t * +pnio_ar_find_by_aruuid(packet_info *pinfo _U_, e_guid_t *aruuid) +{ + GList *ars; + pnio_ar_t *ar; + + + /* find pdev */ + for(ars = pnio_ars; ars != NULL; ars = g_list_next(ars)) { + ar = (pnio_ar_t *)ars->data; + + if (memcmp(&ar->aruuid, aruuid, sizeof(e_guid_t)) == 0) { + return ar; + } + } + + return NULL; +} + + +static pnio_ar_t * +pnio_ar_new(e_guid_t *aruuid) +{ + pnio_ar_t *ar; + + + ar = wmem_new0(wmem_file_scope(), pnio_ar_t); + + memcpy(&ar->aruuid, aruuid, sizeof(e_guid_t)); + + ar->controlleralarmref = 0xffff; + ar->devicealarmref = 0xffff; + + pnio_ars = g_list_append(pnio_ars, ar); + + return ar; +} + +/* dissect the alarm specifier */ +static int +dissect_Alarm_specifier(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16AlarmSpecifierSequence; + guint16 u16AlarmSpecifierChannel; + guint16 u16AlarmSpecifierManufacturer; + guint16 u16AlarmSpecifierSubmodule; + guint16 u16AlarmSpecifierAR; + proto_item *sub_item; + proto_tree *sub_tree; + + /* alarm specifier */ + sub_item = proto_tree_add_item(tree, hf_pn_io_alarm_specifier, tvb, offset, 2, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pdu_type); + + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_alarm_specifier_sequence, &u16AlarmSpecifierSequence); + u16AlarmSpecifierSequence &= 0x07FF; + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_alarm_specifier_channel, &u16AlarmSpecifierChannel); + u16AlarmSpecifierChannel = (u16AlarmSpecifierChannel &0x0800) >> 11; + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_alarm_specifier_manufacturer, &u16AlarmSpecifierManufacturer); + u16AlarmSpecifierManufacturer = (u16AlarmSpecifierManufacturer &0x1000) >> 12; + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_alarm_specifier_submodule, &u16AlarmSpecifierSubmodule); + u16AlarmSpecifierSubmodule = (u16AlarmSpecifierSubmodule & 0x2000) >> 13; + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_alarm_specifier_ardiagnosis, &u16AlarmSpecifierAR); + u16AlarmSpecifierAR = (u16AlarmSpecifierAR & 0x8000) >> 15; + + + proto_item_append_text(sub_item, ", Sequence: %u, Channel: %u, Manuf: %u, Submodule: %u AR: %u", + u16AlarmSpecifierSequence, u16AlarmSpecifierChannel, + u16AlarmSpecifierManufacturer, u16AlarmSpecifierSubmodule, u16AlarmSpecifierAR); + + return offset; +} + + +/* dissect the alarm header */ +static int +dissect_Alarm_header(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep) +{ + guint16 u16AlarmType; + guint32 u32Api; + guint16 u16SlotNr; + guint16 u16SubslotNr; + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_alarm_type, &u16AlarmType); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + proto_item_append_text(item, ", %s, API:%u, Slot:0x%x/0x%x", + val_to_str(u16AlarmType, pn_io_alarm_type, "(0x%x)"), + u32Api, u16SlotNr, u16SubslotNr); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", %s, Slot: 0x%x/0x%x", + val_to_str(u16AlarmType, pn_io_alarm_type, "(0x%x)"), + u16SlotNr, u16SubslotNr); + + return offset; +} + + +static int +dissect_ChannelProperties(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16ChannelProperties; + + + sub_item = proto_tree_add_item(tree, hf_pn_io_channel_properties, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_channel_properties); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_channel_properties_direction, &u16ChannelProperties); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_channel_properties_specifier, &u16ChannelProperties); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_channel_properties_maintenance, &u16ChannelProperties); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_channel_properties_accumulative, &u16ChannelProperties); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_channel_properties_type, &u16ChannelProperties); + + return offset; +} + +/* dissect the RS_BlockHeader */ +static int +dissect_RS_BlockHeader(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item, guint8 *drep, + guint16 *u16RSBodyLength, guint16 *u16RSBlockType) +{ + guint16 u16RSBlockLength; + guint8 u8BlockVersionHigh; + guint8 u8BlockVersionLow; + + /* u16RSBlockType is needed for further dissection */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rs_block_type, u16RSBlockType); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rs_block_length, &u16RSBlockLength); + + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_block_version_high, &u8BlockVersionHigh); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_block_version_low, &u8BlockVersionLow); + + proto_item_append_text(item, ": Type=%s, Length=%u(+4), Version=%u.%u", + rval_to_str(*u16RSBlockType, pn_io_rs_block_type, "Unknown (0x%04x)"), + u16RSBlockLength, u8BlockVersionHigh, u8BlockVersionLow); + + /* Block length is without type and length fields, but with version field */ + /* as it's already dissected, remove it */ + *u16RSBodyLength = u16RSBlockLength - 2; + + /* Padding 2 + 2 + 1 + 1 = 6 */ + /* Therefore we need 2 byte padding to make the block u32 aligned */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* remove padding */ + *u16RSBodyLength -= 2; + return offset; +} + +static int +dissect_RS_AddressInfo(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep, guint16 *u16RSBodyLength) +{ + e_guid_t IM_UniqueIdentifier; + guint32 u32Api; + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16ChannelNumber; + + /* IM_UniqueIdentifier */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ar_uuid, &IM_UniqueIdentifier); + *u16RSBodyLength -= 16; + + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + *u16RSBodyLength -= 4; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + *u16RSBodyLength -= 2; + + /* SubSlotNumber*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + *u16RSBodyLength -= 2; + + /* Channel Number*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_channel_number, &u16ChannelNumber); + *u16RSBodyLength -= 2; + + return offset; +} + +/* dissect the RS_EventDataCommon */ +static int +dissect_RS_EventDataCommon(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep, guint16 *u16RSBodyLength) +{ + guint16 u16RSSpecifierSequenceNumber; + guint16 u16RSSpecifierReserved; + guint16 u16RSSpecifierSpecifier; + guint16 u16RSMinorError; + guint16 u16RSPlusError; + proto_item *sub_item; + proto_tree *sub_tree; + proto_item *sub_item_time_stamp; + proto_tree *sub_tree_time_stamp; + nstime_t timestamp; + guint16 u16RSTimeStampStatus; + + /* RS_AddressInfo */ + offset = dissect_RS_AddressInfo(tvb, offset, pinfo, tree, drep, u16RSBodyLength); + + /* RS_Specifier */ + sub_item = proto_tree_add_item(tree, hf_pn_io_rs_specifier, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_rs_specifier); + + /* RS_Specifier.SequenceNumber */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_rs_specifier_sequence, &u16RSSpecifierSequenceNumber); + + /* RS_Specifier.Reserved */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_rs_specifier_reserved, &u16RSSpecifierReserved); + + /* RS_Specifier.Specifier */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_rs_specifier_specifier, &u16RSSpecifierSpecifier); + *u16RSBodyLength -= 2; + + /* RS_TimeStamp */ + sub_item_time_stamp = proto_tree_add_item(tree, hf_pn_io_rs_time_stamp, tvb, offset, 12, ENC_NA); + sub_tree_time_stamp = proto_item_add_subtree(sub_item_time_stamp, ett_pn_io_rs_time_stamp); + + /* RS_TimeStamp.Status */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree_time_stamp, drep, + hf_pn_io_rs_time_stamp_status, &u16RSTimeStampStatus); + + /* RS_TimeStamp.TimeStamp */ + + /* Start after from 2 bytes Status */ + timestamp.secs = (time_t)tvb_get_ntoh48(tvb, offset + 2); + + /* Start after from 4 bytes timestamp.secs */ + timestamp.nsecs = (int)tvb_get_ntohl(tvb, offset + 8); + + /* Start after from 2 bytes Status and get all 10 bytes */ + proto_tree_add_time(sub_tree_time_stamp, hf_pn_io_rs_time_stamp_value, tvb, offset + 2, 10, ×tamp); + *u16RSBodyLength -= 12; + offset += 12; + + /* RS_MinusError */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rs_minus_error, &u16RSMinorError); + *u16RSBodyLength -= 2; + + /* RS_PlusError */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rs_plus_error, &u16RSPlusError); + *u16RSBodyLength -= 2; + + return offset; +} + +/* dissect the RS_IdentificationInfo */ +static int +dissect_RS_IdentificationInfo(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + dcerpc_info di; /* fake dcerpc_info struct */ + dcerpc_call_value dcv; /* fake dcerpc_call_value struct */ + guint64 u64AMDeviceIdentificationDeviceSubID; + guint64 u64AMDeviceIdentificationDeviceID; + guint64 u64AMDeviceIdentificationVendorID; + guint64 u64AM_DeviceIdentificationOrganization; + + proto_item *sub_item; + proto_tree *sub_tree; + + di.call_data = &dcv; + + sub_item = proto_tree_add_item(tree, hf_pn_io_am_device_identification, tvb, offset, 8, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_am_device_identification); + + /* AM_DeviceIdentification */ + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_am_device_identification_device_sub_id, &u64AMDeviceIdentificationDeviceSubID); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_am_device_identification_device_id, &u64AMDeviceIdentificationDeviceID); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_am_device_identification_vendor_id, &u64AMDeviceIdentificationVendorID); + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_am_device_identification_organization, &u64AM_DeviceIdentificationOrganization); + + /* IM_Tag_Function [32] */ + proto_tree_add_item(tree, hf_pn_io_im_tag_function, tvb, offset, 32, ENC_ASCII); + offset += 32; + + /* IM_Tag_Location [22] */ + proto_tree_add_item(tree, hf_pn_io_im_tag_location, tvb, offset, 22, ENC_ASCII); + offset += 22; + + return offset; +} + +/* dissect the RS_EventDataExtension_Data */ +static int +dissect_RS_EventDataExtension_Data(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, + guint8 *u8RSExtensionBlockLength, guint16 *u16RSBlockType) +{ + guint32 u32RSReasonCodeReason; + guint32 u32RSReasonCodeDetail; + guint8 u8LengthRSDomainIdentification = 16; + guint8 u8LengthRSMasterIdentification = 8; + guint16 u16SoE_DigitalInputCurrentValueValue; + guint16 u16SoE_DigitalInputCurrentValueReserved; + + proto_item *sub_item; + proto_tree *sub_tree; + nstime_t timestamp; + guint16 u16RSTimeStampStatus; + proto_item *sub_item_time_stamp; + proto_tree *sub_tree_time_stamp; + + switch (*u16RSBlockType) { + case(0x4000): /* RS_StopObserver */ + + /* RS_BlockType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rs_block_type, u16RSBlockType); + + /* RS_ReasonCode */ + sub_item = proto_tree_add_item(tree, hf_pn_io_rs_reason_code, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_rs_reason_code); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_rs_reason_code_reason, &u32RSReasonCodeReason); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_rs_reason_code_detail, &u32RSReasonCodeDetail); + *u8RSExtensionBlockLength -= 6; + break; + case(0x4001): /* RS_BufferObserver */ + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, *u8RSExtensionBlockLength, "UserData"); + *u8RSExtensionBlockLength = 0; + break; + case(0x4002): /* RS_TimeStatus */ + + /* Padding 1 + 1 + 16 + 8 = 26 or 1 + 1 + 16 + 8 + 12 = 38 */ + /* Therefore we need 2 byte padding to make the block u32 aligned */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + *u8RSExtensionBlockLength -= 2; + + /* RS_DomainIdentification */ + proto_tree_add_item(tree, hf_pn_io_rs_domain_identification, tvb, offset, u8LengthRSDomainIdentification, ENC_NA); + offset += u8LengthRSDomainIdentification; + *u8RSExtensionBlockLength -= 16; + + /* RS_MasterIdentification */ + proto_tree_add_item(tree, hf_pn_io_rs_master_identification, tvb, offset, u8LengthRSMasterIdentification, ENC_NA); + offset += u8LengthRSMasterIdentification; + *u8RSExtensionBlockLength -= 8; + + if (*u8RSExtensionBlockLength > 2) + { + /* RS_TimeStamp */ + sub_item_time_stamp = proto_tree_add_item(tree, hf_pn_io_rs_time_stamp, tvb, offset, 12, ENC_NA); + sub_tree_time_stamp = proto_item_add_subtree(sub_item_time_stamp, ett_pn_io_rs_time_stamp); + + /* RS_TimeStamp.Status */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree_time_stamp, drep, + hf_pn_io_rs_time_stamp_status, &u16RSTimeStampStatus); + + /* RS_TimeStamp.TimeStamp */ + timestamp.secs = (time_t)tvb_get_ntoh48(tvb, offset + 2); // Start after from 2 bytes Status + timestamp.nsecs = (int)tvb_get_ntohl(tvb, offset + 8); // Start after from 4 bytes timestamp.secs + // Start after from 2 bytes Status and get all 10 bytes + proto_tree_add_time(sub_tree_time_stamp, hf_pn_io_rs_time_stamp_value, tvb, offset + 2, 10, ×tamp); + offset += 12; + } + break; + case(0x4003): /* RS_SRLObserver */ + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, *u8RSExtensionBlockLength, "UserData"); + *u8RSExtensionBlockLength = 0; + break; + case(0x4004): /* RS_SourceIdentification */ + offset = dissect_RS_IdentificationInfo(tvb, offset, pinfo, tree, drep); + *u8RSExtensionBlockLength = 0; + break; + case(0x4010): /* SoE_DigitalInputObserver */ + /* SoE_DigitalInputCurrentValue */ + sub_item = proto_tree_add_item(tree, hf_pn_io_soe_digital_input_current_value, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_soe_digital_input_current_value); + + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_soe_digital_input_current_value_value, &u16SoE_DigitalInputCurrentValueValue); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_soe_digital_input_current_value_reserved, &u16SoE_DigitalInputCurrentValueReserved); + *u8RSExtensionBlockLength -= 2; + break; + default: + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, *u8RSExtensionBlockLength, "UserData"); + *u8RSExtensionBlockLength = 0; + break; + } + return offset; +} + +/* dissect the RS_EventDataExtension */ +static int +dissect_RS_EventDataExtension(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint8 *drep, guint16 *u16RSBlockLength, guint16 *u16RSBlockType) +{ + guint8 u8RSExtensionBlockType; + guint8 u8RSExtensionBlockLength; + + /* RS_ExtensionBlockType */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_rs_extension_block_type, &u8RSExtensionBlockType); + *u16RSBlockLength -= 1; + + /* RS_ExtensionBlockLength */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_rs_extension_block_length, &u8RSExtensionBlockLength); + *u16RSBlockLength -= 1; + + /* Data*[Padding] * a*/ + while (u8RSExtensionBlockLength) { + *u16RSBlockLength -= u8RSExtensionBlockLength; + offset = dissect_RS_EventDataExtension_Data(tvb, offset, pinfo, tree, drep, + &u8RSExtensionBlockLength, u16RSBlockType); + } + + return offset; +} + +/* dissect the RS_EventData */ +static int +dissect_RS_EventData(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep, + guint16 *u16RSBodyLength, guint16 *u16RSBlockType) +{ + proto_item *sub_item; + proto_tree *sub_tree; + + /* RS_EventDataCommon */ + offset = dissect_RS_EventDataCommon(tvb, offset, pinfo, tree, drep, u16RSBodyLength); + + /* optional: RS_EventDataExtension */ + while (*u16RSBodyLength > 0) { + sub_item = proto_tree_add_item(tree, hf_pn_io_rs_event_data_extension, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_rs_event_data_extension); + offset = dissect_RS_EventDataExtension(tvb, offset, pinfo, sub_tree, drep, + u16RSBodyLength, u16RSBlockType); + } + + return offset; +} + +/* dissect the RS_EventBlock */ +static int +dissect_RS_EventBlock(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + + guint16 u16RSBodyLength; + guint16 u16RSBlockType; + + sub_item = proto_tree_add_item(tree, hf_pn_io_rs_event_block, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_rs_event_block); + + /* RS_BlockHeader */ + offset = dissect_RS_BlockHeader(tvb, offset, pinfo, sub_tree, sub_item, drep, + &u16RSBodyLength, &u16RSBlockType); + + /* RS_EventData */ + offset = dissect_RS_EventData(tvb, offset, pinfo, sub_tree, drep, + &u16RSBodyLength, &u16RSBlockType); + return offset; +} + +/* dissect the RS_AlarmInfo */ +static int +dissect_RS_AlarmInfo(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16RSAlarmInfo; + + sub_item = proto_tree_add_item(tree, hf_pn_io_rs_alarm_info, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_rs_alarm_info); + + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_rs_alarm_info_reserved_0_7, &u16RSAlarmInfo); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_rs_alarm_info_reserved_8_15, &u16RSAlarmInfo); + + return offset; +} + +/* dissect the RS_EventInfo */ +static int +dissect_RS_EventInfo(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16NumberofEntries; + + sub_item = proto_tree_add_item(tree, hf_pn_io_rs_event_info, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_rs_event_info); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_number_of_rs_event_info, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + offset = dissect_RS_EventBlock(tvb, offset, pinfo, sub_tree, drep); + } + return offset; +} + +static int +dissect_Diagnosis(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, proto_item *item, guint8 *drep, guint16 u16UserStructureIdentifier) +{ + guint16 u16ChannelNumber; + guint16 u16ChannelErrorType; + guint16 u16ExtChannelErrorType; + guint32 u32ExtChannelAddValue; + guint32 u32QualifiedChannelQualifier; + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_channel_number, &u16ChannelNumber); + + offset = dissect_ChannelProperties(tvb, offset, pinfo, tree, item, drep); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_channel_error_type, &u16ChannelErrorType); + + if (u16UserStructureIdentifier == 0x8000) /* ChannelDiagnosisData */ + { + return offset; + } + + if (u16ChannelErrorType < 0x7fff) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x8000) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8000, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x8001) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8001, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x8002) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8002, &u16ExtChannelErrorType); + } + else if ((u16ChannelErrorType == 0x8003)||(u16ChannelErrorType == 0x8009)) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8003, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x8004) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8004, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x8005) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8005, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x8007) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8007, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x8008) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8008, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x800A) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x800A, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x800B) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x800B, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x800C) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x800C, &u16ExtChannelErrorType); + } + else if (u16ChannelErrorType == 0x8010) + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type0x8010, &u16ExtChannelErrorType); + } + else + { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_error_type, &u16ExtChannelErrorType); + } + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_ext_channel_add_value, &u32ExtChannelAddValue); + + if (u16UserStructureIdentifier == 0x8002) /* ExtChannelDiagnosisData */ + { + return offset; + } + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_qualified_channel_qualifier, &u32QualifiedChannelQualifier); + + /* QualifiedChannelDiagnosisData */ + return offset; +} + +static int +dissect_AlarmUserStructure(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, + guint16 *body_length, guint16 u16UserStructureIdentifier) +{ + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + + switch (u16UserStructureIdentifier) { + case(0x8000): /* ChannelDiagnosisData */ + offset = dissect_Diagnosis(tvb, offset, pinfo, tree, item, drep, + u16UserStructureIdentifier); + *body_length -= 6; + break; + case(0x8002): /* ExtChannelDiagnosisData */ + offset = dissect_Diagnosis(tvb, offset, pinfo, tree, item, drep, + u16UserStructureIdentifier); + *body_length -= 12; + break; + case (0x8003): /* QualifiedChannelDiagnosisData */ + offset = dissect_Diagnosis(tvb, offset, pinfo, tree, item, drep, + u16UserStructureIdentifier); + *body_length -= 16; + break; + case(0x8100): /* MaintenanceItem */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + *body_length -= 12; + break; + case(0x8300): /* RS_AlarmInfo (Reporting System Alarm Information) */ + case(0x8301): /* RS_AlarmInfo */ + case(0x8302): /* RS_AlarmInfo */ + offset = dissect_RS_AlarmInfo(tvb, offset, pinfo, tree, drep); + *body_length = 0; + break; + case(0x8303): /* RS_EventInfo (Reporting System Event Information) */ + offset = dissect_RS_EventInfo(tvb, offset, pinfo, tree, drep); + *body_length = 0; + break; + case(0x8310): /* PE_EnergySavingStatus */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + *body_length = 0; + break; + /* XXX - dissect remaining user structures of [AlarmItem] */ + case(0x8001): /* DiagnosisData */ + default: + if (u16UserStructureIdentifier >= 0x8000) { + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, *body_length); + } else { + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, *body_length, "UserData"); + } + + *body_length = 0; + } + + return offset; +} + + + +/* dissect the alarm notification block */ +static int +dissect_AlarmNotification_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 body_length) +{ + guint32 u32ModuleIdentNumber; + guint32 u32SubmoduleIdentNumber; + guint16 u16UserStructureIdentifier; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_Alarm_header(tvb, offset, pinfo, tree, item, drep); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_module_ident_number, &u32ModuleIdentNumber); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber); + + offset = dissect_Alarm_specifier(tvb, offset, pinfo, tree, drep); + + proto_item_append_text(item, ", Ident:0x%x, SubIdent:0x%x", + u32ModuleIdentNumber, u32SubmoduleIdentNumber); + + body_length -= 20; + + /* the rest of the block contains optional: [MaintenanceItem] and/or [AlarmItem] */ + while (body_length) { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_user_structure_identifier, &u16UserStructureIdentifier); + proto_item_append_text(item, ", USI:0x%x", u16UserStructureIdentifier); + body_length -= 2; + + offset = dissect_AlarmUserStructure(tvb, offset, pinfo, tree, item, drep, &body_length, u16UserStructureIdentifier); + } + + return offset; +} + + +static int +dissect_IandM0_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint8 u8VendorIDHigh; + guint8 u8VendorIDLow; + guint16 u16IMHardwareRevision; + guint8 u8SWRevisionPrefix; + guint8 u8IMSWRevisionFunctionalEnhancement; + guint8 u8IMSWRevisionBugFix; + guint8 u8IMSWRevisionInternalChange; + guint16 u16IMRevisionCounter; + guint16 u16IMProfileID; + guint16 u16IMProfileSpecificType; + guint8 u8IMVersionMajor; + guint8 u8IMVersionMinor; + guint16 u16IMSupported; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* x8 VendorIDHigh */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_vendor_id_high, &u8VendorIDHigh); + /* x8 VendorIDLow */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_vendor_id_low, &u8VendorIDLow); + /* c8[20] OrderID */ + proto_tree_add_item (tree, hf_pn_io_order_id, tvb, offset, 20, ENC_ASCII); + offset += 20; + + /* c8[16] IM_Serial_Number */ + proto_tree_add_item (tree, hf_pn_io_im_serial_number, tvb, offset, 16, ENC_ASCII); + offset += 16; + + /* x16 IM_Hardware_Revision */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_hardware_revision, &u16IMHardwareRevision); + /* c8 SWRevisionPrefix */ + offset = dissect_dcerpc_char(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_revision_prefix, &u8SWRevisionPrefix); + /* x8 IM_SWRevision_Functional_Enhancement */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_sw_revision_functional_enhancement, &u8IMSWRevisionFunctionalEnhancement); + /* x8 IM_SWRevision_Bug_Fix */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_revision_bugfix, &u8IMSWRevisionBugFix); + /* x8 IM_SWRevision_Internal_Change */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_sw_revision_internal_change, &u8IMSWRevisionInternalChange); + /* x16 IM_Revision_Counter */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_revision_counter, &u16IMRevisionCounter); + /* x16 IM_Profile_ID */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_profile_id, &u16IMProfileID); + /* x16 IM_Profile_Specific_Type */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_profile_specific_type, &u16IMProfileSpecificType); + /* x8 IM_Version_Major (values) */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_version_major, &u8IMVersionMajor); + /* x8 IM_Version_Minor (values) */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_version_minor, &u8IMVersionMinor); + /* x16 IM_Supported (bitfield) */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_supported, &u16IMSupported); + + return offset; +} + + +static int +dissect_IandM1_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + char *pTagFunction; + char *pTagLocation; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* IM_Tag_Function [32] */ + proto_tree_add_item_ret_display_string (tree, hf_pn_io_im_tag_function, tvb, offset, 32, ENC_ASCII, pinfo->pool, &pTagFunction); + offset += 32; + + /* IM_Tag_Location [22] */ + proto_tree_add_item_ret_display_string (tree, hf_pn_io_im_tag_location, tvb, offset, 22, ENC_ASCII, pinfo->pool, &pTagLocation); + offset += 22; + + proto_item_append_text(item, ": TagFunction:\"%s\", TagLocation:\"%s\"", pTagFunction, pTagLocation); + + return offset; +} + + +static int +dissect_IandM2_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + char *pDate; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* IM_Date [16] */ + proto_tree_add_item_ret_display_string (tree, hf_pn_io_im_date, tvb, offset, 16, ENC_ASCII, pinfo->pool, &pDate); + offset += 16; + + proto_item_append_text(item, ": Date:\"%s\"", pDate); + + return offset; +} + + +static int +dissect_IandM3_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + char *pDescriptor; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* IM_Descriptor [54] */ + proto_tree_add_item_ret_display_string (tree, hf_pn_io_im_descriptor, tvb, offset, 54, ENC_ASCII, pinfo->pool, &pDescriptor); + offset += 54; + + proto_item_append_text(item, ": Descriptor:\"%s\"", pDescriptor); + + return offset; +} + + +static int +dissect_IandM4_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + dissect_pn_user_data(tvb, offset, pinfo, tree, 54, "IM Signature"); + + return offset; +} + +static int +dissect_IandM5_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberofEntries; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_im_numberofentries, &u16NumberofEntries); + + while(u16NumberofEntries > 0) { + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + u16NumberofEntries--; + } + return offset; +} + +static int +dissect_IandM0FilterData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberOfAPIs; + guint32 u32Api; + guint16 u16NumberOfModules; + guint16 u16SlotNr; + guint32 u32ModuleIdentNumber; + guint16 u16NumberOfSubmodules; + guint16 u16SubslotNr; + guint32 u32SubmoduleIdentNumber; + proto_item *subslot_item; + proto_tree *subslot_tree; + proto_item *module_item; + proto_tree *module_tree; + guint32 u32ModuleStart; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* NumberOfAPIs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + + while (u16NumberOfAPIs--) { + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + /* NumberOfModules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_modules, &u16NumberOfModules); + + while (u16NumberOfModules--) { + module_item = proto_tree_add_item(tree, hf_pn_io_subslot, tvb, offset, 6, ENC_NA); + module_tree = proto_item_add_subtree(module_item, ett_pn_io_module); + + u32ModuleStart = offset; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* ModuleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_module_ident_number, &u32ModuleIdentNumber); + /* NumberOfSubmodules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_number_of_submodules, &u16NumberOfSubmodules); + + proto_item_append_text(module_item, ": Slot:%u, Ident:0x%x Submodules:%u", + u16SlotNr, u32ModuleIdentNumber, u16NumberOfSubmodules); + + while (u16NumberOfSubmodules--) { + subslot_item = proto_tree_add_item(module_tree, hf_pn_io_subslot, tvb, offset, 6, ENC_NA); + subslot_tree = proto_item_add_subtree(subslot_item, ett_pn_io_subslot); + + /* SubslotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, subslot_tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* SubmoduleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, subslot_tree, drep, + hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber); + + proto_item_append_text(subslot_item, ": Number:0x%x, Ident:0x%x", + u16SubslotNr, u32SubmoduleIdentNumber); + } + + proto_item_set_len(module_item, offset-u32ModuleStart); + } + } + + return offset; +} + + +static int +dissect_IandM5Data_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep) +{ + guint8 u8VendorIDHigh; + guint8 u8VendorIDLow; + guint16 u16IMHardwareRevision; + guint8 u8SWRevisionPrefix; + guint8 u8IMSWRevisionFunctionalEnhancement; + guint8 u8IMSWRevisionBugFix; + guint8 u8IMSWRevisionInternalChange; + + /* c8[64] IM Annotation */ + proto_tree_add_item(tree, hf_pn_io_im_annotation, tvb, offset, 64, ENC_ASCII); + offset += 64; + + /* c8[64] IM Order ID */ + proto_tree_add_item(tree, hf_pn_io_im_order_id, tvb, offset, 64, ENC_ASCII); + offset += 64; + + /* x8 VendorIDHigh */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_vendor_id_high, &u8VendorIDHigh); + /* x8 VendorIDLow */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_vendor_id_low, &u8VendorIDLow); + + /* c8[16] IM Serial Number */ + proto_tree_add_item(tree, hf_pn_io_im_serial_number, tvb, offset, 16, ENC_ASCII); + offset += 16; + + /* x16 IM_Hardware_Revision */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_hardware_revision, &u16IMHardwareRevision); + /* c8 SWRevisionPrefix */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_revision_prefix, &u8SWRevisionPrefix); + /* x8 IM_SWRevision_Functional_Enhancement */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_sw_revision_functional_enhancement, &u8IMSWRevisionFunctionalEnhancement); + /* x8 IM_SWRevision_Bug_Fix */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_revision_bugfix, &u8IMSWRevisionBugFix); + + /* x8 IM_SWRevision_Internal_Change */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_sw_revision_internal_change, &u8IMSWRevisionInternalChange); + + return offset; +} + +static int +dissect_AM_Location(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint8 am_location_structtype; + int bit_offset; + guint8 am_location_reserved1; + guint16 am_location_begin_slot_number; + guint16 am_location_begin_subslot_number; + guint16 am_location_end_slot_number; + guint16 am_location_end_subslot_number; + guint16 am_location_reserved2; + guint16 am_location_reserved3; + guint16 am_location_reserved4; + + sub_item = proto_tree_add_item(tree, hf_pn_io_am_location, tvb, offset, 16, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_am_location); + + am_location_structtype = tvb_get_guint8(tvb, offset+15); + bit_offset = offset << 3; + + switch (am_location_structtype) + { + case (0x01): + + /* level 11 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_11, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 10 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_10, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 9 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_9, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 8 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_8, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 7 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_7, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 6 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_6, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 5 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_5, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 4 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_4, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 3 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_3, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 2 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_2, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 1 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_1, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 0 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_level_0, tvb, bit_offset, 10, ENC_BIG_ENDIAN); + bit_offset += 10; + + /* level 0 */ + proto_tree_add_bits_item(sub_tree, hf_pn_io_am_location_structure, tvb, bit_offset, 8, ENC_BIG_ENDIAN); + + offset += 16; + + break; + case (0x02): + /* Reserved 4 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_reserved4, &am_location_reserved4); + + /* Reserved 3 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_reserved3, &am_location_reserved3); + + /* Reserved 2 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_reserved2, &am_location_reserved2); + + /* EndSubSlotNumber*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_endsubslotnum, &am_location_end_subslot_number); + + /* EndSlotNumber*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_endslotnum, &am_location_end_slot_number); + + /* BeginSubslotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_beginsubslotnum, &am_location_begin_subslot_number); + + /* BeginSlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_beginslotnum, &am_location_begin_slot_number); + + /* Reserved1 */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_reserved1, &am_location_reserved1); + + /* Structure */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_am_location_structure, &am_location_structtype); + + break; + default: /* will not execute because of the line preceding the switch */ + offset += 16; + break; + } + + return offset; +} + +static int +dissect_IM_software_revision(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint8 u8SWRevisionPrefix; + guint8 u8IMSWRevisionFunctionalEnhancement; + guint8 u8IMSWRevisionBugFix; + guint8 u8IMSWRevisionInternalChange; + + /* SWRevisionPrefix */ + offset = dissect_dcerpc_char(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_revision_prefix, &u8SWRevisionPrefix); + + /* IM_SWRevision_Functional_Enhancement */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_sw_revision_functional_enhancement, &u8IMSWRevisionFunctionalEnhancement); + + /* IM_SWRevision_Bug_Fix */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_revision_bugfix, &u8IMSWRevisionBugFix); + + /* IM_SWRevision_Internal_Change */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_sw_revision_internal_change, &u8IMSWRevisionInternalChange); + + return offset; +} + +static int +dissect_AM_device_identification(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + dcerpc_info di; /* fake dcerpc_info struct */ + dcerpc_call_value dcv; /* fake dcerpc_call_value struct */ + guint64 u64AMDeviceIdentificationDeviceSubID; + guint64 u64AMDeviceIdentificationDeviceID; + guint64 u64AMDeviceIdentificationVendorID; + guint64 u64AM_DeviceIdentificationOrganization; + + proto_item *sub_item; + proto_tree *sub_tree; + + di.call_data = &dcv; + + sub_item = proto_tree_add_item(tree, hf_pn_io_am_device_identification, tvb, offset, 8, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_am_device_identification); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_am_device_identification_device_sub_id, &u64AMDeviceIdentificationDeviceSubID); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_am_device_identification_device_id, &u64AMDeviceIdentificationDeviceID); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_am_device_identification_vendor_id, &u64AMDeviceIdentificationVendorID); + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_am_device_identification_organization, &u64AM_DeviceIdentificationOrganization); + + return offset; +} + +static int +dissect_AM_FullInformation_block(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, +guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + e_guid_t IM_UniqueIdentifier; + guint16 u16AM_TypeIdentification; + guint16 u16IMHardwareRevision; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* align padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* IM_UniqueIdentifier */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_uniqueidentifier, &IM_UniqueIdentifier); + + /* AM_Location */ + offset = dissect_AM_Location(tvb, offset, pinfo, tree, drep); + + /* IM_Annotation */ + proto_tree_add_item(tree, hf_pn_io_im_annotation, tvb, offset, 64, ENC_ASCII); + offset += 64; + + /* IM_OrderID */ + proto_tree_add_item(tree, hf_pn_io_im_order_id, tvb, offset, 64, ENC_ASCII); + offset += 64; + + /* AM_SoftwareRevision */ + proto_tree_add_item(tree, hf_pn_io_am_software_revision, tvb, offset, 64, ENC_ASCII); + offset += 64; + + /* AM_HardwareRevision */ + proto_tree_add_item(tree, hf_pn_io_am_hardware_revision, tvb, offset, 64, ENC_ASCII); + offset += 64; + + /* IM_Serial_Number */ + proto_tree_add_item(tree, hf_pn_io_im_serial_number, tvb, offset, 16, ENC_ASCII); + offset += 16; + + /* IM_Software_Revision */ + offset = dissect_IM_software_revision(tvb, offset, pinfo, tree, drep); + + /* AM_DeviceIdentification */ + offset = dissect_AM_device_identification(tvb, offset, pinfo, tree, drep); + + /* AM_TypeIdentification */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_am_type_identification, &u16AM_TypeIdentification); + + /* IM_Hardware_Revision */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_hardware_revision, &u16IMHardwareRevision); + + return offset; +} + +static int +dissect_AM_HardwareOnlyInformation_block(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, +guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + e_guid_t IM_UniqueIdentifier; + guint16 u16AM_TypeIdentification; + guint16 u16IMHardwareRevision; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* align padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* IM_UniqueIdentifier */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_uniqueidentifier, &IM_UniqueIdentifier); + + /* AM_Location */ + offset = dissect_AM_Location(tvb, offset, pinfo, tree, drep); + + /* IM_Annotation */ + proto_tree_add_item(tree, hf_pn_io_im_annotation, tvb, offset, 64, ENC_ASCII | ENC_NA); + offset += 64; + + /* IM_OrderID */ + proto_tree_add_item(tree, hf_pn_io_im_order_id, tvb, offset, 64, ENC_ASCII | ENC_NA); + offset += 64; + + /* AM_HardwareRevision */ + proto_tree_add_item(tree, hf_pn_io_am_hardware_revision, tvb, offset, 64, ENC_ASCII | ENC_NA); + offset += 64; + + /* IM_Serial_Number */ + proto_tree_add_item(tree, hf_pn_io_im_serial_number, tvb, offset, 16, ENC_ASCII | ENC_NA); + offset += 16; + + /* AM_DeviceIdentification */ + offset = dissect_AM_device_identification(tvb, offset, pinfo, tree, drep); + + /* AM_TypeIdentification */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_am_type_identification, &u16AM_TypeIdentification); + + /* IM_Hardware_Revision */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_hardware_revision, &u16IMHardwareRevision); + + return offset; +} + +static int +dissect_AM_FirmwareOnlyInformation_block(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, +guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + e_guid_t IM_UniqueIdentifier; + guint16 u16AM_TypeIdentification; + guint16 u16AM_Reserved; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* IM_UniqueIdentifier */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_im_uniqueidentifier, &IM_UniqueIdentifier); + + /* AM_Location */ + offset = dissect_AM_Location(tvb, offset, pinfo, tree, drep); + + /* IM_Annotation */ + proto_tree_add_item(tree, hf_pn_io_im_annotation, tvb, offset, 64, ENC_ASCII | ENC_NA); + offset += 64; + + /* IM_OrderID */ + proto_tree_add_item(tree, hf_pn_io_im_order_id, tvb, offset, 64, ENC_ASCII | ENC_NA); + offset += 64; + + /* AM_SoftwareRevision */ + proto_tree_add_item(tree, hf_pn_io_am_software_revision, tvb, offset, 64, ENC_ASCII | ENC_NA); + offset += 64; + + /* IM_Serial_Number */ + proto_tree_add_item(tree, hf_pn_io_im_serial_number, tvb, offset, 16, ENC_ASCII | ENC_NA); + offset += 16; + + /* IM_Software_Revision */ + offset = dissect_IM_software_revision(tvb, offset, pinfo, tree, drep); + + /* AM_DeviceIdentification */ + offset = dissect_AM_device_identification(tvb, offset, pinfo, tree, drep); + + /* AM_TypeIdentification */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_am_type_identification, &u16AM_TypeIdentification); + + /* AM_Reserved */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_am_reserved, &u16AM_Reserved); + + return offset; +} + +/* dissect the AssetManagementInfo */ +static int +dissect_AssetManagementInfo(tvbuff_t *tvb, int offset, +packet_info *pinfo _U_, proto_tree *tree, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16NumberofEntries; + + sub_item = proto_tree_add_item(tree, hf_pn_io_asset_management_info, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_asset_management_info); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_number_of_asset_management_info, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + offset = dissect_a_block(tvb, offset, pinfo, sub_tree, drep); + } + return offset; +} + +/* dissect the AssetManagementData block */ +static int +dissect_AssetManagementData_block(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, +guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + offset = dissect_AssetManagementInfo(tvb, offset, pinfo, tree, drep); + return offset; +} + +/* dissect the IdentificationData block */ +static int +dissect_IdentificationData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberOfAPIs = 1; + guint32 u32Api; + guint16 u16NumberOfSlots; + guint16 u16SlotNr; + guint32 u32ModuleIdentNumber; + guint16 u16NumberOfSubslots; + guint32 u32SubmoduleIdentNumber; + guint16 u16SubslotNr; + proto_item *slot_item; + proto_tree *slot_tree; + guint32 u32SlotStart; + proto_item *subslot_item; + proto_tree *subslot_tree; + + + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + if (u8BlockVersionLow == 1) { + /* NumberOfAPIs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + } + + proto_item_append_text(item, ": APIs:%u", u16NumberOfAPIs); + + while (u16NumberOfAPIs--) { + if (u8BlockVersionLow == 1) { + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + } + + /* NumberOfSlots */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_slots, &u16NumberOfSlots); + + proto_item_append_text(item, ", Slots:%u", u16NumberOfSlots); + + while (u16NumberOfSlots--) { + slot_item = proto_tree_add_item(tree, hf_pn_io_slot, tvb, offset, 0, ENC_NA); + slot_tree = proto_item_add_subtree(slot_item, ett_pn_io_slot); + u32SlotStart = offset; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, slot_tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* ModuleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, slot_tree, drep, + hf_pn_io_module_ident_number, &u32ModuleIdentNumber); + /* NumberOfSubslots */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, slot_tree, drep, + hf_pn_io_number_of_subslots, &u16NumberOfSubslots); + + proto_item_append_text(slot_item, ": SlotNr:%u Ident:0x%x Subslots:%u", + u16SlotNr, u32ModuleIdentNumber, u16NumberOfSubslots); + + while (u16NumberOfSubslots--) { + subslot_item = proto_tree_add_item(slot_tree, hf_pn_io_subslot, tvb, offset, 6, ENC_NA); + subslot_tree = proto_item_add_subtree(subslot_item, ett_pn_io_subslot); + + /* SubslotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, subslot_tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* SubmoduleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, subslot_tree, drep, + hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber); + + proto_item_append_text(subslot_item, ": Number:0x%x, Ident:0x%x", + u16SubslotNr, u32SubmoduleIdentNumber); + } + + proto_item_set_len(slot_item, offset-u32SlotStart); + } + } + + return offset; +} + + +/* dissect the substitute value block */ +static int +dissect_SubstituteValue_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint16 u16SubstitutionMode; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* SubstitutionMode */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_substitutionmode, &u16SubstitutionMode); + + + /* SubstituteDataItem */ + /* IOCS */ + offset = dissect_PNIO_IOxS(tvb, offset, pinfo, tree, drep, hf_pn_io_iocs); + u16BodyLength -= 3; + /* SubstituteDataObjectElement */ + dissect_pn_user_data_bytes(tvb, offset, pinfo, tree, u16BodyLength, SUBST_DATA); + + return offset; +} + + +/* dissect the RecordInputDataObjectElement block */ +static int +dissect_RecordInputDataObjectElement_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint8 u8LengthIOCS; + guint8 u8LengthIOPS; + guint16 u16LengthData; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* LengthIOCS */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_iocs, &u8LengthIOCS); + /* IOCS */ + offset = dissect_PNIO_IOxS(tvb, offset, pinfo, tree, drep, hf_pn_io_iocs); + /* LengthIOPS */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_iops, &u8LengthIOPS); + /* IOPS */ + offset = dissect_PNIO_IOxS(tvb, offset, pinfo, tree, drep, hf_pn_io_iops); + /* LengthData */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_data, &u16LengthData); + /* Data */ + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, u16LengthData, "Data"); + + return offset; +} + + +/* dissect the RecordOutputDataObjectElement block */ +static int +dissect_RecordOutputDataObjectElement_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16SubstituteActiveFlag; + guint8 u8LengthIOCS; + guint8 u8LengthIOPS; + guint16 u16LengthData; + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* SubstituteActiveFlag */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_substitute_active_flag, &u16SubstituteActiveFlag); + + /* LengthIOCS */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_iocs, &u8LengthIOCS); + /* LengthIOPS */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_iops, &u8LengthIOPS); + /* LengthData */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_data, &u16LengthData); + /* DataItem (IOCS, Data, IOPS) */ + offset = dissect_PNIO_IOxS(tvb, offset, pinfo, tree, drep, hf_pn_io_iocs); + + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, u16LengthData, "Data"); + + offset = dissect_PNIO_IOxS(tvb, offset, pinfo, tree, drep, hf_pn_io_iops); + + /* SubstituteValue */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + + return offset; +} + + +/* dissect the alarm acknowledge block */ +static int +dissect_Alarm_ack_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + col_append_str(pinfo->cinfo, COL_INFO, ", Alarm Ack"); + + offset = dissect_Alarm_header(tvb, offset, pinfo, tree, item, drep); + + offset = dissect_Alarm_specifier(tvb, offset, pinfo, tree, drep); + + offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep); + + return offset; +} + + +/* dissect the maintenance block */ +static int +dissect_Maintenance_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32MaintenanceStatus; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + sub_item = proto_tree_add_item(tree, hf_pn_io_maintenance_status, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_maintenance_status); + + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_maintenance_status_demanded, &u32MaintenanceStatus); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_maintenance_status_required, &u32MaintenanceStatus); + + if (u32MaintenanceStatus & 0x0002) { + proto_item_append_text(item, ", Demanded"); + proto_item_append_text(sub_item, ", Demanded"); + } + + if (u32MaintenanceStatus & 0x0001) { + proto_item_append_text(item, ", Required"); + proto_item_append_text(sub_item, ", Required"); + } + + return offset; +} + +/* dissect the pe_alarm block */ +static int +dissect_PE_Alarm_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint8 u8PEOperationalMode; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + sub_item = proto_tree_add_item(tree, hf_pn_io_pe_operational_mode, tvb, offset, 1, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pe_operational_mode); + + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pe_operational_mode, &u8PEOperationalMode); + + return offset; + +} + +/* dissect the read/write header */ +static int +dissect_ReadWrite_header(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint16 *u16Index, e_guid_t *aruuid) +{ + guint32 u32Api; + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16SeqNr; + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_seq_number, &u16SeqNr); + + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ar_uuid, aruuid); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* padding doesn't match offset required for align4 */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_index, u16Index); + + proto_item_append_text(item, ": Seq:%u, Api:0x%x, Slot:0x%x/0x%x", + u16SeqNr, u32Api, u16SlotNr, u16SubslotNr); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", Api:0x%x, Slot:0x%x/0x%x, Index:%s", + u32Api, u16SlotNr, u16SubslotNr, + val_to_str(*u16Index, pn_io_index, "(0x%x)")); + + return offset; +} + + +/* dissect the write request block */ +static int +dissect_IODWriteReqHeader_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 *u16Index, guint32 *u32RecDataLen, pnio_ar_t ** ar) +{ + e_guid_t aruuid; + e_guid_t null_uuid; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_ReadWrite_header(tvb, offset, pinfo, tree, item, drep, u16Index, &aruuid); + + /* The value NIL indicates the usage of the implicit AR*/ + *ar = pnio_ar_find_by_aruuid(pinfo, &aruuid); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_record_data_length, u32RecDataLen); + + memset(&null_uuid, 0, sizeof(e_guid_t)); + if (memcmp(&aruuid, &null_uuid, sizeof (e_guid_t)) == 0) { + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_target_ar_uuid, &aruuid); + } + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 24); + + proto_item_append_text(item, ", Len:%u", *u32RecDataLen); + + if (*u32RecDataLen != 0) + col_append_fstr(pinfo->cinfo, COL_INFO, ", %u bytes", + *u32RecDataLen); + + return offset; +} + + +/* dissect the read request block */ +static int +dissect_IODReadReqHeader_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 *u16Index, guint32 *u32RecDataLen, pnio_ar_t **ar) +{ + e_guid_t aruuid; + e_guid_t null_uuid; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_ReadWrite_header(tvb, offset, pinfo, tree, item, drep, u16Index, &aruuid); + + /* The value NIL indicates the usage of the implicit AR*/ + *ar = pnio_ar_find_by_aruuid(pinfo, &aruuid); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_record_data_length, u32RecDataLen); + + memset(&null_uuid, 0, sizeof(e_guid_t)); + if (memcmp(&aruuid, &null_uuid, sizeof (e_guid_t)) == 0) { + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_target_ar_uuid, &aruuid); + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 8); + } else { + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 24); + } + + proto_item_append_text(item, ", Len:%u", *u32RecDataLen); + + if (*u32RecDataLen != 0) + col_append_fstr(pinfo->cinfo, COL_INFO, ", %u bytes", + *u32RecDataLen); + + return offset; +} + + +/* dissect the write response block */ +static int +dissect_IODWriteResHeader_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 *u16Index, guint32 *u32RecDataLen, pnio_ar_t **ar) +{ + e_guid_t aruuid; + guint16 u16AddVal1; + guint16 u16AddVal2; + guint32 u32Status; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_ReadWrite_header(tvb, offset, pinfo, tree, item, drep, u16Index, &aruuid); + + /* The value NIL indicates the usage of the implicit AR*/ + *ar = pnio_ar_find_by_aruuid(pinfo, &aruuid); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_record_data_length, u32RecDataLen); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_add_val1, &u16AddVal1); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_add_val2, &u16AddVal2); + + u32Status = ((drep[0] & DREP_LITTLE_ENDIAN) + ? tvb_get_letohl (tvb, offset) + : tvb_get_ntohl (tvb, offset)); + + offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep); + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 16); + + proto_item_append_text(item, ", Len:%u, Index:0x%x, Status:0x%x, Val1:%u, Val2:%u", + *u32RecDataLen, *u16Index, u32Status, u16AddVal1, u16AddVal2); + + if (*u32RecDataLen != 0) + col_append_fstr(pinfo->cinfo, COL_INFO, ", %u bytes", + *u32RecDataLen); + + return offset; +} + + +/* dissect the read response block */ +static int +dissect_IODReadResHeader_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 *u16Index, guint32 *u32RecDataLen, pnio_ar_t **ar) +{ + e_guid_t aruuid; + guint16 u16AddVal1; + guint16 u16AddVal2; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_ReadWrite_header(tvb, offset, pinfo, tree, item, drep, u16Index, &aruuid); + + /* The value NIL indicates the usage of the implicit AR*/ + *ar = pnio_ar_find_by_aruuid(pinfo, &aruuid); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_record_data_length, u32RecDataLen); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_add_val1, &u16AddVal1); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_add_val2, &u16AddVal2); + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 20); + + proto_item_append_text(item, ", Len:%u, AddVal1:%u, AddVal2:%u", + *u32RecDataLen, u16AddVal1, u16AddVal2); + + if (*u32RecDataLen != 0) + col_append_fstr(pinfo->cinfo, COL_INFO, ", %u bytes", + *u32RecDataLen); + + return offset; +} + + +/* dissect the control/connect and control/connect block */ +static int +dissect_ControlPlugOrConnect_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + pnio_ar_t **ar, guint16 blocktype) +{ + e_guid_t ar_uuid; + guint16 u16SessionKey; + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16Command; + guint16 u16Properties; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_reserved16, NULL); + + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ar_uuid, &ar_uuid); + + /* The value NIL indicates the usage of the implicit AR*/ + *ar = pnio_ar_find_by_aruuid(pinfo, &ar_uuid); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_sessionkey, &u16SessionKey); + + if (((blocktype & 0x7FFF) == 0x0111) || ((blocktype & 0x7FFF) == 0x0113)) { + /* control/plug */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_control_alarm_sequence_number, NULL); + } else { + /* control/connect */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_reserved16, NULL); + } + + sub_item = proto_tree_add_item(tree, hf_pn_io_control_command, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_control_command); + + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_prmend, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_applready, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_release, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_done, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_ready_for_companion, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_ready_for_rt_class3, &u16Command); + /* Prm.Begin */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_prmbegin, &u16Command); + + if (u16Command & 0x0002) { + /* ApplicationReady: special decode */ + sub_item = proto_tree_add_item(tree, hf_pn_io_control_block_properties_applready, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_control_block_properties); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_control_block_properties_applready_bit0, &u16Properties); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_control_block_properties_applready_bit1, &u16Properties); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_control_block_properties_applready_otherbits, &u16Properties); + } else { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_control_block_properties, &u16Properties); + } + + proto_item_append_text(item, ": Session:%u, Command:", u16SessionKey); + + if (u16Command & 0x0001) { + proto_item_append_text(sub_item, ", ParameterEnd"); + proto_item_append_text(item, " ParameterEnd"); + col_append_str(pinfo->cinfo, COL_INFO, ", Command: ParameterEnd"); + } + if (u16Command & 0x0002) { + proto_item_append_text(sub_item, ", ApplicationReady"); + proto_item_append_text(item, " ApplicationReady"); + col_append_str(pinfo->cinfo, COL_INFO, ", Command: ApplicationReady"); + } + if (u16Command & 0x0004) { + proto_item_append_text(sub_item, ", Release"); + proto_item_append_text(item, " Release"); + col_append_str(pinfo->cinfo, COL_INFO, ", Command: Release"); + } + if (u16Command & 0x0008) { + proto_item_append_text(sub_item, ", Done"); + proto_item_append_text(item, ", Done"); + col_append_str(pinfo->cinfo, COL_INFO, ", Command: Done"); + + /* When Release Command Done, keep the release frame of corresponding ar & ar uuid */ + if (!PINFO_FD_VISITED(pinfo) && blocktype == 0x8114) { + + wmem_list_frame_t* aruuid_frame; + ARUUIDFrame* current_aruuid_frame = NULL; + + if (aruuid_frame_setup_list != NULL) { + for (aruuid_frame = wmem_list_head(aruuid_frame_setup_list); aruuid_frame != NULL; aruuid_frame = wmem_list_frame_next(aruuid_frame)) { + current_aruuid_frame = (ARUUIDFrame*)wmem_list_frame_data(aruuid_frame); + if (current_aruuid_frame->aruuid.data1 == ar_uuid.data1) { + current_aruuid_frame->releaseframe = pinfo->num; + } + } + } + } + } + + proto_item_append_text(item, ", Properties:0x%x", u16Properties); + + return offset; +} + +/* dissect the ControlBlockPrmBegin block */ +static int +dissect_ControlBlockPrmBegin(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint32 u32RecDataLen, + pnio_ar_t **ar) +{ + e_guid_t ar_uuid; + guint16 u16SessionKey; + guint16 u16Command; + proto_item *sub_item; + proto_tree *sub_tree; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + if (u32RecDataLen != 28-2) /* must be 28 see specification (version already dissected) */ + { + expert_add_info_format(pinfo, item, &ei_pn_io_block_length, "Block length of %u is invalid!", u32RecDataLen); + return offset; + } + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* ARUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, hf_pn_io_ar_uuid, &ar_uuid); + + if (!PINFO_FD_VISITED(pinfo)) { + pn_init_append_aruuid_frame_setup_list(ar_uuid, pinfo->num); + } + + /* The value NIL indicates the usage of the implicit AR*/ + *ar = pnio_ar_find_by_aruuid(pinfo, &ar_uuid); + + /* SessionKey */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_sessionkey, &u16SessionKey); + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* ControlCommand */ + sub_item = proto_tree_add_item(tree, hf_pn_io_control_command, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_control_command); + + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_prmend, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_applready, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_release, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_done, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_ready_for_companion, &u16Command); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_ready_for_rt_class3, &u16Command); + /* Prm.Begin */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_prmbegin, &u16Command); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_control_command_reserved_7_15, &u16Command); + + /* ControlBlockProperties.reserved */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_control_command_reserved, NULL); + return offset; +} + +/* dissect the SubmoduleListBlock block */ +static int +dissect_SubmoduleListBlock(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint32 u32RecDataLen _U_, + pnio_ar_t **ar _U_) +{ + guint16 u16Entries; + guint32 u32API; + guint16 u16SlotNumber; + guint16 u16SubSlotNumber; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_SubmoduleListEntries, &u16Entries); + + while (u16Entries --) + { + /*API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_api, &u32API); + /*SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_slot_nr, &u16SlotNumber); + /* SubSlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_subslot_nr, &u16SubSlotNumber); + } + return offset; +} + + +/* dissect the PDevData block */ +static int +dissect_PDevData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + offset = dissect_blocks(tvb, offset, pinfo, tree, drep); + + return offset; +} + +/* dissect the AdjustPreambleLength block */ +static int +dissect_AdjustPreambleLength_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16AdjustProperties; + guint16 u16PreambleLength; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* PreambleLength */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_PreambleLength, &u16PreambleLength); + + + /* AdjustProperties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + + return offset; +} + +/* dissect the dissect_CheckMAUTypeExtension_block block */ +static int +dissect_CheckMAUTypeExtension_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16MauTypeExtension; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* MauTypeExtension */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_mau_type_extension, &u16MauTypeExtension); + + return offset; +} + +/* dissect the PDPortDataAdjust block */ +static int +dissect_PDPortData_Adjust_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint16 u16SlotNr; + guint16 u16SubslotNr; + tvbuff_t *new_tvb; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + proto_item_append_text(item, ": Slot:0x%x/0x%x", u16SlotNr, u16SubslotNr); + + u16BodyLength -= 6; + + new_tvb = tvb_new_subset_length(tvb, offset, u16BodyLength); + dissect_blocks(new_tvb, 0, pinfo, tree, drep); + offset += u16BodyLength; + + /* XXX - do we have to free the new_tvb somehow? */ + + return offset; +} + + +/* dissect the PDPortDataCheck blocks */ +static int +dissect_PDPortData_Check_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint16 u16SlotNr; + guint16 u16SubslotNr; + tvbuff_t *new_tvb; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + proto_item_append_text(item, ": Slot:0x%x/0x%x", u16SlotNr, u16SubslotNr); + + u16BodyLength -= 6; + + new_tvb = tvb_new_subset_length(tvb, offset, u16BodyLength); + dissect_blocks(new_tvb, 0, pinfo, tree, drep); + offset += u16BodyLength; + + /* XXX - do we have to free the new_tvb somehow? */ + + return offset; +} + +/* dissect the Line Delay */ +static int +dissect_Line_Delay(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, guint8 *drep, + guint32 *u32LineDelayValue) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32FormatIndicator; + guint8 isFormatIndicatorEnabled; + + sub_item = proto_tree_add_item(tree, hf_pn_io_line_delay, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_line_delay); + + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_line_delay_format_indicator, &u32FormatIndicator); + + isFormatIndicatorEnabled = (guint8)((u32FormatIndicator >> 31) & 0x01); + if (isFormatIndicatorEnabled) + { + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_cable_delay_value, u32LineDelayValue); + } + else + { + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_line_delay_value, u32LineDelayValue); + } + + return offset; +} + +/* dissect the PDPortDataReal blocks */ +static int +dissect_PDPortDataReal_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint8 u8LengthOwnPortID; + char *pOwnPortID; + proto_item *sub_item; + proto_tree *sub_tree; + guint8 u8NumberOfPeers; + guint8 u8I; + guint8 u8LengthPeerPortID; + guint8 u8LengthPeerChassisID; + guint8 mac[6]; + char *pPeerChassisId; + char *pPeerPortId; + guint16 u16MAUType; + guint32 u32DomainBoundary; + guint32 u32MulticastBoundary; + guint8 u8LinkStatePort; + guint8 u8LinkStateLink; + guint32 u32MediaType; + guint32 u32LineDelayValue; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + /* LengthOwnPortID */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_own_port_id, &u8LengthOwnPortID); + /* OwnPortID */ + proto_tree_add_item_ret_display_string (tree, hf_pn_io_own_port_id, tvb, offset, u8LengthOwnPortID, ENC_ASCII, pinfo->pool, &pOwnPortID); + offset += u8LengthOwnPortID; + + /* NumberOfPeers */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_peers, &u8NumberOfPeers); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + u8I = u8NumberOfPeers; + while (u8I--) { + sub_item = proto_tree_add_item(tree, hf_pn_io_neighbor, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_neighbor); + + /* LengthPeerPortID */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_length_peer_port_id, &u8LengthPeerPortID); + /* PeerPortID */ + proto_tree_add_item_ret_display_string (sub_tree, hf_pn_io_peer_port_id, tvb, offset, u8LengthPeerPortID, + ENC_ASCII, pinfo->pool, &pPeerPortId); + + offset += u8LengthPeerPortID; + + /* LengthPeerChassisID */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_length_peer_chassis_id, &u8LengthPeerChassisID); + /* PeerChassisID */ + proto_tree_add_item_ret_display_string (sub_tree, hf_pn_io_peer_chassis_id, tvb, offset, u8LengthPeerChassisID, + ENC_ASCII, pinfo->pool, &pPeerChassisId); + + offset += u8LengthPeerChassisID; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, sub_tree); + + /* LineDelay */ + offset = dissect_Line_Delay(tvb, offset, pinfo, sub_tree, drep, &u32LineDelayValue); + + /* PeerMACAddress */ + offset = dissect_pn_mac(tvb, offset, pinfo, sub_tree, + hf_pn_io_peer_macadd, mac); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, sub_tree); + + proto_item_append_text(sub_item, ": %s (%s)", pPeerChassisId, pPeerPortId); + } + + /* MAUType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mau_type, &u16MAUType); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* DomainBoundary */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_domain_boundary, &u32DomainBoundary); + /* MulticastBoundary */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_multicast_boundary, &u32MulticastBoundary); + /* LinkState.Port */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_link_state_port, &u8LinkStatePort); + /* LinkState.Link */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_link_state_link, &u8LinkStateLink); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MediaType */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_media_type, &u32MediaType); + + proto_item_append_text(item, ": Slot:0x%x/0x%x, OwnPortID:%s, Peers:%u LinkState.Port:%s LinkState.Link:%s MediaType:%s", + u16SlotNr, u16SubslotNr, pOwnPortID, u8NumberOfPeers, + val_to_str(u8LinkStatePort, pn_io_link_state_port, "0x%x"), + val_to_str(u8LinkStateLink, pn_io_link_state_link, "0x%x"), + val_to_str(u32MediaType, pn_io_media_type, "0x%x")); + + return offset; +} + + +/* dissect the PDPortDataRealExtended blocks */ +static int +dissect_PDPortDataRealExtended_block(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, + proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BodyLength) +{ + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + int endoffset = offset + u16BodyLength; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + proto_item_append_text(item, ": Slot:0x%x/0x%x", u16SlotNr, u16SubslotNr); + + while (endoffset > offset) { + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + u16Index++; + } + + return offset; +} + +static int +dissect_PDInterfaceMrpDataAdjust_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BodyLength) +{ + e_guid_t uuid; + guint16 u16Role; + guint8 u8LengthDomainName; + guint8 u8NumberOfMrpInstances; + int endoffset = offset + u16BodyLength; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow > 1) { /* added low version == 1 */ + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + if (u8BlockVersionLow == 0) /*dissect LowVersion == 0 */ + { + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MRP_DomainUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_domain_uuid, &uuid); + /* MRP_Role */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_role, &u16Role); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MRP_LengthDomainName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_length_domain_name, &u8LengthDomainName); + /* MRP_DomainName */ + /* XXX - IEC 61158-6-10 Edition 4.0 says, in section 5.2.17.2.4 "Coding + of the field MRP_DomainName", that "This field shall be coded as + data type OctetString with 1 to 240 octets according to Table 702 + and 4.3.1.4.15.2." + + It then says, in subsection 4.3.1.4.15.2 "Encoding" of section + 4.3.1.4.15 "Coding of the field NameOfStationValue", that "This + field shall be coded as data type OctetString with 1 to 240 + octets. The definition of IETF RFC 5890 and the following syntax + applies: ..." + + RFC 5890 means Punycode; should we translate the domain name to + UTF-8 and show both the untranslated and translated domain name? + + They don't mention anything about the RFC 1035 encoding of + domain names as mentioned in section 3.1 "Name space definitions", + with the labels being counted strings; does that mean that this + is just an ASCII string to be interpreted as a Punycode Unicode + domain name? */ + proto_tree_add_item (tree, hf_pn_io_mrp_domain_name, tvb, offset, u8LengthDomainName, ENC_ASCII); + offset += u8LengthDomainName; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + while (endoffset > offset) + { + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + } + } + else if (u8BlockVersionLow == 1) /*dissect LowVersion == 1 */ + { + /* Padding one byte */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + /* Number of Mrp Instances */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_instances, &u8NumberOfMrpInstances); + if (u8NumberOfMrpInstances > 0xf) { + expert_add_info_format(pinfo, item, &ei_pn_io_mrp_instances, "Number of MrpInstances greater 0x0f is (0x%x)", u8NumberOfMrpInstances); + return offset; + } + while(u8NumberOfMrpInstances > 0) + { + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + u8NumberOfMrpInstances--; + } + } + return offset; +} + + +static int +dissect_PDInterfaceMrpDataReal_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BodyLength) +{ + e_guid_t uuid; + guint16 u16Role; + guint16 u16Version; + guint8 u8LengthDomainName; + guint8 u8NumberOfMrpInstances; + int endoffset = offset + u16BodyLength; + + /* added blockversion 1 */ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow > 2) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + if (u8BlockVersionLow < 2) /* dissect low versions 0 and 1 */ + { + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MRP_DomainUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_domain_uuid, &uuid); + /* MRP_Role */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_role, &u16Role); + + if (u8BlockVersionLow == 1) { + /* MRP_Version */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_version, &u16Version); + } + /* MRP_LengthDomainName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_length_domain_name, &u8LengthDomainName); + /* MRP_DomainName */ + /* XXX - see comment earlier about MRP_DomainName */ + proto_tree_add_item (tree, hf_pn_io_mrp_domain_name, tvb, offset, u8LengthDomainName, ENC_ASCII); + offset += u8LengthDomainName; + + if (u8BlockVersionLow == 0) { + /* MRP_Version */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_version, &u16Version); + } + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + while(endoffset > offset) + { + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + } + } + else if (u8BlockVersionLow == 2) + { + /* Padding one byte */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + /* Number of Mrp Instances */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_instances, &u8NumberOfMrpInstances); + if (u8NumberOfMrpInstances > 0xf) { + expert_add_info_format(pinfo, item, &ei_pn_io_mrp_instances, "Number of MrpInstances greater 0x0f is (0x%x)", u8NumberOfMrpInstances); + return offset; + } + while(u8NumberOfMrpInstances > 0) + { + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + u8NumberOfMrpInstances--; + } + } + return offset; +} + + +static int +dissect_PDInterfaceMrpDataCheck_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + e_guid_t uuid; + guint32 u32Check; + guint8 u8NumberOfMrpInstances; + + /* BlockVersionLow == 1 added */ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow > 1) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + if (u8BlockVersionLow == 0) + { + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MRP_DomainUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_domain_uuid, &uuid); + + /* MRP_Check */ + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check, &u32Check); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check_mrm, &u32Check); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check_mrpdomain, &u32Check); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check_reserved_1, &u32Check); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check_reserved_2, &u32Check); + offset +=4; /* MRP_Check (32 bit) done */ + } + else if (u8BlockVersionLow == 1) + { + /* Padding one byte */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + /* Number of Mrp Instances */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_instances, &u8NumberOfMrpInstances); + if (u8NumberOfMrpInstances > 0xf) { + expert_add_info_format(pinfo, item, &ei_pn_io_mrp_instances, "Number of MrpInstances greater 0x0f is (0x%x)", u8NumberOfMrpInstances); + return offset; + } + while(u8NumberOfMrpInstances > 0) + { + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + u8NumberOfMrpInstances--; + } + } + + return offset; +} + + +static int +dissect_PDPortMrpData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + e_guid_t uuid; + guint8 u8MrpInstance; + + /* added BlockVersionLow == 1 */ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow > 1) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + if (u8BlockVersionLow == 0) { + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + } + else /*if (u8BlockVersionLow == 1) */ + { + /* Padding one byte */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + /* Mrp Instance */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_instance, &u8MrpInstance); + } + /* MRP_DomainUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_domain_uuid, &uuid); + return offset; +} + + +static int +dissect_MrpManagerParams_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16Prio; + guint16 u16TOPchgT; + guint16 u16TOPNRmax; + guint16 u16TSTshortT; + guint16 u16TSTdefaultT; + guint16 u16TSTNRmax; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* MRP_Prio */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_prio, &u16Prio); + /* MRP_TOPchgT */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_topchgt, &u16TOPchgT); + /* MRP_TOPNRmax */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_topnrmax, &u16TOPNRmax); + /* MRP_TSTshortT */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_tstshortt, &u16TSTshortT); + /* MRP_TSTdefaultT */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_tstdefaultt, &u16TSTdefaultT); + /* MSP_TSTNRmax */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_tstnrmax, &u16TSTNRmax); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + return offset; +} + + +static int +dissect_MrpRTMode(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32RTMode; + + + /* MRP_RTMode */ + sub_item = proto_tree_add_item(tree, hf_pn_io_mrp_rtmode, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_mrp_rtmode); + + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_mrp_rtmode_reserved2, &u32RTMode); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_mrp_rtmode_reserved1, &u32RTMode); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_mrp_rtmode_rtclass3, &u32RTMode); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_mrp_rtmode_rtclass12, &u32RTMode); + + return offset; +} + + +static int +dissect_MrpRTModeManagerData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16TSTNRmax; + guint16 u16TSTdefaultT; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* MSP_TSTNRmax */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_tstnrmax, &u16TSTNRmax); + /* MRP_TSTdefaultT */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_tstdefaultt, &u16TSTdefaultT); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MRP_RTMode */ + offset = dissect_MrpRTMode(tvb, offset, pinfo, tree, item, drep); + + return offset; +} + + +static int +dissect_MrpRingStateData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16RingState; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* MRP_RingState */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_ring_state, &u16RingState); + + return offset; +} + + +static int +dissect_MrpRTStateData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16RTState; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* MRP_RTState */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_rt_state, &u16RTState); + + return offset; +} + + +static int +dissect_MrpClientParams_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16MRP_LNKdownT; + guint16 u16MRP_LNKupT; + guint16 u16MRP_LNKNRmax; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* MRP_LNKdownT */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_lnkdownt, &u16MRP_LNKdownT); + /* MRP_LNKupT */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_lnkupt, &u16MRP_LNKupT); + /* MRP_LNKNRmax u16 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_lnknrmax, &u16MRP_LNKNRmax); + + return offset; +} + + +static int +dissect_MrpRTModeClientData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* MRP_RTMode */ + offset = dissect_MrpRTMode(tvb, offset, pinfo, tree, item, drep); + + return offset; +} + + +static int +dissect_CheckSyncDifference_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16CheckSyncMode; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + sub_item = proto_tree_add_item(tree, hf_pn_io_check_sync_mode, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_check_sync_mode); + + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_check_sync_mode_reserved, &u16CheckSyncMode); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_check_sync_mode_sync_master, &u16CheckSyncMode); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_check_sync_mode_cable_delay, &u16CheckSyncMode); + + + proto_item_append_text(sub_item, "CheckSyncMode: SyncMaster:%d, CableDelay:%d", + (u16CheckSyncMode >> 1) & 1, u16CheckSyncMode & 1); + + proto_item_append_text(item, " : SyncMaster:%d, CableDelay:%d", + (u16CheckSyncMode >> 1) & 1, u16CheckSyncMode & 1); + + return offset; +} + + +static int +dissect_CheckMAUTypeDifference_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16MAUTypeMode; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mau_type_mode, &u16MAUTypeMode); + + proto_item_append_text(item, ": MAUTypeMode:%s", + val_to_str(u16MAUTypeMode, pn_io_mau_type_mode, "0x%x")); + + return offset; +} + + +/* dissect the AdjustDomainBoundary blocks */ +static int +dissect_AdjustDomainBoundary_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32DomainBoundary; + guint32 u32DomainBoundaryIngress; + guint32 u32DomainBoundaryEgress; + guint16 u16AdjustProperties; + + + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + switch (u8BlockVersionLow) { + case(0): + /* DomainBoundary */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_domain_boundary, &u32DomainBoundary); + /* AdjustProperties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + proto_item_append_text(item, ": Boundary:0x%x, Properties:0x%x", + u32DomainBoundary, u16AdjustProperties); + + break; + case(1): + /* DomainBoundaryIngress */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_domain_boundary_ingress, &u32DomainBoundaryIngress); + /* DomainBoundaryEgress */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_domain_boundary_egress, &u32DomainBoundaryEgress); + /* AdjustProperties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + proto_item_append_text(item, ": BoundaryIngress:0x%x, BoundaryEgress:0x%x, Properties:0x%x", + u32DomainBoundaryIngress, u32DomainBoundaryEgress, u16AdjustProperties); + + break; + default: + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + return offset; +} + + +/* dissect the AdjustMulticastBoundary blocks */ +static int +dissect_AdjustMulticastBoundary_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32MulticastBoundary; + guint16 u16AdjustProperties; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* Boundary */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_multicast_boundary, &u32MulticastBoundary); + /* AdjustProperties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + + proto_item_append_text(item, ": Boundary:0x%x, Properties:0x%x", + u32MulticastBoundary, u16AdjustProperties); + + return offset; +} + + +/* dissect the AdjustMAUType block */ +static int +dissect_AdjustMAUType_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16MAUType; + guint16 u16AdjustProperties; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MAUType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mau_type, &u16MAUType); + /* AdjustProperties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + + proto_item_append_text(item, ": MAUType:%s, Properties:0x%x", + val_to_str(u16MAUType, pn_io_mau_type, "0x%x"), + u16AdjustProperties); + + return offset; +} + + +/* dissect the CheckMAUType block */ +static int +dissect_CheckMAUType_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16MAUType; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* MAUType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mau_type, &u16MAUType); + + proto_item_append_text(item, ": MAUType:%s", + val_to_str(u16MAUType, pn_io_mau_type, "0x%x")); + + return offset; +} + + +/* dissect the CheckLineDelay block */ +static int +dissect_CheckLineDelay_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32LineDelay; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* LineDelay */ + offset = dissect_Line_Delay(tvb, offset, pinfo, tree, drep, &u32LineDelay); + + proto_item_append_text(item, ": LineDelay:%uns", u32LineDelay); + + return offset; +} + + +/* dissect the CheckPeers block */ +static int +dissect_CheckPeers_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint8 u8NumberOfPeers; + guint8 u8I; + guint8 u8LengthPeerPortID; + guint8 u8LengthPeerChassisID; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* NumberOfPeers */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_peers, &u8NumberOfPeers); + + u8I = u8NumberOfPeers; + while (u8I--) { + /* LengthPeerPortID */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_peer_port_id, &u8LengthPeerPortID); + /* PeerPortID */ + proto_tree_add_item (tree, hf_pn_io_peer_port_id, tvb, offset, u8LengthPeerPortID, ENC_ASCII); + offset += u8LengthPeerPortID; + + /* LengthPeerChassisID */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_peer_chassis_id, &u8LengthPeerChassisID); + /* PeerChassisID */ + proto_tree_add_item (tree, hf_pn_io_peer_chassis_id, tvb, offset, u8LengthPeerChassisID, ENC_ASCII); + offset += u8LengthPeerChassisID; + } + + proto_item_append_text(item, ": NumberOfPeers:%u", u8NumberOfPeers); + + return offset; +} + + +/* dissect the AdjustPortState block */ +static int +dissect_AdjustPortState_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16PortState; + guint16 u16AdjustProperties; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* PortState */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_port_state, &u16PortState); + /* AdjustProperties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + + proto_item_append_text(item, ": PortState:%s, Properties:0x%x", + val_to_str(u16PortState, pn_io_port_state, "0x%x"), + u16AdjustProperties); + + return offset; +} + + +/* dissect the CheckPortState block */ +static int +dissect_CheckPortState_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16PortState; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* PortState */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_port_state, &u16PortState); + + proto_item_append_text(item, ": %s", + val_to_str(u16PortState, pn_io_port_state, "0x%x")); + return offset; +} + + +/* dissect the PDPortFODataReal block */ +static int +dissect_PDPortFODataReal_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint32 u32FiberOpticType; + guint32 u32FiberOpticCableType; + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* FiberOpticType */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fiber_optic_type, &u32FiberOpticType); + + /* FiberOpticCableType */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fiber_optic_cable_type, &u32FiberOpticCableType); + + /* optional: FiberOpticManufacturerSpecific */ + if (u16BodyLength != 10) { + dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + } + + return offset; +} + + +/* dissect the FiberOpticManufacturerSpecific block */ +static int +dissect_FiberOpticManufacturerSpecific_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint8 u8VendorIDHigh; + guint8 u8VendorIDLow; + guint16 u16VendorBlockType; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* x8 VendorIDHigh */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_vendor_id_high, &u8VendorIDHigh); + /* x8 VendorIDLow */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_vendor_id_low, &u8VendorIDLow); + + /* VendorBlockType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_vendor_block_type, &u16VendorBlockType); + /* Data */ + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, u16BodyLength-4, "Data"); + + return offset; +} + + +/* dissect the FiberOpticDiagnosisInfo block */ +static int +dissect_FiberOpticDiagnosisInfo_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32FiberOpticPowerBudget; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* decode the u32FiberOpticPowerBudget better */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_maintenance_required_power_budget, &u32FiberOpticPowerBudget); + + return offset; +} + +/* dissect the AdjustMAUTypeExtension block */ +static int +dissect_AdjustMAUTypeExtension_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16MauTypeExtension; + guint16 u16AdjustProperties; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MauTypeExtension */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_mau_type_extension, &u16MauTypeExtension); + + /* Properties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + + return offset; +} + +/* dissect the PDPortFODataAdjust block */ +static int +dissect_PDPortFODataAdjust_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32FiberOpticType; + guint32 u32FiberOpticCableType; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* FiberOpticType */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fiber_optic_type, &u32FiberOpticType); + + /* FiberOpticCableType */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fiber_optic_cable_type, &u32FiberOpticCableType); + +/* + proto_item_append_text(item, ": %s", + val_to_str(u16PortState, pn_io_port_state, "0x%x"));*/ + + return offset; +} + + +/* dissect the PDPortFODataCheck block */ +static int +dissect_PDPortFODataCheck_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32FiberOpticPowerBudget; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MaintenanceRequiredPowerBudget */ + /* XXX - decode the u32FiberOpticPowerBudget better */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_maintenance_required_power_budget, &u32FiberOpticPowerBudget); + + /* MaintenanceDemandedPowerBudget */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_maintenance_demanded_power_budget, &u32FiberOpticPowerBudget); + + /* ErrorPowerBudget */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_error_power_budget, &u32FiberOpticPowerBudget); + +/* + proto_item_append_text(item, ": %s", + val_to_str(u16PortState, pn_io_port_state, "0x%x"));*/ + + return offset; +} + +/* dissect the AdjustPeerToPeerBoundary block */ +static int +dissect_AdjustPeerToPeerBoundary_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32PeerToPeerBoundary; + guint16 u16AdjustProperties; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + sub_item = proto_tree_add_item(tree, hf_pn_io_peer_to_peer_boundary_value, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_peer_to_peer_boundary); + + /* PeerToPeerBoundary.Bit0 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_peer_to_peer_boundary_value_bit0, &u32PeerToPeerBoundary); + + /* PeerToPeerBoundary.Bit1 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_peer_to_peer_boundary_value_bit1, &u32PeerToPeerBoundary); + + /* PeerToPeerBoundary.Bit2 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_peer_to_peer_boundary_value_bit2, &u32PeerToPeerBoundary); + + /* PeerToPeerBoundary.OtherBits */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_peer_to_peer_boundary_value_otherbits, &u32PeerToPeerBoundary); + + /* Properties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + + return offset; +} + + +/* dissect the AdjustDCPBoundary block */ +static int +dissect_AdjustDCPBoundary_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32DcpBoundary; + guint16 u16AdjustProperties; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + sub_item = proto_tree_add_item(tree, hf_pn_io_dcp_boundary_value, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_dcp_boundary); + + /* DcpBoundary.Bit0 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_dcp_boundary_value_bit0, &u32DcpBoundary); + + /* DcpBoundary.Bit1 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_dcp_boundary_value_bit1, &u32DcpBoundary); + + /* DcpBoundary.OtherBits */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_dcp_boundary_value_otherbits, &u32DcpBoundary); + + /* Properties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_adjust_properties, &u16AdjustProperties); + + return offset; +} + +static int +dissect_MrpInstanceDataAdjust_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BodyLength) +{ + guint8 u8MrpInstance; + e_guid_t uuid; + guint16 u16Role; + guint8 u8LengthDomainName; + int endoffset = offset + u16BodyLength; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + /* Padding one byte */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + /* Mrp Instance */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_instance, &u8MrpInstance); + /* MRP_DomainUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_domain_uuid, &uuid); + /* MRP_Role */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_role, &u16Role); + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + /* MRP_LengthDomainName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_length_domain_name, &u8LengthDomainName); + /* MRP_DomainName */ + /* XXX - see comment earlier about MRP_DomainName */ + proto_tree_add_item (tree, hf_pn_io_mrp_domain_name, tvb, offset, u8LengthDomainName, ENC_ASCII); + offset += u8LengthDomainName; + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + while(endoffset > offset) + { + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + } + + return offset; +} + +static int +dissect_MrpInstanceDataReal_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BodyLength) +{ + guint8 u8MrpInstance; + e_guid_t uuid; + guint16 u16Role; + guint16 u16Version; + guint8 u8LengthDomainName; + int endoffset = offset + u16BodyLength; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + /* Padding one byte */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + /* Mrp Instance */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_instance, &u8MrpInstance); + /* MRP_DomainUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_domain_uuid, &uuid); + /* MRP_Role */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_role, &u16Role); + /* MRP_Version */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_version, &u16Version); + /* MRP_LengthDomainName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_length_domain_name, &u8LengthDomainName); + /* MRP_DomainName */ + /* XXX - see comment earlier about MRP_DomainName */ + proto_tree_add_item (tree, hf_pn_io_mrp_domain_name, tvb, offset, u8LengthDomainName, ENC_ASCII); + offset += u8LengthDomainName; + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + while(endoffset > offset) + { + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + } + return offset; +} + +static int +dissect_MrpInstanceDataCheck_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BodyLength _U_) +{ + guint8 u8MrpInstance; + guint32 u32Check; + e_guid_t uuid; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + /* Padding one byte */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + /* Mrp Instance */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_instance, &u8MrpInstance); + /* MRP_DomainUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_domain_uuid, &uuid); + + /* MRP_Check */ + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check, &u32Check); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check_mrm, &u32Check); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check_mrpdomain, &u32Check); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check_reserved_1, &u32Check); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_mrp_check_reserved_2, &u32Check); + offset +=4; /* MRP_Check (32 bit) done */ + + return offset; +} + +/* PDInterfaceAdjust */ +static int +dissect_PDInterfaceAdjust_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32SMultipleInterfaceMode; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; +} + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); +/* MultipleInterfaceMode */ + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_MultipleInterfaceMode_NameOfDevice, &u32SMultipleInterfaceMode); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_MultipleInterfaceMode_reserved_1, &u32SMultipleInterfaceMode); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_MultipleInterfaceMode_reserved_2, &u32SMultipleInterfaceMode); + return offset; +} + +/* TSNNetworkControlDataReal */ +static int +dissect_TSNNetworkControlDataReal_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item* sub_item; + proto_tree* sub_tree; + + e_guid_t nme_parameter_uuid; + guint32 u32NetworkDeadline; + guint16 u16SendClockFactor; + guint16 u16NumberofEntries; + guint16 u16TSNNMENameLength; + guint16 u16TSNDomainNameLength; + e_guid_t tsn_nme_name_uuid; + e_guid_t tsn_domain_uuid; + + int bit_offset; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* NMEParameterUUID*/ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_io_tsn_nme_parameter_uuid, &nme_parameter_uuid); + + /* TSNDomainVIDConfig*/ + sub_item = proto_tree_add_item(tree, hf_pn_io_tsn_domain_vid_config, tvb, offset, 16, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_tsn_domain_vid_config); + bit_offset = offset << 3; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_reserved, tvb, bit_offset, 32, ENC_BIG_ENDIAN); + bit_offset += 32; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_non_stream_vid_D, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_non_stream_vid_C, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_non_stream_vid_B, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_non_stream_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_stream_low_red_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_stream_low_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_stream_high_red_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_stream_high_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + + offset += 16; + + /* TSNDomainPortConfigBlock */ + offset = dissect_a_block(tvb, offset, pinfo, /*sub_*/tree, drep); + + /* Network Deadline */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_network_deadline, &u32NetworkDeadline); + + /* SendClockFactor 16 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_send_clock_factor, &u16SendClockFactor); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_number_of_tsn_time_data_block_entries, &u16NumberofEntries); + + /* TSNTimeDataBlock */ + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + + offset = dissect_a_block(tvb, offset, pinfo, /*sub_*/tree, drep); + } + + /* TSNNMENameUUID */ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_io_tsn_nme_name_uuid, &tsn_nme_name_uuid); + + /* TSNNMENameLength */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_tsn_nme_name_length, &u16TSNNMENameLength); + + /* TSNNMEName */ + proto_tree_add_item(tree, hf_pn_io_tsn_nme_name, tvb, offset, u16TSNNMENameLength, ENC_ASCII | ENC_NA); + offset += u16TSNNMENameLength; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* TSNDomainUUID */ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_io_tsn_domain_uuid, &tsn_domain_uuid); + + /* TSNDomainNameLength */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_tsn_domain_name_length, &u16TSNDomainNameLength); + + /* TSNDomainName */ + proto_tree_add_item(tree, hf_pn_io_tsn_domain_name, tvb, offset, u16TSNDomainNameLength, ENC_ASCII | ENC_NA); + offset += u16TSNDomainNameLength; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + return offset; + +} + +/* TSNNetworkControlDataAdjust */ +static int +dissect_TSNNetworkControlDataAdjust_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item* sub_item; + proto_tree* sub_tree; + + e_guid_t nme_parameter_uuid; + guint32 u32NetworkDeadline; + guint16 u16SendClockFactor; + guint16 u16NumberofEntries; + guint16 u16TSNNMENameLength; + e_guid_t tsn_nme_name_uuid; + + int bit_offset; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* NMEParameterUUID*/ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_io_tsn_nme_parameter_uuid, &nme_parameter_uuid); + + /* TSNDomainVIDConfig*/ + sub_item = proto_tree_add_item(tree, hf_pn_io_tsn_domain_vid_config, tvb, offset, 16, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_tsn_domain_vid_config); + + bit_offset = offset << 3; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_reserved, tvb, bit_offset, 32, ENC_BIG_ENDIAN); + bit_offset += 32; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_non_stream_vid_D, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_non_stream_vid_C, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_non_stream_vid_B, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_non_stream_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_stream_low_red_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_stream_low_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_stream_high_red_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + bit_offset += 12; + + proto_tree_add_bits_item(sub_tree, hf_pn_io_tsn_domain_vid_config_stream_high_vid, tvb, bit_offset, 12, ENC_BIG_ENDIAN); + + offset += 16; + + /* TSNDomainPortConfigBlock */ + offset = dissect_a_block(tvb, offset, pinfo, /*sub_*/tree, drep); + + /* Network Deadline */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_network_deadline, &u32NetworkDeadline); + + /* SendClockFactor 16 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_send_clock_factor, &u16SendClockFactor); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_number_of_tsn_time_data_block_entries, &u16NumberofEntries); + + /* TSNTimeDataBlock */ + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + + offset = dissect_a_block(tvb, offset, pinfo, /*sub_*/tree, drep); + } + + /* TSNNMENameUUID */ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_io_tsn_nme_name_uuid, &tsn_nme_name_uuid); + + /* TSNNMENameLength */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_tsn_nme_name_length, &u16TSNNMENameLength); + + /* TSNNMEName */ + proto_tree_add_item(tree, hf_pn_io_tsn_nme_name, tvb, offset, u16TSNNMENameLength, ENC_ASCII | ENC_NA); + offset += u16TSNNMENameLength; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + return offset; +} + +/* TSNStreamPathData */ +static int +dissect_TSNStreamPathDataReal_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, gboolean real) +{ + guint8 u8FDBCommand; + guint16 u16NumberofEntries; + guint8 dstAdd[6]; + guint16 u16StreamClass; + guint16 u16SlotNumber; + guint16 u16SubSlotNumber; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + + if (!real) { + /* FDBCommand */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_fdb_command, &u8FDBCommand); + } + else { + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + } + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_tsn_domain_sync_tree_entries, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + /* DestinationAddress */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_io_tsn_dst_add, dstAdd); + + /* StreamClass */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_tsn_stream_class, &u16StreamClass); + + /* IngressPort */ + /* TSNDomainPortID */ + /*SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_slot_nr, &u16SlotNumber); + /* SubSlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_subslot_nr, &u16SubSlotNumber); + + /* EgressPort */ + /* TSNDomainPortID */ + /*SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_slot_nr, &u16SlotNumber); + /* SubSlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_subslot_nr, &u16SubSlotNumber); + } + return offset; +} + +/* TSNSyncTreeData */ +static int +dissect_TSNSyncTreeData_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberofEntries; + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16TimeDomainNumber; + guint8 u8SyncPortRole; + proto_item* sub_item; + proto_tree* sub_tree; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_tsn_domain_sync_tree_entries, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + /* TSNDomainPortID */ + sub_item = proto_tree_add_item(tree, hf_pn_io_tsn_domain_port_id, tvb, offset, 4, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_tsn_domain_port_id); + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_slot_nr, &u16SlotNr); + /*--*/ + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_subslot_nr, &u16SubslotNr); + /* TimeDomainNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_time_domain_number, &u16TimeDomainNumber); + /* SyncPortRole */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, hf_pn_io_tsn_domain_sync_port_role, &u8SyncPortRole); + + /* Padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + } + return offset; +} + +/* TSNDomainPortConfigBlock */ +static int +dissect_TSNDomainPortConfig_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberofEntries; + guint16 u16SlotNr; + guint16 u16SubslotNr; + proto_item* sub_item_port_config; + proto_tree* sub_tree_port_config; + guint8 u8TSNDomainPortConfig; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_tsn_domain_port_config_entries, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + /* TSNDomainPortConfig */ + sub_item_port_config = proto_tree_add_item(tree, hf_pn_io_tsn_domain_port_config, tvb, offset, 1, ENC_NA); + sub_tree_port_config = proto_item_add_subtree(sub_item_port_config, ett_pn_io_tsn_domain_port_config); + + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree_port_config, drep, + hf_pn_io_tsn_domain_port_config_reserved, &u8TSNDomainPortConfig); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree_port_config, drep, + hf_pn_io_tsn_domain_port_config_boundary_port_config, &u8TSNDomainPortConfig); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree_port_config, drep, + hf_pn_io_tsn_domain_port_config_preemption_enabled, &u8TSNDomainPortConfig); + + /* Padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 3); + + /* TSNDomainPortIngressRateLimiter */ + offset = dissect_a_block(tvb, offset, pinfo, /*sub_*/tree, drep); + + /* TSNDomainQueueConfigBlock */ + offset = dissect_a_block(tvb, offset, pinfo, /*sub_*/tree, drep); + + /* TSNDomainQueueRateLimiterBlock */ + offset = dissect_a_block(tvb, offset, pinfo, /*sub_*/tree, drep); + } + return offset; +} + +/* TSNDomainQueueConfigBlock */ +static int +dissect_TSNDomainQueueConfig_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberofEntries; + proto_item* sub_item; + proto_tree* sub_tree; + guint64 u64TSNDomainQueueConfig; + dcerpc_info di; /* fake dcerpc_info struct */ + dcerpc_call_value dcv; /* fake dcerpc_call_value struct */ + di.call_data = &dcv; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_tsn_domain_queue_config_entries, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + + sub_item = proto_tree_add_item(tree, hf_pn_io_tsn_domain_queue_config, tvb, offset, 8, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_tsn_domain_queue_config); + + /* TSNDomainQueueConfig */ + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_config_mask_time_offset, &u64TSNDomainQueueConfig); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_config_unmask_time_offset, &u64TSNDomainQueueConfig); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_config_preemption_mode, &u64TSNDomainQueueConfig); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_config_shaper, &u64TSNDomainQueueConfig); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_config_tci_pcp, &u64TSNDomainQueueConfig); + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_config_queue_id, &u64TSNDomainQueueConfig); + } + return offset; +} + +/* TSNTimeDataBlock */ +static int +dissect_TSNTimeData_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16TimeDomainNumber; + guint32 u32TimePLLWindow; + guint32 u32MessageIntervalFactor; + guint16 u16MessageTimeoutFactor; + guint16 u16TimeSyncProperties; + guint8 u8TimeDomainNameLength; + e_guid_t time_domain_uuid; + proto_item* sub_item; + proto_tree* sub_tree; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* TimeDomainNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_time_domain_number, &u16TimeDomainNumber); + + /* TimePLLWindow */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_time_pll_window, &u32TimePLLWindow); + + /* MessageIntervalFactor */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_message_interval_factor, &u32MessageIntervalFactor); + + /* MessageTimeoutFactor */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_message_timeout_factor, &u16MessageTimeoutFactor); + + /* TimeSyncProperties */ + sub_item = proto_tree_add_item(tree, hf_pn_io_time_sync_properties, tvb, offset, 2, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_time_sync_properties); + + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_time_sync_properties_reserved, &u16TimeSyncProperties); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_time_sync_properties_role, &u16TimeSyncProperties); + + /* TimeDomainUUID */ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_io_time_domain_uuid, &time_domain_uuid); + + /* TimeDomainNameLength */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, hf_pn_io_time_domain_name_length, &u8TimeDomainNameLength); + + /* TimeDomainName */ + proto_tree_add_item(tree, hf_pn_io_time_domain_name, tvb, offset, u8TimeDomainNameLength, ENC_ASCII | ENC_NA); + offset += u8TimeDomainNameLength; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + return offset; +} + +/* TSNUploadNetworkAttributesBlock */ +static int +dissect_TSNUploadNetworkAttributes_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32TransferTimeTX; + guint32 u32TransferTimeRX; + guint32 u32MaxSupportedRecordSize; + + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + /* Align to the next 32 bit twice */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* TSNPortIDBlock */ + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + + /*MaxSupportedRecordSize*/ + offset= dissect_dcerpc_uint32(tvb,offset,pinfo,tree,drep,hf_pn_io_tsn_max_supported_record_size,&u32MaxSupportedRecordSize); + + /* TransferTimeTX */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_transfer_time_tx, &u32TransferTimeTX); + + /* TransferTimeRX */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_transfer_time_rx, &u32TransferTimeRX); + + /* TSNForwardingDelayBlock */ + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + + return offset; +} + +/* TSNExpectedNeighborBlock */ +static int +dissect_TSNExpectedNeighbor_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint8 u8NumberOfPeers; + guint8 u8I; + guint8 u8LengthPeerPortName; + guint8 u8LengthPeerStationName; + guint16 u16NumberOfEntries; + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint32 u32LineDelayValue; + + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_tsn_expected_neighbor_block_number_of_entries, &u16NumberOfEntries); + + while (u16NumberOfEntries > 0) + { + u16NumberOfEntries--; + + /*TSNDomainPortID*/ + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_slot_nr, &u16SlotNr); + /*--*/ + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_subslot_nr, &u16SubslotNr); + + /* Padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 3); + + /* NumberOfPeers */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_peers, &u8NumberOfPeers); + + u8I = u8NumberOfPeers; + while (u8I--) { + /* LengthPeerPortName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_peer_port_name, &u8LengthPeerPortName); + + /* PeerPortName */ + proto_tree_add_item(tree, hf_pn_io_peer_port_name, tvb, offset, u8LengthPeerPortName, ENC_ASCII | ENC_NA); + offset += u8LengthPeerPortName; + + /* LengthPeerStationName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_peer_station_name, &u8LengthPeerStationName); + + /* PeerStationName */ + proto_tree_add_item(tree, hf_pn_io_peer_station_name, tvb, offset, u8LengthPeerStationName, ENC_ASCII | ENC_NA); + offset += u8LengthPeerStationName; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* LineDelay */ + offset = dissect_Line_Delay(tvb, offset, pinfo, tree, drep, &u32LineDelayValue); + } + } + return offset; +} + +/* TSNExpectedNetworkAttributesBlock */ +static int +dissect_TSNExpectedNetworkAttributes_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Align to the next 32 bit twice */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* TSNPortIDBlock */ + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + + /* TSNForwardingDelayBlock */ + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + + /* TSNExpectedNeighborBlock */ + offset = dissect_a_block(tvb, offset, pinfo, tree, drep); + + return offset; +} + +/* TSNDomainPortIngressRateLimiterBlock */ +static int +dissect_TSNDomainPortIngressRateLimiter_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberofEntries; + proto_item* sub_item_port_ingress; + proto_tree* sub_tree_port_ingress; + guint64 u64TSNDomainPortIngressRateLimiter; + dcerpc_info di; /* fake dcerpc_info struct */ + dcerpc_call_value dcv; /* fake dcerpc_call_value struct */ + di.call_data = &dcv; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_tsn_domain_port_ingress_rate_limiter_entries, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + + /* TSNDomainPortIngressRateLimiter */ + sub_item_port_ingress = proto_tree_add_item(tree, hf_pn_io_tsn_domain_port_ingress_rate_limiter, tvb, offset, 8, ENC_NA); + sub_tree_port_ingress = proto_item_add_subtree(sub_item_port_ingress, ett_pn_io_tsn_domain_port_ingress_rate_limiter); + + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree_port_ingress, &di, drep, + hf_pn_io_tsn_domain_port_ingress_rate_limiter_cir, &u64TSNDomainPortIngressRateLimiter); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree_port_ingress, &di, drep, + hf_pn_io_tsn_domain_port_ingress_rate_limiter_cbs, &u64TSNDomainPortIngressRateLimiter); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree_port_ingress, &di, drep, + hf_pn_io_tsn_domain_port_ingress_rate_limiter_envelope, &u64TSNDomainPortIngressRateLimiter); + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree_port_ingress, &di, drep, + hf_pn_io_tsn_domain_port_ingress_rate_limiter_rank, &u64TSNDomainPortIngressRateLimiter); + } + return offset; +} + +/* TSNDomainQueueRateLimiterBlock */ +static int +dissect_TSNDomainQueueRateLimiter_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberofEntries; + proto_item* sub_item; + proto_tree* sub_tree; + guint64 u64TSNDomainQueueRateLimiter; + dcerpc_info di; /* fake dcerpc_info struct */ + dcerpc_call_value dcv; /* fake dcerpc_call_value struct */ + di.call_data = &dcv; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_tsn_domain_queue_rate_limiter_entries, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + + /* TSNDomainQueueRateLimiter */ + sub_item = proto_tree_add_item(tree, hf_pn_io_tsn_domain_queue_rate_limiter, tvb, offset, 8, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_tsn_domain_queue_rate_limiter); + + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_rate_limiter_cir, &u64TSNDomainQueueRateLimiter); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_rate_limiter_cbs, &u64TSNDomainQueueRateLimiter); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_rate_limiter_envelope, &u64TSNDomainQueueRateLimiter); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_rate_limiter_rank, &u64TSNDomainQueueRateLimiter); + dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_rate_limiter_queue_id, &u64TSNDomainQueueRateLimiter); + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, sub_tree, &di, drep, + hf_pn_io_tsn_domain_queue_rate_limiter_reserved, &u64TSNDomainQueueRateLimiter); + } + return offset; +} + +/* TSNPortIDBlock */ +static int +dissect_TSNPortID_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint8 u8NumberOfQueues; + guint8 u8ForwardingGroup; + guint8 u8TSNPortCapabilities; + guint16 u16NumberOfEntries; + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16MAUType; + guint16 u16MAUTypeExtension; + + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_tsn_port_id_block_number_of_entries, &u16NumberOfEntries); + + while (u16NumberOfEntries > 0) + { + u16NumberOfEntries--; + + /*TSNDomainPortID*/ + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_slot_nr, &u16SlotNr); + /*--*/ + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_subslot_nr, &u16SubslotNr); + + /*MAUType*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mau_type, &u16MAUType); + + /*MAUTypeExtension*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mau_type_extension, &u16MAUTypeExtension); + + /* NumberOfQueues */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_number_of_queues, &u8NumberOfQueues); + + /* TSNPortCapabilities */ + /* bit 0 */ + dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_port_capabilities_time_aware, &u8TSNPortCapabilities); + + /* bit 1 */ + dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_port_capabilities_preemption, &u8TSNPortCapabilities); + + /* bit 2 */ + dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_port_capabilities_queue_masking, &u8TSNPortCapabilities); + + /* bit 3-7 */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_port_capabilities_reserved, &u8TSNPortCapabilities); + + /* ForwardingGroup */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_forwarding_group, &u8ForwardingGroup); + + /* Align to the next 32 bit */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + + } + return offset; +} + +/* TSNForwardingDelayBlock */ +static int +dissect_TSNForwardingDelay_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint8 u8ForwardingGroupIngress; + guint8 u8ForwardingGroupEgress; + guint16 u16NumberOfEntries; + guint16 u16StreamClass; + guint32 u32DependentForwardingDelay; + guint32 u32IndependentForwardingDelay; + + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_tsn_forwarding_delay_block_number_of_entries, &u16NumberOfEntries); + + while (u16NumberOfEntries > 0) + { + u16NumberOfEntries--; + + /*ForwardingGroupIngress*/ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_forwarding_group_ingress, &u8ForwardingGroupIngress); + + /*ForwardingGroupEgress*/ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_forwarding_group_egress, &u8ForwardingGroupEgress); + + /* StreamClass */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_stream_class, &u16StreamClass); + + /* DependentForwardingDelay */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_dependent_forwarding_delay, &u32DependentForwardingDelay); + + /* IndependentForwardingDelay */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_tsn_independent_forwarding_delay, &u32IndependentForwardingDelay); + } + return offset; +} + +/* PDPortStatistic for one subslot */ +static int +dissect_PDPortStatistic_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32StatValue; + guint16 u16CounterStatus; + proto_item *sub_item; + proto_tree *sub_tree; + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + switch (u8BlockVersionLow) { + case(0): + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + break; + case(1): + sub_item = proto_tree_add_item(tree, hf_pn_io_pdportstatistic_counter_status, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_counter_status); + /* bit 0 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdportstatistic_counter_status_ifInOctets, &u16CounterStatus); + /* bit 1 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdportstatistic_counter_status_ifOutOctets, &u16CounterStatus); + /* bit 2 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdportstatistic_counter_status_ifInDiscards, &u16CounterStatus); + /* bit 3 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdportstatistic_counter_status_ifOutDiscards, &u16CounterStatus); + /* bit 4 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdportstatistic_counter_status_ifInErrors, &u16CounterStatus); + /* bit 5 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdportstatistic_counter_status_ifOutErrors, &u16CounterStatus); + /* bit 6-15 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdportstatistic_counter_status_reserved, &u16CounterStatus); + break; + default: /* will not execute because of the line preceding the switch */ + break; + } + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_pdportstatistic_ifInOctets, &u32StatValue); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_pdportstatistic_ifOutOctets, &u32StatValue); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_pdportstatistic_ifInDiscards, &u32StatValue); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_pdportstatistic_ifOutDiscards, &u32StatValue); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_pdportstatistic_ifInErrors, &u32StatValue); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_pdportstatistic_ifOutErrors, &u32StatValue); + + return offset; +} + +/* OwnPort */ +static int +dissect_OwnPort_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint8 u8LengthOwnPortID; + char *pOwnPortID; + guint16 u16MAUType; + guint16 u16MAUTypeExtension; + guint32 u32MulticastBoundary; + guint8 u8LinkStatePort; + guint8 u8LinkStateLink; + guint32 u32MediaType; + guint32 u32LineDelayValue; + guint16 u16PortStatus; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* LengthOwnPortID */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_own_port_id, &u8LengthOwnPortID); + /* OwnPortName */ + proto_tree_add_item_ret_display_string (tree, hf_pn_io_own_port_id, tvb, offset, u8LengthOwnPortID, ENC_ASCII, pinfo->pool, &pOwnPortID); + offset += u8LengthOwnPortID; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* LineDelay */ + offset = dissect_Line_Delay(tvb, offset, pinfo, tree, drep, &u32LineDelayValue); + + /* MediaType */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_media_type, &u32MediaType); + + /* MulticastBoundary */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_multicast_boundary, &u32MulticastBoundary); + + /* MAUType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mau_type, &u16MAUType); + + /* MAUTypeExtension */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mau_type_extension, &u16MAUTypeExtension); + + /* LinkState.Port */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_link_state_port, &u8LinkStatePort); + /* LinkState.Link */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_link_state_link, &u8LinkStateLink); + + /* RTClass3_PortStatus */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rtclass3_port_status, &u16PortStatus); + + proto_item_append_text(item, ": OwnPortID:%s, LinkState.Port:%s LinkState.Link:%s MediaType:%s MAUType:%s", + pOwnPortID, + val_to_str(u8LinkStatePort, pn_io_link_state_port, "0x%x"), + val_to_str(u8LinkStateLink, pn_io_link_state_link, "0x%x"), + val_to_str(u32MediaType, pn_io_media_type, "0x%x"), + val_to_str(u16MAUType, pn_io_mau_type, "0x%x")); + + return offset; +} + + +/* Neighbors */ +static int +dissect_Neighbors_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint8 u8NumberOfPeers; + guint8 u8I; + guint8 mac[6]; + char *pPeerStationName; + char *pPeerPortName; + guint8 u8LengthPeerPortName; + guint8 u8LengthPeerStationName; + guint16 u16MAUType; + guint16 u16MAUTypeExtension; + guint32 u32LineDelayValue; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* NumberOfPeers */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_peers, &u8NumberOfPeers); + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + u8I = u8NumberOfPeers; + while (u8I--) { + sub_item = proto_tree_add_item(tree, hf_pn_io_neighbor, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_neighbor); + + /* LineDelay */ + offset = dissect_Line_Delay(tvb, offset, pinfo, sub_tree, drep, &u32LineDelayValue); + + /* MAUType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_mau_type, &u16MAUType); + + /* MAUTypeExtension */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_mau_type_extension, &u16MAUTypeExtension); + + /* PeerMACAddress */ + offset = dissect_pn_mac(tvb, offset, pinfo, sub_tree, + hf_pn_io_peer_macadd, mac); + + /* LengthPeerPortName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_length_peer_port_name, &u8LengthPeerPortName); + /* PeerPortName */ + proto_tree_add_item_ret_display_string (sub_tree, hf_pn_io_peer_port_name, tvb, offset, u8LengthPeerPortName, + ENC_ASCII, pinfo->pool, &pPeerPortName); + offset += u8LengthPeerPortName; + + /* LengthPeerStationName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_length_peer_station_name, &u8LengthPeerStationName); + /* PeerStationName */ + proto_tree_add_item_ret_display_string (sub_tree, hf_pn_io_peer_station_name, tvb, offset, u8LengthPeerStationName, + ENC_ASCII, pinfo->pool, &pPeerStationName); + offset += u8LengthPeerStationName; + + offset = dissect_pn_align4(tvb, offset, pinfo, sub_tree); + + proto_item_append_text(sub_item, ": %s (%s)", pPeerStationName, pPeerPortName); + } + + return offset; +} + + +/* dissect the PDInterfaceDataReal block */ +static int +dissect_PDInterfaceDataReal_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint8 u8LengthOwnChassisID; + guint8 mac[6]; + guint32 ip; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* LengthOwnChassisID */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_length_own_chassis_id, &u8LengthOwnChassisID); + /* OwnChassisID */ + proto_tree_add_item (tree, hf_pn_io_own_chassis_id, tvb, offset, u8LengthOwnChassisID, ENC_ASCII); + offset += u8LengthOwnChassisID; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* MACAddressValue */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_io_macadd, mac); + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* IPAddress */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_io_ip_address, &ip); + /*proto_item_append_text(block_item, ", IP: %s", ip_to_str((guint8*)&ip));*/ + + /* Subnetmask */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_io_subnetmask, &ip); + /*proto_item_append_text(block_item, ", Subnet: %s", ip_to_str((guint8*)&ip));*/ + + /* StandardGateway */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_io_standard_gateway, &ip); + /*proto_item_append_text(block_item, ", Router: %s", ip_to_str((guint8*)&ip));*/ + + + return offset; +} + + +/* dissect the PDSyncData block */ +static int +dissect_PDSyncData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16SlotNr; + guint16 u16SubslotNr; + e_guid_t uuid; + guint32 u32ReservedIntervalBegin; + guint32 u32ReservedIntervalEnd; + guint32 u32PLLWindow; + guint32 u32SyncSendFactor; + guint16 u16SendClockFactor; + guint16 u16SyncProperties; + guint16 u16SyncFrameAddress; + guint16 u16PTCPTimeoutFactor; + guint16 u16PTCPTakeoverTimeoutFactor; + guint16 u16PTCPMasterStartupTime; + guint8 u8MasterPriority1; + guint8 u8MasterPriority2; + guint8 u8LengthSubdomainName; + + + if (u8BlockVersionHigh != 1) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + switch (u8BlockVersionLow) { + case(0): + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* PTCPSubdomainID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_subdomain_id, &uuid); + /* IRDataID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ir_data_id, &uuid); + /* ReservedIntervalBegin */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_reserved_interval_begin, &u32ReservedIntervalBegin); + /* ReservedIntervalEnd */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_reserved_interval_end, &u32ReservedIntervalEnd); + /* PLLWindow enum */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_pllwindow, &u32PLLWindow); + /* SyncSendFactor 32 enum */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_sync_send_factor, &u32SyncSendFactor); + /* SendClockFactor 16 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_send_clock_factor, &u16SendClockFactor); + /* SyncProperties 16 bitfield */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_sync_properties, &u16SyncProperties); + /* SyncFrameAddress 16 bitfield */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_sync_frame_address, &u16SyncFrameAddress); + /* PTCPTimeoutFactor 16 enum */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_timeout_factor, &u16PTCPTimeoutFactor); + + proto_item_append_text(item, ": Slot:0x%x/0x%x, Interval:%u-%u, PLLWin:%u, Send:%u, Clock:%u", + u16SlotNr, u16SubslotNr, u32ReservedIntervalBegin, u32ReservedIntervalEnd, + u32PLLWindow, u32SyncSendFactor, u16SendClockFactor); + break; + case(2): + /* PTCPSubdomainID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_subdomain_id, &uuid); + /* ReservedIntervalBegin */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_reserved_interval_begin, &u32ReservedIntervalBegin); + /* ReservedIntervalEnd */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_reserved_interval_end, &u32ReservedIntervalEnd); + /* PLLWindow enum */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_pllwindow, &u32PLLWindow); + /* SyncSendFactor 32 enum */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_sync_send_factor, &u32SyncSendFactor); + /* SendClockFactor 16 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_send_clock_factor, &u16SendClockFactor); + /* PTCPTimeoutFactor 16 enum */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_timeout_factor, &u16PTCPTimeoutFactor); + /* PTCPTakeoverTimeoutFactor 16 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_takeover_timeout_factor, &u16PTCPTakeoverTimeoutFactor); + /* PTCPMasterStartupTime 16 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_master_startup_time, &u16PTCPMasterStartupTime); + /* SyncProperties 16 bitfield */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_sync_properties, &u16SyncProperties); + /* PTCP_MasterPriority1 */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_master_priority_1, &u8MasterPriority1); + /* PTCP_MasterPriority2 */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_master_priority_2, &u8MasterPriority2); + /* PTCPLengthSubdomainName */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, tree, drep, + hf_pn_io_ptcp_length_subdomain_name, &u8LengthSubdomainName); + /* PTCPSubdomainName */ + /* XXX - another Punycode string */ + proto_tree_add_item (tree, hf_pn_io_ptcp_subdomain_name, tvb, offset, u8LengthSubdomainName, ENC_ASCII); + offset += u8LengthSubdomainName; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + proto_item_append_text(item, ": Interval:%u-%u, PLLWin:%u, Send:%u, Clock:%u", + u32ReservedIntervalBegin, u32ReservedIntervalEnd, + u32PLLWindow, u32SyncSendFactor, u16SendClockFactor); + break; + default: + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + } + + return offset; +} + + +/* dissect the PDIRData block */ +static int +dissect_PDIRData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + + /* versions decoded are High: 1 and LOW 0..2 */ + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow > 2 ) ) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + proto_item_append_text(item, ": Slot:0x%x/0x%x", + u16SlotNr, u16SubslotNr); + + /* PDIRGlobalData */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + if (u8BlockVersionLow == 0) { + /* PDIRFrameData */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + } else if (u8BlockVersionLow == 1) { + /* [PDIRFrameData] */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + /* PDIRBeginEndData */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + }else if (u8BlockVersionLow == 2) { + /* [PDIRFrameData] */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + /* PDIRBeginEndData */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + } + return offset; +} + + +/* dissect the PDIRGlobalData block */ +static int +dissect_PDIRGlobalData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + e_guid_t uuid; + guint32 u32MaxBridgeDelay; + guint32 u32NumberOfPorts; + guint32 u32MaxPortTxDelay; + guint32 u32MaxPortRxDelay; + guint32 u32MaxLineRxDelay; + guint32 u32YellowTime; + guint32 u32Tmp; + + /* added blockversion 2 */ + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow > 2)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* IRDataID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ir_data_id, &uuid); + + if (u8BlockVersionLow <= 2) { + /* MaxBridgeDelay */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_max_bridge_delay, &u32MaxBridgeDelay); + /* NumberOfPorts */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_ports, &u32NumberOfPorts); + u32Tmp = u32NumberOfPorts; + + while (u32Tmp--) { + /* MaxPortTxDelay */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_max_port_tx_delay, &u32MaxPortTxDelay); + /* MaxPortRxDelay */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_max_port_rx_delay, &u32MaxPortRxDelay); + if (u8BlockVersionLow >= 2) { + /* MaxLineRxDelay */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_max_line_rx_delay, &u32MaxLineRxDelay); + /* YellowTime */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_yellowtime, &u32YellowTime); + } + } + proto_item_append_text(item, ": MaxBridgeDelay:%u, NumberOfPorts:%u", + u32MaxBridgeDelay, u32NumberOfPorts); + + } + return offset; +} + + +/* dissect the PDIRFrameData block */ +static int +dissect_PDIRFrameData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint32 u32FrameSendOffset; + guint32 u32FrameDataProperties; + guint16 u16DataLength; + guint16 u16ReductionRatio; + guint16 u16Phase; + guint16 u16FrameID; + guint16 u16Ethertype; + guint8 u8RXPort; + guint8 u8FrameDetails; + guint8 u8NumberOfTxPortGroups; + guint8 u8TxPortGroupArray; + guint16 u16TxPortGroupArraySize; + guint16 u16EndOffset; + guint16 n = 0; + proto_item *sub_item; + proto_tree *sub_tree; + + /* added low version 1 */ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow > 1) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + u16EndOffset = offset + u16BodyLength -2; + if (u8BlockVersionLow > 0) { + /* for low version 1 FrameDataProperties is added */ + sub_item = proto_tree_add_item(tree, hf_pn_io_frame_data_properties, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_FrameDataProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_frame_data_properties_forwarding_Mode, &u32FrameDataProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_frame_data_properties_FastForwardingMulticastMACAdd, &u32FrameDataProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_frame_data_properties_FragmentMode, &u32FrameDataProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_frame_data_properties_reserved_1, &u32FrameDataProperties); + offset = + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_frame_data_properties_reserved_2, &u32FrameDataProperties); + } + /* dissect all IR frame data */ + while (offset < u16EndOffset) + { + proto_item *ir_frame_data_sub_item; + proto_tree *ir_frame_data_tree; + + n++; + + /* new subtree for each IR frame */ + ir_frame_data_sub_item = proto_tree_add_item(tree, hf_pn_io_ir_frame_data, tvb, offset, 17, ENC_NA); + ir_frame_data_tree = proto_item_add_subtree(ir_frame_data_sub_item, ett_pn_io_ir_frame_data); + + /* FrameSendOffset */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_frame_data_tree, drep, + hf_pn_io_frame_send_offset, &u32FrameSendOffset); + /* DataLength */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ir_frame_data_tree, drep, + hf_pn_io_data_length, &u16DataLength); + /* ReductionRatio */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ir_frame_data_tree, drep, + hf_pn_io_reduction_ratio, &u16ReductionRatio); + /* Phase */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ir_frame_data_tree, drep, + hf_pn_io_phase, &u16Phase); + /* FrameID */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ir_frame_data_tree, drep, + hf_pn_io_frame_id, &u16FrameID); + + /* Ethertype */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ir_frame_data_tree, drep, + hf_pn_io_ethertype, &u16Ethertype); + /* RxPort */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, ir_frame_data_tree, drep, + hf_pn_io_rx_port, &u8RXPort); + /* FrameDetails */ + sub_item = proto_tree_add_item(ir_frame_data_tree, hf_pn_io_frame_details, tvb, offset, 1, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_frame_defails); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_frame_details_sync_frame, &u8FrameDetails); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_frame_details_meaning_frame_send_offset, &u8FrameDetails); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_frame_details_reserved, &u8FrameDetails); + /* TxPortGroup */ + u8NumberOfTxPortGroups = tvb_get_guint8(tvb, offset); + sub_item = proto_tree_add_uint(ir_frame_data_tree, hf_pn_io_nr_of_tx_port_groups, + tvb, offset, 1, u8NumberOfTxPortGroups); + offset++; + if ((u8NumberOfTxPortGroups > 21) || ((u8NumberOfTxPortGroups & 0x1) !=1)) { + expert_add_info(pinfo, sub_item, &ei_pn_io_nr_of_tx_port_groups); + } + + /* TxPortArray */ + u16TxPortGroupArraySize = (u8NumberOfTxPortGroups + 7 / 8); + sub_item = proto_tree_add_item(ir_frame_data_tree, hf_pn_io_TxPortGroupProperties, + tvb, offset, u16TxPortGroupArraySize, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_GroupProperties); + while (u16TxPortGroupArraySize > 0) + { + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_TxPortGroupProperties_bit0, &u8TxPortGroupArray); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_TxPortGroupProperties_bit1, &u8TxPortGroupArray); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_TxPortGroupProperties_bit2, &u8TxPortGroupArray); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_TxPortGroupProperties_bit3, &u8TxPortGroupArray); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_TxPortGroupProperties_bit4, &u8TxPortGroupArray); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_TxPortGroupProperties_bit5, &u8TxPortGroupArray); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_TxPortGroupProperties_bit6, &u8TxPortGroupArray); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_TxPortGroupProperties_bit7, &u8TxPortGroupArray); + + offset+=1; + u16TxPortGroupArraySize --; + } + + /* align to next dataset */ + offset = dissect_pn_align4(tvb, offset, pinfo, ir_frame_data_tree); + + proto_item_append_text(ir_frame_data_tree, ": Offset:%u, Len:%u, Ratio:%u, Phase:%u, FrameID:0x%04x", + u32FrameSendOffset, u16DataLength, u16ReductionRatio, u16Phase, u16FrameID); + + } + + proto_item_append_text(item, ": Frames:%u", n); + + return offset; +} + + +static int +dissect_PDIRBeginEndData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint16 u16StartOfRedFrameID; + guint16 u16EndOfRedFrameID; + guint32 u32NumberOfPorts; + guint32 u32NumberOfAssignments; + guint32 u32NumberOfPhases; + guint32 u32RedOrangePeriodBegin; + guint32 u32OrangePeriodBegin; + guint32 u32GreenPeriodBegin; + guint16 u16TXPhaseAssignment; + guint16 u16RXPhaseAssignment; + guint32 u32SubStart; + guint32 u32Tmp; + guint32 u32Tmp2; + guint32 u32TxRedOrangePeriodBegin[0x11] = {0}; + guint32 u32TxOrangePeriodBegin [0x11] = {0}; + guint32 u32TxGreenPeriodBegin [0x11] = {0}; + guint32 u32RxRedOrangePeriodBegin[0x11] = {0}; + guint32 u32RxOrangePeriodBegin [0x11] = {0}; + guint32 u32RxGreenPeriodBegin [0x11] = {0}; + guint32 u32PortIndex; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_start_of_red_frame_id, &u16StartOfRedFrameID); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_end_of_red_frame_id, &u16EndOfRedFrameID); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_ports, &u32NumberOfPorts); + u32Tmp2 = u32NumberOfPorts; + while (u32Tmp2--) { + proto_item *ir_begin_end_port_sub_item; + proto_tree *ir_begin_end_port_tree; + + /* new subtree for each Port */ + ir_begin_end_port_sub_item = proto_tree_add_item(tree, hf_pn_io_ir_begin_end_port, tvb, offset, 0, ENC_NA); + ir_begin_end_port_tree = proto_item_add_subtree(ir_begin_end_port_sub_item, ett_pn_io_ir_begin_end_port); + u32SubStart = offset; + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_begin_end_port_tree, drep, + hf_pn_io_number_of_assignments, &u32NumberOfAssignments); + u32Tmp = u32NumberOfAssignments; + u32PortIndex = 0; + if (u32Tmp <= 0x10) + { + while (u32Tmp--) { + /* TXBeginEndAssignment */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_begin_end_port_tree, drep, + hf_pn_io_red_orange_period_begin_tx, &u32RedOrangePeriodBegin); + u32TxRedOrangePeriodBegin[u32PortIndex] = u32RedOrangePeriodBegin; + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_begin_end_port_tree, drep, + hf_pn_io_orange_period_begin_tx, &u32OrangePeriodBegin); + u32TxOrangePeriodBegin[u32PortIndex]= u32OrangePeriodBegin; + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_begin_end_port_tree, drep, + hf_pn_io_green_period_begin_tx, &u32GreenPeriodBegin); + u32TxGreenPeriodBegin[u32PortIndex] = u32GreenPeriodBegin; + + /* RXBeginEndAssignment */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_begin_end_port_tree, drep, + hf_pn_io_red_orange_period_begin_rx, &u32RedOrangePeriodBegin); + u32RxRedOrangePeriodBegin[u32PortIndex] = u32RedOrangePeriodBegin; + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_begin_end_port_tree, drep, + hf_pn_io_orange_period_begin_rx, &u32OrangePeriodBegin); + u32RxOrangePeriodBegin[u32PortIndex]= u32OrangePeriodBegin; + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_begin_end_port_tree, drep, + hf_pn_io_green_period_begin_rx, &u32GreenPeriodBegin); + u32RxGreenPeriodBegin[u32PortIndex] = u32GreenPeriodBegin; + + u32PortIndex++; + } + } + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ir_begin_end_port_tree, drep, + hf_pn_io_number_of_phases, &u32NumberOfPhases); + u32Tmp = u32NumberOfPhases; + if (u32Tmp <= 0x10) + { + while (u32Tmp--) { + proto_item *ir_begin_tx_phase_sub_item; + proto_tree *ir_begin_tx_phase_tree; + + /* new subtree for TXPhaseAssignment */ + ir_begin_tx_phase_sub_item = proto_tree_add_item(ir_begin_end_port_tree, + hf_pn_ir_tx_phase_assignment, tvb, offset, 0, ENC_NA); + ir_begin_tx_phase_tree = proto_item_add_subtree(ir_begin_tx_phase_sub_item, ett_pn_io_ir_tx_phase); + /* bit 0..3 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, ir_begin_tx_phase_tree, drep, + hf_pn_io_tx_phase_assignment_begin_value, &u16TXPhaseAssignment); + /* bit 4..7 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, ir_begin_tx_phase_tree, drep, + hf_pn_io_tx_phase_assignment_orange_begin, &u16TXPhaseAssignment); + /* bit 8..11 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, ir_begin_tx_phase_tree, drep, + hf_pn_io_tx_phase_assignment_end_reserved, &u16TXPhaseAssignment); + /* bit 12..15 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ir_begin_tx_phase_tree, drep, + hf_pn_io_tx_phase_assignment_reserved, &u16TXPhaseAssignment); + + proto_item_append_text(ir_begin_tx_phase_sub_item, + ": 0x%x, RedOrangePeriodBegin: %d, OrangePeriodBegin: %d, GreenPeriodBegin: %d", + u16TXPhaseAssignment, + u32TxRedOrangePeriodBegin[u16TXPhaseAssignment & 0x0F], + u32TxOrangePeriodBegin[(u16TXPhaseAssignment & 0x0F0) >> 4], + u32TxGreenPeriodBegin[(u16TXPhaseAssignment & 0x0F00)>> 8]); + + /* new subtree for RXPhaseAssignment */ + ir_begin_tx_phase_sub_item = proto_tree_add_item(ir_begin_end_port_tree, + hf_pn_ir_rx_phase_assignment, tvb, offset, 0, ENC_NA); + ir_begin_tx_phase_tree = proto_item_add_subtree(ir_begin_tx_phase_sub_item, ett_pn_io_ir_rx_phase); + /* bit 0..3 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, ir_begin_tx_phase_tree, drep, + hf_pn_io_tx_phase_assignment_begin_value, &u16RXPhaseAssignment); + /* bit 4..7 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, ir_begin_tx_phase_tree, drep, + hf_pn_io_tx_phase_assignment_orange_begin, &u16RXPhaseAssignment); + /* bit 8..11 */ + dissect_dcerpc_uint16(tvb, offset, pinfo, ir_begin_tx_phase_tree, drep, + hf_pn_io_tx_phase_assignment_end_reserved, &u16RXPhaseAssignment); + /* bit 12..15 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ir_begin_tx_phase_tree, drep, + hf_pn_io_tx_phase_assignment_reserved, &u16RXPhaseAssignment); + + proto_item_append_text(ir_begin_tx_phase_sub_item, + ": 0x%x, RedOrangePeriodBegin: %d, OrangePeriodBegin: %d, GreenPeriodBegin: %d", + u16RXPhaseAssignment, + u32RxRedOrangePeriodBegin[u16RXPhaseAssignment & 0x0F], + u32RxOrangePeriodBegin[(u16RXPhaseAssignment & 0x0F0) >> 4], + u32RxGreenPeriodBegin[(u16RXPhaseAssignment & 0x0F00)>> 8]); + } + } + proto_item_append_text(ir_begin_end_port_sub_item, ": Assignments:%u, Phases:%u", + u32NumberOfAssignments, u32NumberOfPhases); + + proto_item_set_len(ir_begin_end_port_sub_item, offset - u32SubStart); + } + + proto_item_append_text(item, ": StartOfRedFrameID: 0x%x, EndOfRedFrameID: 0x%x, Ports: %u", + u16StartOfRedFrameID, u16EndOfRedFrameID, u32NumberOfPorts); + + return offset+u16BodyLength; +} + + +/* dissect the DiagnosisData block */ +static int +dissect_DiagnosisData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 body_length) +{ + guint32 u32Api; + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16ChannelNumber; + guint16 u16UserStructureIdentifier; + proto_item *sub_item; + + + if (u8BlockVersionHigh != 1 || (u8BlockVersionLow != 0 && u8BlockVersionLow != 1)) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + if (u8BlockVersionLow == 1) { + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + body_length-=4; + } + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* ChannelNumber got new ranges: 0..0x7FFF the source is a channel as specified by the manufacturer */ + /* fetch u16ChannelNumber */ + u16ChannelNumber = ((drep[0] & DREP_LITTLE_ENDIAN) + ? tvb_get_letohs(tvb, offset) + : tvb_get_ntohs(tvb, offset)); + if (tree) { + sub_item = proto_tree_add_item(tree,hf_pn_io_channel_number, tvb, offset, 2, DREP_ENC_INTEGER(drep)); + if (u16ChannelNumber < 0x8000){ /* 0..0x7FFF the source is a channel as specified by the manufacturer */ + proto_item_append_text(sub_item, " channel number of the diagnosis source"); + } + else + if (u16ChannelNumber == 0x8000) /* 0x8000 the whole submodule is the source, */ + proto_item_append_text(sub_item, " (whole) Submodule"); + else + proto_item_append_text(sub_item, " reserved"); + } + offset = offset +2; /* Advance behind ChannelNumber */ + /* ChannelProperties */ + offset = dissect_ChannelProperties(tvb, offset, pinfo, tree, item, drep); + body_length-=8; + /* UserStructureIdentifier */ + u16UserStructureIdentifier = ((drep[0] & DREP_LITTLE_ENDIAN) + ? tvb_get_letohs(tvb, offset) + : tvb_get_ntohs(tvb, offset)); + if (u16UserStructureIdentifier > 0x7FFF){ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_user_structure_identifier, &u16UserStructureIdentifier); + } + else + { /* range 0x0 to 0x7fff is manufacturer specific */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_user_structure_identifier_manf, &u16UserStructureIdentifier); + } + proto_item_append_text(item, ", USI:0x%x", u16UserStructureIdentifier); + body_length-=2; + + /* the rest of the block contains optional: [MaintenanceItem] and/or [AlarmItem] */ + while (body_length) { + offset = dissect_AlarmUserStructure(tvb, offset, pinfo, tree, item, drep, + &body_length, u16UserStructureIdentifier); + } + return offset; +} + + +static int +dissect_ARProperties(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, guint8 *drep _U_) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32ARProperties; + guint8 startupMode; + guint8 isTimeAware; + + sub_item = proto_tree_add_item(tree, hf_pn_io_ar_properties, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_ar_properties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_pull_module_alarm_allowed, &u32ARProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_arproperties_StartupMode, &u32ARProperties); + startupMode = (guint8)((u32ARProperties >> 30) & 0x01); + /* Advanced startup mode */ + if (startupMode) + { + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_combined_object_container_with_advanced_startupmode, &u32ARProperties); + } + /* Legacy startup mode */ + else + { + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_combined_object_container_with_legacy_startupmode, &u32ARProperties); + } + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_time_aware_system, &u32ARProperties); + + isTimeAware = (guint8)((u32ARProperties >> 28) & 0x01); + + wmem_map_insert(pnio_time_aware_frame_map, GUINT_TO_POINTER(pinfo->num), GUINT_TO_POINTER(isTimeAware)); + + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_reserved, &u32ARProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_achnowledge_companion_ar, &u32ARProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_companion_ar, &u32ARProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_device_access, &u32ARProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_reserved_1, &u32ARProperties); +/* removed within 2.3 + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_data_rate, &u32ARProperties); +*/ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_parameterization_server, &u32ARProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_supervisor_takeover_allowed, &u32ARProperties); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_ar_properties_state, &u32ARProperties); + + return offset; +} + +/* dissect the IOCRProperties */ +static int +dissect_IOCRProperties(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32IOCRProperties; + + sub_item = proto_tree_add_item(tree, hf_pn_io_iocr_properties, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_iocr_properties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocr_properties_full_subframe_structure, &u32IOCRProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocr_properties_distributed_subframe_watchdog, &u32IOCRProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocr_properties_fast_forwarding_mac_adr, &u32IOCRProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocr_properties_reserved_3, &u32IOCRProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocr_properties_reserved_2, &u32IOCRProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocr_properties_media_redundancy, &u32IOCRProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocr_properties_reserved_1, &u32IOCRProperties); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocr_properties_rtclass, &u32IOCRProperties); + + return offset; +} + + +/* dissect the ARData block */ +static int +dissect_ARData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BlockLength) +{ + guint16 u16NumberOfARs; + guint16 u16NumberofEntries; + e_guid_t aruuid; + e_guid_t uuid; + guint16 u16ARType; + guint16 u16NameLength; + guint16 u16NumberOfIOCRs; + guint16 u16IOCRType; + guint16 u16FrameID; + guint16 u16CycleCounter; + guint8 u8DataStatus; + guint8 u8TransferStatus; + proto_item *ds_item; + proto_tree *ds_tree; + guint16 u16UDPRTPort; + guint16 u16AlarmCRType; + guint16 u16LocalAlarmReference; + guint16 u16RemoteAlarmReference; + guint16 u16NumberOfAPIs; + guint32 u32Api; + proto_item *iocr_item; + proto_tree *iocr_tree; + proto_item *ar_item; + proto_tree *ar_tree; + guint32 u32IOCRStart; + gint32 i32EndOffset; + guint32 u32ARDataStart; + + /* added BlockversionLow == 1 */ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow > 1) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + i32EndOffset = offset + u16BlockLength; + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_ars, &u16NumberOfARs); + /* BlockversionLow: 0 */ + if (u8BlockVersionLow == 0) { + while (u16NumberOfARs--) { + ar_item = proto_tree_add_item(tree, hf_pn_io_ar_data, tvb, offset, 0, ENC_NA); + ar_tree = proto_item_add_subtree(ar_item, ett_pn_io_ar_data); + u32ARDataStart = offset; + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_ar_uuid, &aruuid); + + if (!PINFO_FD_VISITED(pinfo)) { + pn_init_append_aruuid_frame_setup_list(aruuid, pinfo->num); + } + + proto_item_append_text(ar_item, "ARUUID:%s", guid_to_str(pinfo->pool, (const e_guid_t*) &aruuid)); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_ar_type, &u16ARType); + offset = dissect_ARProperties(tvb, offset, pinfo, ar_tree, item, drep); + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_cminitiator_objectuuid, &uuid); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_station_name_length, &u16NameLength); + proto_tree_add_item (ar_tree, hf_pn_io_cminitiator_station_name, tvb, offset, u16NameLength, ENC_ASCII); + offset += u16NameLength; + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_number_of_iocrs, &u16NumberOfIOCRs); + + while (u16NumberOfIOCRs--) { + iocr_item = proto_tree_add_item(ar_tree, hf_pn_io_iocr_tree, tvb, offset, 0, ENC_NA); + iocr_tree = proto_item_add_subtree(iocr_item, ett_pn_io_iocr); + u32IOCRStart = offset; + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, iocr_tree, drep, + hf_pn_io_iocr_type, &u16IOCRType); + offset = dissect_IOCRProperties(tvb, offset, pinfo, iocr_tree, drep); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, iocr_tree, drep, + hf_pn_io_frame_id, &u16FrameID); + + proto_item_append_text(iocr_item, ": FrameID:0x%x", u16FrameID); + + /* add cycle counter */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, iocr_tree, drep, + hf_pn_io_cycle_counter, &u16CycleCounter); + + u8DataStatus = tvb_get_guint8(tvb, offset); + u8TransferStatus = tvb_get_guint8(tvb, offset+1); + + /* add data status subtree */ + ds_item = proto_tree_add_uint_format(iocr_tree, hf_pn_io_data_status, + tvb, offset, 1, u8DataStatus, + "DataStatus: 0x%02x (Frame: %s and %s, Provider: %s and %s)", + u8DataStatus, + (u8DataStatus & 0x04) ? "Valid" : "Invalid", + (u8DataStatus & 0x01) ? "Primary" : "Backup", + (u8DataStatus & 0x20) ? "Ok" : "Problem", + (u8DataStatus & 0x10) ? "Run" : "Stop"); + ds_tree = proto_item_add_subtree(ds_item, ett_pn_io_data_status); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_res67, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_ok, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_operate, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_res3, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_valid, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_res1, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_primary, tvb, offset, 1, u8DataStatus); + + offset++; + + /* add transfer status */ + if (u8TransferStatus) { + proto_tree_add_uint_format(iocr_tree, hf_pn_io_transfer_status, tvb, + offset, 1, u8TransferStatus, + "TransferStatus: 0x%02x (ignore this frame)", u8TransferStatus); + } else { + proto_tree_add_uint_format(iocr_tree, hf_pn_io_transfer_status, tvb, + offset, 1, u8TransferStatus, + "TransferStatus: 0x%02x (OK)", u8TransferStatus); + } + + offset++; + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, iocr_tree, drep, + hf_pn_io_cminitiator_udprtport, &u16UDPRTPort); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, iocr_tree, drep, + hf_pn_io_cmresponder_udprtport, &u16UDPRTPort); + + proto_item_set_len(iocr_item, offset - u32IOCRStart); + } + + /* AlarmCRType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_alarmcr_type, &u16AlarmCRType); + /* LocalAlarmReference */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_localalarmref, &u16LocalAlarmReference); + /* RemoteAlarmReference */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_remotealarmref, &u16RemoteAlarmReference); + /* ParameterServerObjectUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_parameter_server_objectuuid, &uuid); + /* StationNameLength */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_station_name_length, &u16NameLength); + /* ParameterServerStationName */ + proto_tree_add_item (ar_tree, hf_pn_io_parameter_server_station_name, tvb, offset, u16NameLength, ENC_ASCII); + offset += u16NameLength; + /* NumberOfAPIs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + /* API */ + while (u16NumberOfAPIs--) { + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ar_tree, drep, + hf_pn_io_api, &u32Api); + } + proto_item_set_len(ar_item, offset - u32ARDataStart); + } + } + else + { /* BlockversionLow == 1 */ + while (u16NumberOfARs--) { + ar_item = proto_tree_add_item(tree, hf_pn_io_ar_data, tvb, offset, 0, ENC_NA); + ar_tree = proto_item_add_subtree(ar_item, ett_pn_io_ar_data); + u32ARDataStart = offset; + /*ARUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_ar_uuid, &aruuid); + + if (!PINFO_FD_VISITED(pinfo)) { + pn_init_append_aruuid_frame_setup_list(aruuid, pinfo->num); + } + + proto_item_append_text(ar_item, "ARUUID:%s", guid_to_str(pinfo->pool, (const e_guid_t*) &aruuid)); + /* CMInitiatorObjectUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_cminitiator_objectuuid, &uuid); + /* ParameterServerObjectUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_parameter_server_objectuuid, &uuid); + /* ARProperties*/ + offset = dissect_ARProperties(tvb, offset, pinfo, ar_tree, item, drep); + /* ARType*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_ar_type, &u16ARType); + /* AlarmCRType */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_alarmcr_type, &u16AlarmCRType); + /* LocalAlarmReference */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_localalarmref, &u16LocalAlarmReference); + /* RemoteAlarmReference */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_remotealarmref, &u16RemoteAlarmReference); + /* InitiatorUDPRTPort*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_cminitiator_udprtport, &u16UDPRTPort); + /* ResponderUDPRTPort*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_cmresponder_udprtport, &u16UDPRTPort); + /* CMInitiatorStationName*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_station_name_length, &u16NameLength); + proto_tree_add_item (ar_tree, hf_pn_io_cminitiator_station_name, tvb, offset, u16NameLength, ENC_ASCII); + offset += u16NameLength; + /** align padding! **/ + offset = dissect_pn_align4(tvb, offset, pinfo, ar_tree); + + /* StationNameLength */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_station_name_length, &u16NameLength); + if (u16NameLength != 0) { + /* ParameterServerStationName */ + proto_tree_add_item (ar_tree, hf_pn_io_parameter_server_station_name, tvb, offset, u16NameLength, ENC_ASCII); + offset += u16NameLength; + } + else + { /* display no name present */ + proto_tree_add_string (ar_tree, hf_pn_io_parameter_server_station_name, tvb, offset, u16NameLength, " "); + } + /** align padding! **/ + offset = dissect_pn_align4(tvb, offset, pinfo, ar_tree); + + /* NumberOfIOCRs*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_number_of_iocrs, &u16NumberOfIOCRs); + /* align to next 32 bit */ + offset = dissect_pn_padding(tvb, offset, pinfo, ar_tree, 2); + + while (u16NumberOfIOCRs--) { + iocr_item = proto_tree_add_item(ar_tree, hf_pn_io_iocr_tree, tvb, offset, 0, ENC_NA); + iocr_tree = proto_item_add_subtree(iocr_item, ett_pn_io_iocr); + u32IOCRStart = offset; + + /* IOCRProperties*/ + offset = dissect_IOCRProperties(tvb, offset, pinfo, iocr_tree, drep); + /* IOCRType*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, iocr_tree, drep, hf_pn_io_iocr_type, &u16IOCRType); + /* FrameID*/ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, iocr_tree, drep, hf_pn_io_frame_id, &u16FrameID); + proto_item_append_text(iocr_item, ": FrameID:0x%x", u16FrameID); + + /* add cycle counter */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, iocr_tree, drep, + hf_pn_io_cycle_counter, &u16CycleCounter); + + u8DataStatus = tvb_get_guint8(tvb, offset); + u8TransferStatus = tvb_get_guint8(tvb, offset+1); + + /* add data status subtree */ + ds_item = proto_tree_add_uint_format(iocr_tree, hf_pn_io_data_status, + tvb, offset, 1, u8DataStatus, + "DataStatus: 0x%02x (Frame: %s and %s, Provider: %s and %s)", + u8DataStatus, + (u8DataStatus & 0x04) ? "Valid" : "Invalid", + (u8DataStatus & 0x01) ? "Primary" : "Backup", + (u8DataStatus & 0x20) ? "Ok" : "Problem", + (u8DataStatus & 0x10) ? "Run" : "Stop"); + ds_tree = proto_item_add_subtree(ds_item, ett_pn_io_data_status); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_res67, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_ok, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_operate, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_res3, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_valid, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_res1, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(ds_tree, hf_pn_io_data_status_primary, tvb, offset, 1, u8DataStatus); + + offset++; + + /* add transfer status */ + if (u8TransferStatus) { + proto_tree_add_uint_format(iocr_tree, hf_pn_io_transfer_status, tvb, + offset, 1, u8TransferStatus, + "TransferStatus: 0x%02x (ignore this frame)", u8TransferStatus); + } else { + proto_tree_add_uint_format(iocr_tree, hf_pn_io_transfer_status, tvb, + offset, 1, u8TransferStatus, + "TransferStatus: 0x%02x (OK)", u8TransferStatus); + } + offset++; + proto_item_set_len(iocr_item, offset - u32IOCRStart); + } + /* NumberOfAPIs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_number_of_apis, &u16NumberOfAPIs); + /* align to next 32 bit */ + offset = dissect_pn_padding(tvb, offset, pinfo, ar_tree, 2); + /* API */ + while (u16NumberOfAPIs--) { + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_api, &u32Api); + } + /* get the number of subblocks an dissect them */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, ar_tree, drep, hf_pn_io_number_of_ARDATAInfo, &u16NumberofEntries); + + offset = dissect_pn_padding(tvb, offset, pinfo, ar_tree, 2); + + while ((offset < i32EndOffset) && (u16NumberofEntries > 0)) { + offset = dissect_a_block(tvb, offset, pinfo, ar_tree, drep); + u16NumberofEntries--; + } + proto_item_set_len(ar_item, offset - u32ARDataStart); + } + } + return offset; +} + + +/* dissect the APIData block */ +static int +dissect_APIData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberOfAPIs; + guint32 u32Api; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* NumberOfAPIs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + + while (u16NumberOfAPIs--) { + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + } + + return offset; +} + +/* dissect the SLRData block */ +static int +dissect_SRLData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 RedundancyInfo; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + /* bit 0 ..1 EndPoint1 and EndPoint2*/ + dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_RedundancyInfo, &RedundancyInfo); + /* bit 2 .. 15 reserved */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_RedundancyInfo_reserved, &RedundancyInfo); + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + return offset; +} + +/* dissect the LogData block */ +static int +dissect_LogData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint64 u64ActualLocaltimeStamp; + guint16 u16NumberOfLogEntries; + guint64 u64LocaltimeStamp; + e_guid_t aruuid; + guint32 u32EntryDetail; + dcerpc_info di; /* fake dcerpc_info struct */ + dcerpc_call_value call_data; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + di.conformant_run = 0; + /* we need di->call_data->flags.NDR64 == 0 */ + call_data.flags = 0; + di.call_data = &call_data; + di.dcerpc_procedure_name = ""; + + /* ActualLocalTimeStamp */ + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, tree, &di, drep, + hf_pn_io_actual_local_time_stamp, &u64ActualLocaltimeStamp); + /* NumberOfLogEntries */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_log_entries, &u16NumberOfLogEntries); + + while (u16NumberOfLogEntries--) { + /* LocalTimeStamp */ + offset = dissect_dcerpc_uint64(tvb, offset, pinfo, tree, &di, drep, + hf_pn_io_local_time_stamp, &u64LocaltimeStamp); + /* ARUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ar_uuid, &aruuid); + + if (!PINFO_FD_VISITED(pinfo)) { + pn_init_append_aruuid_frame_setup_list(aruuid, pinfo->num); + } + + /* PNIOStatus */ + offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep); + /* EntryDetail */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_entry_detail, &u32EntryDetail); + } + + return offset; +} + + +/* dissect the FS Hello block */ +static int +dissect_FSHello_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32FSHelloMode; + guint32 u32FSHelloInterval; + guint32 u32FSHelloRetry; + guint32 u32FSHelloDelay; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* FSHelloMode */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fs_hello_mode, &u32FSHelloMode); + /* FSHelloInterval */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fs_hello_interval, &u32FSHelloInterval); + /* FSHelloRetry */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fs_hello_retry, &u32FSHelloRetry); + /* FSHelloDelay */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fs_hello_delay, &u32FSHelloDelay); + + proto_item_append_text(item, ": Mode:%s, Interval:%ums, Retry:%u, Delay:%ums", + val_to_str(u32FSHelloMode, pn_io_fs_hello_mode_vals, "0x%x"), + u32FSHelloInterval, u32FSHelloRetry, u32FSHelloDelay); + + return offset; +} + + +/* dissect the FS Parameter block */ +static int +dissect_FSParameter_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint32 u32FSParameterMode; + e_guid_t FSParameterUUID; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* FSParameterMode */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_fs_parameter_mode, &u32FSParameterMode); + /* FSParameterUUID */ + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_fs_parameter_uuid, &FSParameterUUID); + + proto_item_append_text(item, ": Mode:%s", + val_to_str(u32FSParameterMode, pn_io_fs_parameter_mode_vals, "0x%x")); + + return offset; +} + + + + +/* dissect the FSUDataAdjust block */ +static int +dissect_PDInterfaceFSUDataAdjust_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + tvbuff_t *new_tvb; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + u16BodyLength -= 2; + + /* sub blocks */ + new_tvb = tvb_new_subset_length(tvb, offset, u16BodyLength); + dissect_blocks(new_tvb, 0, pinfo, tree, drep); + offset += u16BodyLength; + + return offset; +} + + +/* dissect the ARFSUDataAdjust block */ +static int +dissect_ARFSUDataAdjust_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + tvbuff_t *new_tvb; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + u16BodyLength -= 2; + + /* sub blocks */ + new_tvb = tvb_new_subset_length(tvb, offset, u16BodyLength); + dissect_blocks(new_tvb, 0, pinfo, tree, drep); + offset += u16BodyLength; + + return offset; +} + +/* dissect the PE_EntityFilterData block */ +static int +dissect_PE_EntityFilterData_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberOfAPIs; + guint32 u32Api; + guint16 u16NumberOfModules; + guint16 u16SlotNr; + guint32 u32ModuleIdentNumber; + guint16 u16NumberOfSubmodules; + guint16 u16SubslotNr; + guint32 u32SubmoduleIdentNumber; + proto_item* api_item; + proto_tree* api_tree; + guint32 u32ApiStart; + proto_item* module_item; + proto_tree* module_tree; + guint32 u32ModuleStart; + proto_item* sub_item; + proto_tree* sub_tree; + guint32 u32SubStart; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + // NumberOfAPIs, + // (API, NumberOfModules, (SlotNumber, ModuleIdentNumber, NumberOfSubmodules, (SubslotNumber, SubmoduleIdentNumber)*)*)* + + /* NumberOfAPIs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + + proto_item_append_text(item, ": APIs:%u", u16NumberOfAPIs); + + while (u16NumberOfAPIs--) { + api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, ENC_NA); + api_tree = proto_item_add_subtree(api_item, ett_pn_io_api); + u32ApiStart = offset; + + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_api, &u32Api); + /* NumberOfModules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_number_of_modules, &u16NumberOfModules); + + proto_item_append_text(api_item, ": %u, Modules: %u", + u32Api, u16NumberOfModules); + + proto_item_append_text(item, ", Modules:%u", u16NumberOfModules); + + while (u16NumberOfModules--) { + module_item = proto_tree_add_item(api_tree, hf_pn_io_module_tree, tvb, offset, 0, ENC_NA); + module_tree = proto_item_add_subtree(module_item, ett_pn_io_module); + u32ModuleStart = offset; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* ModuleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_module_ident_number, &u32ModuleIdentNumber); + /* NumberOfSubmodules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_number_of_submodules, &u16NumberOfSubmodules); + + proto_item_append_text(module_item, ": Slot 0x%x, Ident: 0x%x Submodules: %u", + u16SlotNr, u32ModuleIdentNumber, + u16NumberOfSubmodules); + + proto_item_append_text(item, ", Submodules:%u", u16NumberOfSubmodules); + + while (u16NumberOfSubmodules--) { + sub_item = proto_tree_add_item(module_tree, hf_pn_io_submodule_tree, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_submodule); + u32SubStart = offset; + + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* SubmoduleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber); + + proto_item_append_text(sub_item, ": Subslot 0x%x, IdentNumber: 0x%x", + u16SubslotNr, u32SubmoduleIdentNumber); + + proto_item_set_len(sub_item, offset - u32SubStart); + } /* NumberOfSubmodules */ + + proto_item_set_len(module_item, offset - u32ModuleStart); + } + + proto_item_set_len(api_item, offset - u32ApiStart); + } + + + return offset; +} + +/* dissect the PE_EntityStatusData block */ +static int +dissect_PE_EntityStatusData_block(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, proto_item* item _U_, guint8* drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberOfAPIs; + guint32 u32Api; + guint16 u16NumberOfModules; + guint16 u16SlotNr; + guint16 u16NumberOfSubmodules; + guint16 u16SubslotNr; + proto_item* api_item; + proto_tree* api_tree; + guint32 u32ApiStart; + proto_item* module_item; + proto_tree* module_tree; + guint32 u32ModuleStart; + proto_item* sub_item; + proto_tree* sub_tree; + guint32 u32SubStart; + guint8 u8PEOperationalMode; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + // NumberOfAPIs, + // (API, NumberOfModules, (SlotNumber, NumberOfSubmodules, (SubslotNumber, PE_OperationalMode, [Padding] * a)*)*)* + + /* NumberOfAPIs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + + proto_item_append_text(item, ": APIs:%u", u16NumberOfAPIs); + + while (u16NumberOfAPIs--) { + api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, ENC_NA); + api_tree = proto_item_add_subtree(api_item, ett_pn_io_api); + u32ApiStart = offset; + + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_api, &u32Api); + /* NumberOfModules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_number_of_modules, &u16NumberOfModules); + + proto_item_append_text(api_item, ": %u, Modules: %u", + u32Api, u16NumberOfModules); + + proto_item_append_text(item, ", Modules:%u", u16NumberOfModules); + + while (u16NumberOfModules--) { + module_item = proto_tree_add_item(api_tree, hf_pn_io_module_tree, tvb, offset, 0, ENC_NA); + module_tree = proto_item_add_subtree(module_item, ett_pn_io_module); + u32ModuleStart = offset; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* NumberOfSubmodules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_number_of_submodules, &u16NumberOfSubmodules); + + proto_item_append_text(module_item, ": Slot 0x%x, Submodules: %u", + u16SlotNr, + u16NumberOfSubmodules); + + proto_item_append_text(item, ", Submodules:%u", u16NumberOfSubmodules); + + while (u16NumberOfSubmodules--) { + sub_item = proto_tree_add_item(module_tree, hf_pn_io_submodule_tree, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_submodule); + u32SubStart = offset; + + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + proto_item_append_text(sub_item, ": Subslot 0x%x", + u16SubslotNr); + + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pe_operational_mode, &u8PEOperationalMode); + + offset = dissect_pn_padding(tvb, offset, pinfo, sub_tree, 1); + + proto_item_set_len(sub_item, offset - u32SubStart); + } /* NumberOfSubmodules */ + + proto_item_set_len(module_item, offset - u32ModuleStart); + } + + proto_item_set_len(api_item, offset - u32ApiStart); + } + + + return offset; + +} + +static const char * +decode_ARType_spezial(guint16 ARType, guint16 ARAccess) +{ + if (ARType == 0x0001) + return ("IO Controller AR"); + else if (ARType == 0x0003) + return("IO Controller AR"); + else if (ARType == 0x0010) + return("IO Controller AR (RT_CLASS_3)"); + else if (ARType == 0x0020) + return("IO Controller AR (sysred/CiR)"); + else if (ARType == 0x0006) + { + if (ARAccess) /*TRUE */ + return("DeviceAccess AR"); + else + return("IO Supervisor AR"); + } + else + return("reserved"); +} + +/* dissect the ARBlockReq */ +static int +dissect_ARBlockReq_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + pnio_ar_t ** ar) +{ + guint16 u16ARType; + guint32 u32ARProperties; + gboolean have_aruuid = FALSE; + e_guid_t aruuid; + e_guid_t uuid; + guint16 u16SessionKey; + guint8 mac[6]; + guint16 u16TimeoutFactor; + guint16 u16UDPRTPort; + guint16 u16NameLength; + char *pStationName; + pnio_ar_t *par; + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16ArNumber; + guint16 u16ArResource; + guint16 u16ArReserved; + proto_item *sub_item_selector; + proto_tree *sub_tree_selector; + conversation_t *conversation; + apduStatusSwitch *apdu_status_switch = NULL; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + u32ARProperties = ((drep[0] & DREP_LITTLE_ENDIAN) + ? tvb_get_letohl (tvb, offset + 2 + 16 +2 + 6 +12) + : tvb_get_ntohl (tvb, offset + 2 + 16 +2 + 6 +12)); + + u16ARType = ((drep[0] & DREP_LITTLE_ENDIAN) + ? tvb_get_letohs (tvb, offset) + : tvb_get_ntohs (tvb, offset)); + + if (tree) { + proto_tree_add_string_format(tree, hf_pn_io_artype_req, tvb, offset, 2, + "ARType", "ARType: (0x%04x) %s ", + u16ARType, decode_ARType_spezial(u16ARType, u32ARProperties)); + } + offset = offset + 2; + + if (u16ARType == 0x0020) + { + dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, hf_pn_io_ar_uuid, &aruuid); + + sub_item = proto_tree_add_item(tree, hf_pn_io_ar_uuid, tvb, offset, 16, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_ar_info); + + proto_tree_add_item(sub_tree, hf_pn_io_ar_discriminator, tvb, offset, 6, ENC_NA); + offset += 6; + + proto_tree_add_item(sub_tree, hf_pn_io_ar_configid, tvb, offset, 8, ENC_NA); + offset += 8; + + sub_item_selector = proto_tree_add_item(sub_tree, hf_pn_io_ar_selector, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree_selector = proto_item_add_subtree(sub_item_selector, ett_pn_io_ar_info); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree_selector, drep, hf_pn_io_ar_arnumber, &u16ArNumber); + dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree_selector, drep, hf_pn_io_ar_arresource, &u16ArResource); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree_selector, drep, hf_pn_io_ar_arreserved, &u16ArReserved); + + /* When ARType==IOCARSR, then find or create conversation for this frame */ + if (!PINFO_FD_VISITED(pinfo)) { + /* Get current conversation endpoints using MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_UDP, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, if no "Ident OK" frame as been dissected yet! + * Need to switch dl_src & dl_dst, as current packet is sent by controller and not by device. + * All conversations are based on Device MAC as addr1 */ + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_UDP, 0, 0, 0); + } + + /* Try to get apdu status switch information from the conversation */ + apdu_status_switch = (apduStatusSwitch*)conversation_get_proto_data(conversation, proto_pn_io_apdu_status); + + /* If apdu status switch is null, then fill it*/ + /* If apdu status switch is not null, then update it*/ + if (apdu_status_switch == NULL) { + /* apdu status switch information is valid for whole file*/ + apdu_status_switch = wmem_new0(wmem_file_scope(), apduStatusSwitch); + copy_address_shallow(&apdu_status_switch->dl_src, conversation_key_addr1(conversation->key_ptr)); + copy_address_shallow(&apdu_status_switch->dl_dst, conversation_key_addr2(conversation->key_ptr)); + apdu_status_switch->isRedundancyActive = TRUE; + conversation_add_proto_data(conversation, proto_pn_io_apdu_status, apdu_status_switch); + } + else { + copy_address_shallow(&apdu_status_switch->dl_src, conversation_key_addr1(conversation->key_ptr)); + copy_address_shallow(&apdu_status_switch->dl_dst, conversation_key_addr2(conversation->key_ptr)); + apdu_status_switch->isRedundancyActive = TRUE; + } + } + } + else + { + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ar_uuid, &aruuid); + have_aruuid = TRUE; + } + + if (!PINFO_FD_VISITED(pinfo)) { + pn_init_append_aruuid_frame_setup_list(aruuid, pinfo->num); + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_sessionkey, &u16SessionKey); + offset = dissect_pn_mac(tvb, offset, pinfo, tree, + hf_pn_io_cminitiator_macadd, mac); + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_cminitiator_objectuuid, &uuid); + + + offset = dissect_ARProperties(tvb, offset, pinfo, tree, item, drep); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_cminitiator_activitytimeoutfactor, &u16TimeoutFactor); /* XXX - special values */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_cminitiator_udprtport, &u16UDPRTPort); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_station_name_length, &u16NameLength); + + proto_tree_add_item_ret_display_string (tree, hf_pn_io_cminitiator_station_name, tvb, offset, u16NameLength, ENC_ASCII, pinfo->pool, &pStationName); + offset += u16NameLength; + + proto_item_append_text(item, ": %s, Session:%u, MAC:%02x:%02x:%02x:%02x:%02x:%02x, Port:0x%x, Station:%s", + decode_ARType_spezial(u16ARType, u32ARProperties), + u16SessionKey, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + u16UDPRTPort, + pStationName); + + if (have_aruuid) { + par = pnio_ar_find_by_aruuid(pinfo, &aruuid); + if (par == NULL) { + par = pnio_ar_new(&aruuid); + memcpy( (void *) (&par->controllermac), mac, sizeof(par->controllermac)); + par->arType = u16ARType; /* store AR-type for filter generation */ + /*strncpy( (char *) (&par->controllername), pStationName, sizeof(par->controllername));*/ + } else { + /*expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN, "ARBlockReq: AR already existing!");*/ + } + *ar = par; + } else { + *ar = NULL; + } + + return offset; +} + + +/* dissect the ARBlockRes */ +static int +dissect_ARBlockRes_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + pnio_ar_t **ar) +{ + guint16 u16ARType; + e_guid_t uuid; + guint16 u16SessionKey; + guint8 mac[6]; + guint16 u16UDPRTPort; + pnio_ar_t *par; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_ar_type, &u16ARType); + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_ar_uuid, &uuid); + + + if (!PINFO_FD_VISITED(pinfo)) { + pn_init_append_aruuid_frame_setup_list(uuid, pinfo->num); + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_sessionkey, &u16SessionKey); + offset = dissect_pn_mac(tvb, offset, pinfo, tree, + hf_pn_io_cmresponder_macadd, mac); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_cmresponder_udprtport, &u16UDPRTPort); + + proto_item_append_text(item, ": %s, Session:%u, MAC:%02x:%02x:%02x:%02x:%02x:%02x, Port:0x%x", + val_to_str(u16ARType, pn_io_ar_type, "0x%x"), + u16SessionKey, + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + u16UDPRTPort); + + /* The value NIL indicates the usage of the implicit AR*/ + par = pnio_ar_find_by_aruuid(pinfo, &uuid); + if (par != NULL) { + memcpy( (void *) (&par->devicemac), mac, sizeof(par->controllermac)); + } + *ar = par; + + return offset; +} + + +/* dissect the IOCRBlockReq */ +static int +dissect_IOCRBlockReq_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + pnio_ar_t *ar) +{ + guint16 u16IOCRType; + guint16 u16IOCRReference; + guint16 u16LT; + guint16 u16DataLength; + guint16 u16FrameID; + guint16 u16SendClockFactor; + guint16 u16ReductionRatio; + guint16 u16Phase; + guint16 u16Sequence; + guint32 u32FrameSendOffset; + guint16 u16WatchdogFactor; + guint16 u16DataHoldFactor; + guint16 u16IOCRTagHeader; + guint8 mac[6]; + guint16 u16NumberOfAPIs; + guint32 u32Api; + guint16 u16NumberOfIODataObjectsInAPI; + guint16 u16NumberOfIODataObjectsInCR = 0U; + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16IODataObjectFrameOffset; + guint16 u16NumberOfIOCSInAPI; + guint16 u16NumberOfIOCSInCR = 0U; + guint16 u16IOCSFrameOffset; + proto_item *api_item; + proto_tree *api_tree; + guint32 u32ApiStart; + guint16 u16Tmp; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + conversation_t *conversation; + conversation_t *conversation_time_aware; + stationInfo *station_info = NULL; + iocsObject *iocs_object; + iocsObject *cmp_iocs_object; + ioDataObject *io_data_object; + ioDataObject *cmp_io_data_object; + wmem_list_frame_t *frame; + wmem_list_t *iocs_list; + + ARUUIDFrame *current_aruuid_frame = NULL; + guint32 current_aruuid = 0; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_iocr_type, &u16IOCRType); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_iocr_reference, &u16IOCRReference); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_lt, &u16LT); + + offset = dissect_IOCRProperties(tvb, offset, pinfo, tree, drep); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_data_length, &u16DataLength); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_frame_id, &u16FrameID); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_send_clock_factor, &u16SendClockFactor); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_reduction_ratio, &u16ReductionRatio); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_phase, &u16Phase); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_sequence, &u16Sequence); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_frame_send_offset, &u32FrameSendOffset); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_watchdog_factor, &u16WatchdogFactor); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_data_hold_factor, &u16DataHoldFactor); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_iocr_tag_header, &u16IOCRTagHeader); + offset = dissect_pn_mac(tvb, offset, pinfo, tree, + hf_pn_io_iocr_multicast_mac_add, mac); + + if (wmem_map_contains(pnio_time_aware_frame_map, GUINT_TO_POINTER(pinfo->num))) + { + address cyclic_mac_addr; + address iocr_mac_addr; + + set_address(&cyclic_mac_addr, AT_ETHER, 6, mac); + + iocr_mac_addr = (u16IOCRType == PN_INPUT_CR) ? pinfo->dl_dst : pinfo->dl_src; + + /* Get current conversation endpoints using MAC addresses */ + conversation_time_aware = find_conversation(pinfo->num, &cyclic_mac_addr, &iocr_mac_addr, CONVERSATION_NONE, 0, 0, 0); + + if (conversation_time_aware == NULL) { + conversation_time_aware = conversation_new(pinfo->num, &iocr_mac_addr, &cyclic_mac_addr, CONVERSATION_NONE, 0, 0, 0); + } + + conversation_add_proto_data(conversation_time_aware, proto_pn_io_time_aware_status, wmem_map_lookup(pnio_time_aware_frame_map, GUINT_TO_POINTER(pinfo->num))); + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + + proto_item_append_text(item, ": %s, Ref:0x%x, Len:%u, FrameID:0x%x, Clock:%u, Ratio:%u, Phase:%u APIs:%u", + val_to_str(u16IOCRType, pn_io_iocr_type, "0x%x"), + u16IOCRReference, u16DataLength, u16FrameID, + u16SendClockFactor, u16ReductionRatio, u16Phase, u16NumberOfAPIs); + + while (u16NumberOfAPIs--) { + api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, ENC_NA); + api_tree = proto_item_add_subtree(api_item, ett_pn_io_api); + u32ApiStart = offset; + + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_api, &u32Api); + /* NumberOfIODataObjects */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_number_of_io_data_objects, &u16NumberOfIODataObjectsInAPI); + + /* Set global Variant for Number of IO Data Objects */ + /* Notice: Handle Input & Output seperate!!! */ + if (!PINFO_FD_VISITED(pinfo)) { + /* Get current conversation endpoints using MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, if no "Ident OK" frame as been dissected yet! + * Need to switch dl_src & dl_dst, as Connect Request is sent by controller and not by device. + * All conversations are based on Device MAC as addr1 */ + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_NONE, 0, 0, 0); + } + + current_aruuid_frame = pn_find_aruuid_frame_setup(pinfo); + + if (current_aruuid_frame != NULL) { + current_aruuid = current_aruuid_frame->aruuid.data1; + if (u16IOCRType == PN_INPUT_CR) { + current_aruuid_frame->inputframe = u16FrameID; + } + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, current_aruuid); + if (station_info == NULL) { + station_info = wmem_new0(wmem_file_scope(), stationInfo); + init_pnio_rtc1_station(station_info); + conversation_add_proto_data(conversation, current_aruuid, station_info); + } + u16NumberOfIODataObjectsInCR += u16NumberOfIODataObjectsInAPI; + + pn_find_dcp_station_info(station_info, conversation); + } + + u16Tmp = u16NumberOfIODataObjectsInAPI; + while (u16Tmp--) { + sub_item = proto_tree_add_item(api_tree, hf_pn_io_io_data_object, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_io_data_object); + u32SubStart = offset; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* IODataObjectFrameOffset */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_io_data_object_frame_offset, &u16IODataObjectFrameOffset); + + proto_item_append_text(sub_item, ": Slot: 0x%x, Subslot: 0x%x FrameOffset: %u", + u16SlotNr, u16SubslotNr, u16IODataObjectFrameOffset); + + proto_item_set_len(sub_item, offset - u32SubStart); + + if (!PINFO_FD_VISITED(pinfo) && station_info != NULL) { + io_data_object = wmem_new0(wmem_file_scope(), ioDataObject); + io_data_object->slotNr = u16SlotNr; + io_data_object->subSlotNr = u16SubslotNr; + io_data_object->frameOffset = u16IODataObjectFrameOffset; + /* initial - Will be added later with Write Request */ + io_data_object->f_dest_adr = 0; + io_data_object->f_par_crc1 = 0; + io_data_object->f_src_adr = 0; + io_data_object->f_crc_seed = FALSE; + io_data_object->f_crc_len = 0; + /* Reset as a PNIO Connect Request of a known module appears */ + io_data_object->last_sb_cb = 0; + io_data_object->lastToggleBit = 0; + + if (u16IOCRType == PN_INPUT_CR) { + iocs_list = station_info->ioobject_data_in; + } + else { + iocs_list = station_info->ioobject_data_out; + } + + for (frame = wmem_list_head(iocs_list); frame != NULL; frame = wmem_list_frame_next(frame)) { + cmp_io_data_object = (ioDataObject*)wmem_list_frame_data(frame); + if (cmp_io_data_object->slotNr == u16SlotNr && cmp_io_data_object->subSlotNr == u16SubslotNr) { + /* Found identical existing object */ + break; + } + } + + if (frame == NULL) { + /* new io_object data incoming */ + wmem_list_append(iocs_list, io_data_object); + } + } + } + + /* NumberOfIOCS */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_number_of_iocs, &u16NumberOfIOCSInAPI); + + /* Set global Vairant for NumberOfIOCS */ + if (!PINFO_FD_VISITED(pinfo)) { + u16NumberOfIOCSInCR += u16NumberOfIOCSInAPI; + } + + u16Tmp = u16NumberOfIOCSInAPI; + while (u16Tmp--) { + sub_item = proto_tree_add_item(api_tree, hf_pn_io_io_cs, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_io_cs); + u32SubStart = offset; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* IOCSFrameOffset */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_iocs_frame_offset, &u16IOCSFrameOffset); + + proto_item_append_text(sub_item, ": Slot: 0x%x, Subslot: 0x%x FrameOffset: %u", + u16SlotNr, u16SubslotNr, u16IOCSFrameOffset); + + proto_item_set_len(sub_item, offset - u32SubStart); + + if (!PINFO_FD_VISITED(pinfo)) { + if (station_info != NULL) { + if (u16IOCRType == PN_INPUT_CR) { + iocs_list = station_info->iocs_data_in; + } + else { + iocs_list = station_info->iocs_data_out; + } + + for (frame = wmem_list_head(iocs_list); frame != NULL; frame = wmem_list_frame_next(frame)) { + cmp_iocs_object = (iocsObject*)wmem_list_frame_data(frame); + if (cmp_iocs_object->slotNr == u16SlotNr && cmp_iocs_object->subSlotNr == u16SubslotNr) { + /* Found identical existing object */ + break; + } + } + + if (frame == NULL) { + /* new iocs_object data incoming */ + iocs_object = wmem_new(wmem_file_scope(), iocsObject); + iocs_object->slotNr = u16SlotNr; + iocs_object->subSlotNr = u16SubslotNr; + iocs_object->frameOffset = u16IOCSFrameOffset; + wmem_list_append(iocs_list, iocs_object); + } + } + } + } + + proto_item_append_text(api_item, ": 0x%x, NumberOfIODataObjects: %u NumberOfIOCS: %u", + u32Api, u16NumberOfIODataObjectsInAPI, u16NumberOfIOCSInAPI); + + proto_item_set_len(api_item, offset - u32ApiStart); + } + + /* Update global object count */ + if (!PINFO_FD_VISITED(pinfo)) { + if (station_info != NULL) { + if (u16IOCRType == PN_INPUT_CR) { + station_info->iocsNr_in = u16NumberOfIOCSInCR; + station_info->ioDataObjectNr_in = u16NumberOfIODataObjectsInCR; + } else { + station_info->iocsNr_out = u16NumberOfIOCSInCR; + station_info->ioDataObjectNr_out = u16NumberOfIODataObjectsInCR; + } + } + } + + if (ar != NULL) { + switch (u16IOCRType) { + case(1): /* Input CR */ + if (ar->inputframeid != 0 && ar->inputframeid != u16FrameID) { + expert_add_info_format(pinfo, item, &ei_pn_io_frame_id, "IOCRBlockReq: input frameID changed from %u to %u!", ar->inputframeid, u16FrameID); + } + ar->inputframeid = u16FrameID; + break; + case(2): /* Output CR */ +#if 0 + /* will usually contain 0xffff here because the correct framid will be given in the connect.Cnf */ + if (ar->outputframeid != 0 && ar->outputframeid != u16FrameID) { + expert_add_info_format(pinfo, item, &ei_pn_io_frame_id, "IOCRBlockReq: output frameID changed from %u to %u!", ar->outputframeid, u16FrameID); + } + ar->outputframeid = u16FrameID; +#endif + break; + default: + expert_add_info_format(pinfo, item, &ei_pn_io_iocr_type, "IOCRBlockReq: IOCRType %u undecoded!", u16IOCRType); + } + } else { + expert_add_info_format(pinfo, item, &ei_pn_io_ar_info_not_found, "IOCRBlockReq: no corresponding AR found!"); + } + + return offset; +} + + +/* dissect the AlarmCRBlockReq */ +static int +dissect_AlarmCRBlockReq_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + pnio_ar_t *ar) +{ + guint16 u16AlarmCRType; + guint16 u16LT; + guint32 u32AlarmCRProperties; + guint16 u16RTATimeoutFactor; + guint16 u16RTARetries; + guint16 u16LocalAlarmReference; + guint16 u16MaxAlarmDataLength; + guint16 u16AlarmCRTagHeaderHigh; + guint16 u16AlarmCRTagHeaderLow; + proto_item *sub_item; + proto_tree *sub_tree; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_alarmcr_type, &u16AlarmCRType); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_lt, &u16LT); + + sub_item = proto_tree_add_item(tree, hf_pn_io_alarmcr_properties, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_alarmcr_properties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_alarmcr_properties_reserved, &u32AlarmCRProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_alarmcr_properties_transport, &u32AlarmCRProperties); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_alarmcr_properties_priority, &u32AlarmCRProperties); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rta_timeoutfactor, &u16RTATimeoutFactor); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rta_retries, &u16RTARetries); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_localalarmref, &u16LocalAlarmReference); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_maxalarmdatalength, &u16MaxAlarmDataLength); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_alarmcr_tagheaderhigh, &u16AlarmCRTagHeaderHigh); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_alarmcr_tagheaderlow, &u16AlarmCRTagHeaderLow); + + proto_item_append_text(item, ": %s, LT:0x%x, TFactor:%u, Retries:%u, Ref:0x%x, Len:%u Tag:0x%x/0x%x", + val_to_str(u16AlarmCRType, pn_io_alarmcr_type, "0x%x"), + u16LT, u16RTATimeoutFactor, u16RTARetries, u16LocalAlarmReference, u16MaxAlarmDataLength, + u16AlarmCRTagHeaderHigh, u16AlarmCRTagHeaderLow); + + if (ar != NULL) { + if (ar->controlleralarmref != 0xffff && ar->controlleralarmref != u16LocalAlarmReference) { + expert_add_info_format(pinfo, item, &ei_pn_io_localalarmref, "AlarmCRBlockReq: local alarm ref changed from %u to %u!", ar->controlleralarmref, u16LocalAlarmReference); + } + ar->controlleralarmref = u16LocalAlarmReference; + } else { + expert_add_info_format(pinfo, item, &ei_pn_io_ar_info_not_found, "AlarmCRBlockReq: no corresponding AR found!"); + } + + return offset; +} + + +/* dissect the AlarmCRBlockRes */ +static int +dissect_AlarmCRBlockRes_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + pnio_ar_t *ar) +{ + guint16 u16AlarmCRType; + guint16 u16LocalAlarmReference; + guint16 u16MaxAlarmDataLength; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_alarmcr_type, &u16AlarmCRType); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_localalarmref, &u16LocalAlarmReference); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_maxalarmdatalength, &u16MaxAlarmDataLength); + + proto_item_append_text(item, ": %s, Ref:0x%04x, MaxDataLen:%u", + val_to_str(u16AlarmCRType, pn_io_alarmcr_type, "0x%x"), + u16LocalAlarmReference, u16MaxAlarmDataLength); + + if (ar != NULL) { + if (ar->devicealarmref != 0xffff && ar->devicealarmref != u16LocalAlarmReference) { + expert_add_info_format(pinfo, item, &ei_pn_io_localalarmref, "AlarmCRBlockRes: local alarm ref changed from %u to %u!", ar->devicealarmref, u16LocalAlarmReference); + } + ar->devicealarmref = u16LocalAlarmReference; + } else { + expert_add_info_format(pinfo, item, &ei_pn_io_ar_info_not_found, "AlarmCRBlockRes: no corresponding AR found!"); + } + + return offset; +} + +/* dissect the ARServerBlock */ +static int +dissect_ARServerBlock(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BodyLength) +{ + guint16 u16NameLength, u16padding; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_station_name_length, &u16NameLength); + + proto_tree_add_item (tree, hf_pn_io_cminitiator_station_name, tvb, offset, u16NameLength, ENC_ASCII); + offset += u16NameLength; + /* Padding to next 4 byte alignment in this block */ + u16padding = u16BodyLength - (2 + u16NameLength); + if (u16padding > 0) + offset = dissect_pn_padding(tvb, offset, pinfo, tree, u16padding); + return offset; +} + + + +/* dissect the IOCRBlockRes */ +static int +dissect_IOCRBlockRes_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + pnio_ar_t *ar) +{ + guint16 u16IOCRType; + guint16 u16IOCRReference; + guint16 u16FrameID; + + ARUUIDFrame *current_aruuid_frame = NULL; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_iocr_type, &u16IOCRType); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_iocr_reference, &u16IOCRReference); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_frame_id, &u16FrameID); + + proto_item_append_text(item, ": %s, Ref:0x%04x, FrameID:0x%04x", + val_to_str(u16IOCRType, pn_io_iocr_type, "0x%x"), + u16IOCRReference, u16FrameID); + + if (ar != NULL) { + switch (u16IOCRType) { + case(1): /* Input CR */ + if (ar->inputframeid != 0 && ar->inputframeid != u16FrameID) { + expert_add_info_format(pinfo, item, &ei_pn_io_frame_id, "IOCRBlockRes: input frameID changed from %u to %u!", ar->inputframeid, u16FrameID); + } + ar->inputframeid = u16FrameID; + break; + case(2): /* Output CR */ + if (ar->outputframeid != 0 && ar->outputframeid != u16FrameID) { + expert_add_info_format(pinfo, item, &ei_pn_io_frame_id, "IOCRBlockRes: output frameID changed from %u to %u!", ar->outputframeid, u16FrameID); + } + ar->outputframeid = u16FrameID; + break; + default: + expert_add_info_format(pinfo, item, &ei_pn_io_iocr_type, "IOCRBlockRes: IOCRType %u undecoded!", u16IOCRType); + } + } else { + expert_add_info_format(pinfo, item, &ei_pn_io_ar_info_not_found, "IOCRBlockRes: no corresponding AR found!"); + } + + if (!PINFO_FD_VISITED(pinfo)) { + current_aruuid_frame = pn_find_aruuid_frame_setup(pinfo); + if (current_aruuid_frame != NULL) { + if (u16IOCRType == 1) { + current_aruuid_frame->inputframe = u16FrameID; + } + else if (u16IOCRType == 2) { + current_aruuid_frame->outputframe = u16FrameID; + } + } + } + + return offset; +} + + + +/* dissect the MCRBlockReq */ +static int +dissect_MCRBlockReq_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16IOCRReference; + guint32 u32AddressResolutionProperties; + guint16 u16MCITimeoutFactor; + guint16 u16NameLength; + char *pStationName; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_iocr_reference, &u16IOCRReference); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_address_resolution_properties, &u32AddressResolutionProperties); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_mci_timeout_factor, &u16MCITimeoutFactor); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_station_name_length, &u16NameLength); + + proto_tree_add_item_ret_display_string (tree, hf_pn_io_provider_station_name, tvb, offset, u16NameLength, ENC_ASCII, pinfo->pool, &pStationName); + offset += u16NameLength; + + proto_item_append_text(item, ", CRRef:%u, Properties:0x%x, TFactor:%u, Station:%s", + u16IOCRReference, u32AddressResolutionProperties, u16MCITimeoutFactor, pStationName); + + return offset; +} + + + +/* dissect the SubFrameBlock */ +static int +dissect_SubFrameBlock_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint16 u16IOCRReference; + guint8 mac[6]; + guint32 u32SubFrameData; + guint16 u16Tmp; + proto_item *sub_item; + proto_tree *sub_tree; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* IOCRReference */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_iocr_reference, &u16IOCRReference); + + /* CMInitiatorMACAdd */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, + hf_pn_io_cminitiator_macadd, mac); + + /* SubFrameData n*32 */ + u16BodyLength -= 10; + u16Tmp = u16BodyLength; + do { + sub_item = proto_tree_add_item(tree, hf_pn_io_subframe_data, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_subframe_data); + /* 31-16 reserved_2 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subframe_data_reserved2, &u32SubFrameData); + /* 15- 8 DataLength */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subframe_data_length, &u32SubFrameData); + /* 7 reserved_1 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subframe_data_reserved1, &u32SubFrameData); + /* 6-0 Position */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subframe_data_position, &u32SubFrameData); + + proto_item_append_text(sub_item, ", Length:%u, Pos:%u", + (u32SubFrameData & 0x0000FF00) >> 8, u32SubFrameData & 0x0000007F); + } while (u16Tmp -= 4); + + proto_item_append_text(item, ", CRRef:%u, %u*Data", + u16IOCRReference, u16BodyLength/4); + + return offset; +} + +/* dissect the (PD)SubFrameBlock 0x022B */ +static int +dissect_PDSubFrameBlock_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint32 u32SFIOCRProperties; + guint32 u32SubFrameData; + guint16 u16FrameID; + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16RemainingLength; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + /* FrameID */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_frame_id, &u16FrameID); + /* SFIOCRProperties */ + sub_item = proto_tree_add_item(tree, hf_pn_io_SFIOCRProperties, tvb, offset, PD_SUB_FRAME_BLOCK_FIOCR_PROPERTIES_LENGTH, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_SFIOCRProperties); + + /* dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_SFIOCRProperties, &u32SFIOCRProperties); */ + /* Bit 31: SFIOCRProperties.SFCRC16 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_SFIOCRProperties_SFCRC16, &u32SFIOCRProperties); + + /* Bit 30: SFIOCRProperties.DFPRedundantPathLayout */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_SFIOCRProperties_DFPRedundantPathLayout, &u32SFIOCRProperties); + /* Bit 29: SFIOCRProperties.DFPRedundantPathLayout */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_SFIOCRProperties_DFPType, &u32SFIOCRProperties); + /* Bit 28 - 29: SFIOCRProperties.reserved_2 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_SFIOCRProperties_reserved_2, &u32SFIOCRProperties); + /* Bit 24 - 27: SFIOCRProperties.reserved_1 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_SFIOCRProperties_reserved_1, &u32SFIOCRProperties); + /* Bit 16 - 23: SFIOCRProperties.DFPmode */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_SFIOCRProperties_DFPmode, &u32SFIOCRProperties); + /* Bit 8 - 15: SFIOCRProperties.RestartFactorForDistributedWD */ + /* 0x00 Mandatory No restart delay necessary + 0x01 - 0x09 Optional Less than 1 s restart delay + 0x0A - 0x50 Mandatory 1 s to 8 s restart delay + 0x51 - 0xFF Optional More than 8 s restart delay */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_RestartFactorForDistributedWD, &u32SFIOCRProperties); + /* bit 0..7 SFIOCRProperties.DistributedWatchDogFactor */ + offset = /* it is the last one, so advance! */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_DistributedWatchDogFactor, &u32SFIOCRProperties); + + /* SubframeData */ + u16RemainingLength = u16BodyLength - PD_SUB_FRAME_BLOCK_FIOCR_PROPERTIES_LENGTH - PD_SUB_FRAME_BLOCK_FRAME_ID_LENGTH; + while (u16RemainingLength >= PD_SUB_FRAME_BLOCK_SUB_FRAME_DATA_LENGTH) + { + guint8 Position, + DataLength; + sub_item = proto_tree_add_item(tree, hf_pn_io_subframe_data, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_subframe_data); + + /* Bit 0 - 6: SubframeData.Position */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_subframe_data_position, &u32SubFrameData); + /* Bit 7: SubframeData.reserved_1 */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_subframe_reserved1, &u32SubFrameData); + /* Bit 8 - 15: SubframeData.dataLength */ + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_subframe_data_length, &u32SubFrameData); + /* Bit 16 - 31: SubframeData.reserved_2 */ + offset = + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_subframe_reserved2, &u32SubFrameData); + Position = (guint8) (u32SubFrameData & 0x7F); /* the lower 6 bits */ + DataLength =(guint8) ((u32SubFrameData >>8) & 0x0ff); /* bit 8 to 15 */ + proto_item_append_text(sub_item, ", Length:%u (0x%x), Pos:%u", + DataLength,DataLength, Position); + u16RemainingLength = u16RemainingLength - 4; + } + return offset; +} + + +/* dissect the IRInfoBlock */ +static int +dissect_IRInfoBlock_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength _U_) +{ + guint16 u16NumberOfIOCR; + guint16 u16SubframeOffset; + guint32 u32SubframeData; + guint16 u16IOCRReference; + e_guid_t IRDataUUID; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hf_pn_io_IRData_uuid, &IRDataUUID); + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + /* Numbers of IOCRs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_iocrs, &u16NumberOfIOCR); + + while (u16NumberOfIOCR--) + { /* IOCRReference */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_iocr_reference, &u16IOCRReference); + + /* SubframeOffset 16 */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_iocr_SubframeOffset, &u16SubframeOffset); + + /* SubframeData 32 */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_iocr_SubframeData, &u32SubframeData); + } + return offset; +} + +/* dissect the SRInfoBlock */ +static int +dissect_SRInfoBlock_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength _U_) +{ + guint16 u16RedundancyDataHoldFactor; + guint32 u32sr_properties; + guint8 u8SRPropertiesMode; + proto_item *sub_item; + proto_tree *sub_tree; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_RedundancyDataHoldFactor, &u16RedundancyDataHoldFactor); + + u32sr_properties = tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN); + sub_item = proto_tree_add_item(tree, hf_pn_io_sr_properties, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_sr_properties); + + u8SRPropertiesMode = (guint8)((u32sr_properties >> 2) & 0x01); + + /* SRProperties.InputValidOnBackupAR with SRProperties.Mode == 1 */ + if (u8SRPropertiesMode) + { + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_sr_properties_InputValidOnBackupAR_with_SRProperties_Mode_1, &u32sr_properties); + } + /* SRProperties.InputValidOnBackupAR with SRProperties.Mode == 0 */ + else + { + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_sr_properties_InputValidOnBackupAR_with_SRProperties_Mode_0, &u32sr_properties); + } + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_sr_properties_Reserved_1, &u32sr_properties); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_sr_properties_Mode, &u32sr_properties); + + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_sr_properties_Reserved_2, &u32sr_properties); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, hf_pn_io_sr_properties_Reserved_3, &u32sr_properties); + return offset; +} + +/* dissect the RSInfoBlock */ +static int +dissect_RSInfoBlock_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, + guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, guint16 u16BodyLength _U_) +{ + guint32 u32RSProperties; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* Padding 2 + 2 + 1 + 1 = 6 */ + /* Therefore we need 2 byte padding to make the block u32 aligned */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_rs_properties, &u32RSProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_rs_properties_alarm_transport, &u32RSProperties); + dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_rs_properties_reserved1, &u32RSProperties); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, hf_pn_io_rs_properties_reserved2, &u32RSProperties); + + return offset; +} + +/* dissect the PDIRSubframeData block 0x022a */ +static int +dissect_PDIRSubframeData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberOfSubframeBlocks; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, hf_pn_io_NumberOfSubframeBlocks, &u16NumberOfSubframeBlocks); + + while (u16NumberOfSubframeBlocks --) + { /* dissect the Subframe Block */ + offset = dissect_a_block(tvb, offset, pinfo, /*sub_*/tree, drep); + } + + return offset; +} + +static int +dissect_ARVendorBlockReq_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength _U_) +{ + guint16 APStructureIdentifier; + guint32 gu32API; + guint32 guDataBytes; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + APStructureIdentifier = ((drep[0] & DREP_LITTLE_ENDIAN) + ? tvb_get_letohs(tvb, offset) + : tvb_get_ntohs(tvb, offset)); + + gu32API = ((drep[0] & DREP_LITTLE_ENDIAN) + ? tvb_get_letohl(tvb, offset + 2) + : tvb_get_ntohl (tvb, offset + 2)); + + if (tree) + { + if (gu32API == 0) + { + if (APStructureIdentifier <0x8000) + { + proto_tree_add_item(tree, hf_pn_io_arvendor_strucidentifier_if0_low, tvb, offset, 2, DREP_ENC_INTEGER(drep)); + } + else + { + if (APStructureIdentifier > 0x8000) + { + proto_tree_add_item(tree, hf_pn_io_arvendor_strucidentifier_if0_high, tvb, offset, 2, DREP_ENC_INTEGER(drep)); + } + else /* APStructureIdentifier == 0x8000 */ + { + proto_tree_add_item(tree, hf_pn_io_arvendor_strucidentifier_if0_is8000, tvb, offset, 2, DREP_ENC_INTEGER(drep)); + } + } + } + else + { + proto_tree_add_item(tree, hf_pn_io_arvendor_strucidentifier_not0, tvb, offset, 2, DREP_ENC_INTEGER(drep)); + } + /* API */ + proto_tree_add_item(tree, hf_pn_io_api, tvb, offset + 2, 4, DREP_ENC_INTEGER(drep)); + } + offset += 6; + if (u16BodyLength < 6 ) + return offset; /* there are no user bytes! */ + guDataBytes = u16BodyLength - 6; + + dissect_pn_user_data(tvb, offset, pinfo, tree, guDataBytes, "Data "); + return offset; +} + +/* dissect the DataDescription */ +static int +dissect_DataDescription(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, ioDataObject *tmp_io_data_object) +{ + guint16 u16DataDescription; + guint16 u16SubmoduleDataLength; + guint8 u8LengthIOCS; + guint8 u8LengthIOPS; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + conversation_t *conversation; + stationInfo *station_info = NULL; + ioDataObject *io_data_object; + wmem_list_frame_t *frame; + wmem_list_t *ioobject_list; + + ARUUIDFrame *current_aruuid_frame = NULL; + guint32 current_aruuid = 0; + + sub_item = proto_tree_add_item(tree, hf_pn_io_data_description_tree, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_data_description); + u32SubStart = offset; + + /* DataDescription */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_data_description, &u16DataDescription); + /* SubmoduleDataLength */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_submodule_data_length, &u16SubmoduleDataLength); + /* LengthIOCS */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_length_iocs, &u8LengthIOCS); + /* LengthIOPS */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_length_iops, &u8LengthIOPS); + + proto_item_append_text(sub_item, ": %s, SubmoduleDataLength: %u, LengthIOCS: %u, u8LengthIOPS: %u", + val_to_str(u16DataDescription, pn_io_data_description, "(0x%x)"), + u16SubmoduleDataLength, u8LengthIOCS, u8LengthIOPS); + proto_item_set_len(sub_item, offset - u32SubStart); + + /* Save new data for IO Data Objects */ + if (!PINFO_FD_VISITED(pinfo)) { + /* Get current conversation endpoints using MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, if no "Ident OK" frame as been dissected yet! + * Need to switch dl_src & dl_dst, as current packet is sent by controller and not by device. + * All conversations are based on Device MAC as addr1 */ + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_NONE, 0, 0, 0); + } + + current_aruuid_frame = pn_find_aruuid_frame_setup(pinfo); + + if (current_aruuid_frame != NULL) { + current_aruuid = current_aruuid_frame->aruuid.data1; + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, current_aruuid); + + if (station_info != NULL) { + pn_find_dcp_station_info(station_info, conversation); + + if (u16DataDescription == PN_INPUT_DATADESCRITPION) { + /* INPUT HANDLING */ + ioobject_list = station_info->ioobject_data_in; + } + else { + /* OUTPUT HANDLING */ + ioobject_list = station_info->ioobject_data_out; + } + + for (frame = wmem_list_head(ioobject_list); frame != NULL; frame = wmem_list_frame_next(frame)) { + io_data_object = (ioDataObject*)wmem_list_frame_data(frame); + if (io_data_object->slotNr == tmp_io_data_object->slotNr && io_data_object->subSlotNr == tmp_io_data_object->subSlotNr) { + /* Write additional data from dissect_ExpectedSubmoduleBlockReq_block() to corresponding io_data_object */ + io_data_object->api = tmp_io_data_object->api; + io_data_object->moduleIdentNr = tmp_io_data_object->moduleIdentNr; + io_data_object->subModuleIdentNr = tmp_io_data_object->subModuleIdentNr; + io_data_object->length = u16SubmoduleDataLength; + + io_data_object->moduleNameStr = wmem_strdup(wmem_file_scope(), tmp_io_data_object->moduleNameStr); + io_data_object->profisafeSupported = tmp_io_data_object->profisafeSupported; + io_data_object->discardIOXS = tmp_io_data_object->discardIOXS; + io_data_object->amountInGSDML = tmp_io_data_object->amountInGSDML; + io_data_object->fParameterIndexNr = tmp_io_data_object->fParameterIndexNr; + + break; + } + } + } + } + + return offset; +} + + +static int +resolve_pa_profile_submodule_name(ioDataObject *io_data_object) +{ + const uint32_t u32SubmoduleIdentNumber = io_data_object->subModuleIdentNr; + /* split components of submodule ident number */ + const uint8_t variant = (u32SubmoduleIdentNumber >> 24u) & 0xFFu; + const uint8_t block_object = (u32SubmoduleIdentNumber >> 16u) & 0xFFu; + const uint8_t parent_class = (u32SubmoduleIdentNumber >> 8u) & 0xFFu; + const uint8_t class = (u32SubmoduleIdentNumber) & 0xFFu; + + const gchar* parent_class_name = NULL; + const gchar* class_name = NULL; + + const gchar* block_object_name = try_val_to_str(block_object, pn_io_pa_profile_block_object_vals); + + if (block_object_name != NULL) + { + switch (block_object) + { + case PA_PROFILE_BLOCK_DAP: + if (parent_class == 0u) + { + class_name = try_val_to_str(class, pn_io_pa_profile_dap_submodule_vals); + if (class_name != NULL) + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - %s", block_object_name, class_name); + } + } + else + { + /* we have an interface or a port */ + if (class == 0u) + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "Interface %d", parent_class); + } + else + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "Port %d Interface %d", class, parent_class); + } + } + break; + + case PA_PROFILE_BLOCK_PB: + parent_class_name = try_val_to_str(parent_class, pn_io_pa_profile_physical_block_parent_class_vals); + if (parent_class_name != NULL) + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - %s", block_object_name, parent_class_name); + } + else + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - Unknown", block_object_name); + } + break; + + case PA_PROFILE_BLOCK_FB: + class_name = try_val_to_str(class, pn_io_pa_profile_function_block_class_vals); + if (class <= 2u) + { + parent_class_name = try_val_to_str(parent_class, pn_io_pa_profile_function_block_parent_class_vals); + } + else + { + parent_class_name = (class <= 4u) ? "Analog" : ""; + } + + if ((parent_class_name != NULL) && (class_name != NULL)) + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - %s %s", block_object_name, parent_class_name, class_name); + } + else + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - Unknown", block_object_name); + } + break; + + case PA_PROFILE_BLOCK_TB: + parent_class_name = try_val_to_str(parent_class, pn_io_pa_profile_transducer_block_parent_class_vals); + if (parent_class_name != NULL) + { + class_name = try_val_to_str(class, pn_io_pa_profile_transducer_block_class_vals[parent_class]); + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - %s (%s)", block_object_name, parent_class_name, class_name); + } + else + { + (void)snprintf(io_data_object->moduleNameStr, MAX_NAMELENGTH, "%s - Unknown", block_object_name); + } + break; + } + + if (variant != 0u) + { + g_strlcat (io_data_object->moduleNameStr, " (VARIANT)", MAX_NAMELENGTH); + } + + return 1; + } + else + { + return 0; + } +} + +/* dissect the ExpectedSubmoduleBlockReq */ +static int +dissect_ExpectedSubmoduleBlockReq_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberOfAPIs; + guint32 u32Api; + guint16 u16SlotNr; + guint32 u32ModuleIdentNumber; + guint16 u16ModuleProperties; + guint16 u16NumberOfSubmodules; + guint16 u16SubslotNr; + guint32 u32SubmoduleIdentNumber; + guint16 u16SubmoduleProperties; + proto_item *api_item; + proto_tree *api_tree; + guint32 u32ApiStart; + proto_item *sub_item; + proto_tree *sub_tree; + proto_item *submodule_item; + proto_tree *submodule_tree; + guint32 u32SubStart; + + /* Variable for the search of gsd file */ + const char vendorIdStr[] = "VendorID=\""; + const char deviceIdStr[] = "DeviceID=\""; + const char moduleStr[] = "ModuleIdentNumber=\""; + const char subModuleStr[] = "SubmoduleIdentNumber=\""; + const char profisafeStr[] = "PROFIsafeSupported=\"true\""; + const char fParameterStr[] = "pool, MAX_NAMELENGTH); + convertStr[0] = '\0'; + pch = (gchar*)wmem_alloc(pinfo->pool, MAX_LINE_LENGTH); + pch[0] = '\0'; + puffer = (gchar*)wmem_alloc(pinfo->pool, MAX_LINE_LENGTH); + puffer[0] = '\0'; + temp = (gchar*)wmem_alloc(pinfo->pool, MAX_LINE_LENGTH); + temp[0] = '\0'; + + /* Initial */ + io_data_object = wmem_new0(wmem_file_scope(), ioDataObject); + io_data_object->profisafeSupported = FALSE; + io_data_object->moduleNameStr = (gchar*)wmem_alloc(wmem_file_scope(), MAX_NAMELENGTH); + (void) g_strlcpy(io_data_object->moduleNameStr, "Unknown", MAX_NAMELENGTH); + vendorMatch = FALSE; + deviceMatch = FALSE; + gsdmlFoundFlag = FALSE; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + + proto_item_append_text(item, ": APIs:%u", u16NumberOfAPIs); + + + /* Get current conversation endpoints using MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, if no "Ident OK" frame as been dissected yet! + * Need to switch dl_src & dl_dst, as current packet is sent by controller and not by device. + * All conversations are based on Device MAC as addr1 */ + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_NONE, 0, 0, 0); + } + + current_aruuid_frame = pn_find_aruuid_frame_setup(pinfo); + + if (current_aruuid_frame != NULL) { + current_aruuid = current_aruuid_frame->aruuid.data1; + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, current_aruuid); + + if (station_info != NULL) { + pn_find_dcp_station_info(station_info, conversation); + + station_info->gsdFound = FALSE; + station_info->gsdPathLength = FALSE; + + /* Set searchVendorID and searchDeviceID for GSDfile search */ + searchVendorID = station_info->u16Vendor_id; + searchDeviceID = station_info->u16Device_id; + + /* Use the given GSD-file networkpath of the PNIO-Preference */ + if(pnio_ps_networkpath[0] != '\0') { /* check the length of the given networkpath (array overflow protection) */ + station_info->gsdPathLength = TRUE; + + if ((dir = g_dir_open(pnio_ps_networkpath, 0, NULL)) != NULL) { + /* Find all GSD-files within directory */ + while ((filename = g_dir_read_name(dir)) != NULL) { + + /* ---- complete the path to open a GSD-file ---- */ + diropen = wmem_strdup_printf(pinfo->pool, "%s" G_DIR_SEPARATOR_S "%s", pnio_ps_networkpath, filename); + + /* ---- Open the found GSD-file ---- */ + fp = ws_fopen(diropen, "r"); + + if(fp != NULL) { + /* ---- Get VendorID & DeviceID ---- */ + while(pn_fgets(puffer, MAX_LINE_LENGTH, fp, pinfo->pool) != NULL) { + /* ----- VendorID ------ */ + if((strstr(puffer, vendorIdStr)) != NULL) { + memset (convertStr, 0, sizeof(*convertStr)); + pch = strstr(puffer, vendorIdStr); + if (pch!= NULL && sscanf(pch, "VendorID=\"%199[^\"]", convertStr) == 1) { + read_vendor_id = (guint32) strtoul (convertStr, NULL, 0); + + if(read_vendor_id == searchVendorID) { + vendorMatch = TRUE; /* found correct VendorID */ + } + } + } + + /* ----- DeviceID ------ */ + if((strstr(puffer, deviceIdStr)) != NULL) { + memset(convertStr, 0, sizeof(*convertStr)); + pch = strstr(puffer, deviceIdStr); + if (pch != NULL && sscanf(pch, "DeviceID=\"%199[^\"]", convertStr) == 1) { + read_device_id = (guint32)strtoul(convertStr, NULL, 0); + + if(read_device_id == searchDeviceID) { + deviceMatch = TRUE; /* found correct DeviceID */ + } + } + } + } + + fclose(fp); + fp = NULL; + + if(vendorMatch && deviceMatch) { + break; /* Found correct GSD-file! -> Break the searchloop */ + } + else { + /* Couldn't find the correct GSD-file to the corresponding device */ + vendorMatch = FALSE; + deviceMatch = FALSE; + gsdmlFoundFlag = FALSE; + diropen = ""; /* reset array for next search */ + } + } + } + + g_dir_close(dir); + } + + /* ---- Found the correct GSD-file -> set Flag and save the completed path ---- */ + if(vendorMatch && deviceMatch) { + gsdmlFoundFlag = TRUE; + station_info->gsdFound = TRUE; + station_info->gsdLocation = wmem_strdup(wmem_file_scope(), diropen); + } + else { + /* Copy searchpath to array for a detailed output message in cyclic data dissection */ + station_info->gsdLocation = wmem_strdup_printf(wmem_file_scope(), "%s" G_DIR_SEPARATOR_S "*.xml", pnio_ps_networkpath); + } + } + else { + /* will be used later on in cyclic RTC1 data dissection for detailed output message */ + station_info->gsdPathLength = FALSE; + } + } + + while (u16NumberOfAPIs--) { + api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, ENC_NA); + api_tree = proto_item_add_subtree(api_item, ett_pn_io_api); + u32ApiStart = offset; + + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_api, &u32Api); + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* ModuleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_module_ident_number, &u32ModuleIdentNumber); + /* ModuleProperties */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_module_properties, &u16ModuleProperties); + /* NumberOfSubmodules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_number_of_submodules, &u16NumberOfSubmodules); + + proto_item_append_text(api_item, ": %u, Slot:0x%x, IdentNumber:0x%x Properties:0x%x Submodules:%u", + u32Api, u16SlotNr, u32ModuleIdentNumber, u16ModuleProperties, u16NumberOfSubmodules); + + proto_item_append_text(item, ", Submodules:%u", u16NumberOfSubmodules); + + while (u16NumberOfSubmodules--) { + sub_item = proto_tree_add_item(api_tree, hf_pn_io_submodule_tree, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_submodule); + u32SubStart = offset; + + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* SubmoduleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber); + /* SubmoduleProperties */ + submodule_item = proto_tree_add_item(sub_tree, hf_pn_io_submodule_properties, tvb, offset, 2, ENC_BIG_ENDIAN); + submodule_tree = proto_item_add_subtree(submodule_item, ett_pn_io_submodule_properties); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_properties_reserved, &u16SubmoduleProperties); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_properties_discard_ioxs, &u16SubmoduleProperties); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_properties_reduce_output_submodule_data_length, &u16SubmoduleProperties); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_properties_reduce_input_submodule_data_length, &u16SubmoduleProperties); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_properties_shared_input, &u16SubmoduleProperties); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_properties_type, &u16SubmoduleProperties); + + io_data_object->api = u32Api; + io_data_object->slotNr = u16SlotNr; + io_data_object->subSlotNr = u16SubslotNr; + io_data_object->moduleIdentNr = u32ModuleIdentNumber; + io_data_object->subModuleIdentNr = u32SubmoduleIdentNumber; + io_data_object->discardIOXS = u16SubmoduleProperties & 0x0020; + + /* Before searching the GSD, check if we have a PA Profile 4.02 submodule. If yes + then the submodule's name is defined in the specification and can be resolved + without the GSD. + We still read the GSD afterwards, in case the user wants to override the specification's + names with a GSD. + Most PA Profile submodules are located in API 0x9700, but the DAP and the interfaces/ports + are located in API 0 per PROFINET specification, so we need to filter also on the DAP module + ident number. + */ + if ((io_data_object->api == PA_PROFILE_API) || + ((io_data_object->moduleIdentNr & PA_PROFILE_DAP_MASK) == PA_PROFILE_DAP_IDENT)) + { + resolve_pa_profile_submodule_name(io_data_object); + } + + + /* Search the moduleID and subModuleID, find if PROFIsafe and also search for F-Par. Indexnumber + * --------------------------------------------------------------------------------------------- + * Speical case: Module has several ModuleIdentNr. in one GSD-file + * Also with the given parameters of wireshark, some modules were completely equal. For this + * special case a compromise for this problem has been made, to set the module name will + * be more generally displayed. + * Also this searchloop will find the F-Parameter Indexnumber, so that Wireshark is able to + * dissect those F-Parameters correctly, as this index can change between the vendors. + */ + + io_data_object->amountInGSDML = 0; + io_data_object->fParameterIndexNr = 0; + io_data_object->profisafeSupported = FALSE; + + if (diropen != NULL) { + fp = ws_fopen(diropen, "r"); + } + else { + fp = NULL; + } + if(fp != NULL && gsdmlFoundFlag) { + fseek(fp, 0, SEEK_SET); + + /* Find Indexnumber for fParameter */ + while(pn_fgets(temp, MAX_LINE_LENGTH, fp, pinfo->pool) != NULL) { + if((strstr(temp, fParameterStr)) != NULL) { + memset (convertStr, 0, sizeof(*convertStr)); + + pch = strstr(temp, fParameterIndexStr); + if (pch != NULL && sscanf(pch, "Index=\"%199[^\"]", convertStr) == 1) { + io_data_object->fParameterIndexNr = (guint32)strtoul(convertStr, NULL, 0); + } + break; /* found Indexnumber -> break search loop */ + } + } + + memset (temp, 0, sizeof(*temp)); + fseek(fp, 0, SEEK_SET); /* Set filepointer to the beginning */ + + while(pn_fgets(temp, MAX_LINE_LENGTH, fp, pinfo->pool) != NULL) { + if((strstr(temp, moduleStr)) != NULL) { /* find the String "ModuleIdentNumber=" */ + memset (convertStr, 0, sizeof(*convertStr)); + pch = strstr(temp, moduleStr); /* search for "ModuleIdentNumber=\"" within GSD-file */ + if (pch != NULL && sscanf(pch, "ModuleIdentNumber=\"%199[^\"]", convertStr) == 1) { /* Change format of Value string-->numeric string */ + read_module_id = (guint32)strtoul(convertStr, NULL, 0); /* Change numeric string --> unsigned long; read_module_id contains the Value of the ModuleIdentNumber */ + + /* If the found ModuleID matches with the wanted ModuleID, search for the Submodule and break */ + if (read_module_id == io_data_object->moduleIdentNr) { + ++io_data_object->amountInGSDML; /* Save the amount of same (!) Module- & SubmoduleIdentNr in one GSD-file */ + + while(pn_fgets(temp, MAX_LINE_LENGTH, fp, pinfo->pool) != NULL) { + if((strstr(temp, moduleNameInfo)) != NULL) { /* find the String "= 0) { + while (pn_fgets(temp, MAX_LINE_LENGTH, fp, pinfo->pool) != NULL && io_data_object->amountInGSDML == 1) { + /* Find a String with the saved TextID and with a fitting value for it in the same line. This value is the name of the Module! */ + if(((strstr(temp, tmp_moduletext)) != NULL) && ((strstr(temp, moduleValueInfo)) != NULL)) { + pch = strstr(temp, moduleValueInfo); + if (pch != NULL && sscanf(pch, "Value=\"%199[^\"]", io_data_object->moduleNameStr) == 1) + break; /* Found the name of the module */ + } + } + + fseek(fp, filePosRecord, SEEK_SET); /* set filepointer to the correct TextID */ + } + } + + /* Search for Submoduleidentnumber in GSD-file */ + if((strstr(temp, subModuleStr)) != NULL) { + memset (convertStr, 0, sizeof(*convertStr)); + pch = strstr(temp, subModuleStr); + if (pch != NULL && sscanf(pch, "SubmoduleIdentNumber=\"%199[^\"]", convertStr) == 1) { + read_submodule_id = (guint32) strtoul (convertStr, NULL, 0); /* read_submodule_id contains the Value of the SubModuleIdentNumber */ + + /* Find "PROFIsafeSupported" flag of the module in GSD-file */ + if(read_submodule_id == io_data_object->subModuleIdentNr) { + if((strstr(temp, profisafeStr)) != NULL) { + io_data_object->profisafeSupported = TRUE; /* flag is in the same line as SubmoduleIdentNr */ + break; + } + else { /* flag is not in the same line as Submoduleidentnumber -> search for it */ + while(pn_fgets(temp, MAX_LINE_LENGTH, fp, pinfo->pool) != NULL) { + if((strstr(temp, profisafeStr)) != NULL) { + io_data_object->profisafeSupported = TRUE; + break; /* Found the PROFIsafeSupported flag of the module */ + } + + else if((strstr(temp, ">")) != NULL) { + break; + } + } + } + break; /* Found the PROFIsafe Module */ + } + } + } + } + } + } + } + } + + fclose(fp); + fp = NULL; + } + + if(fp != NULL) + { + fclose(fp); + fp = NULL; + } + + switch (u16SubmoduleProperties & 0x03) { + case(0x00): /* no input and no output data (one Input DataDescription Block follows) */ + offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep, io_data_object); + break; + case(0x01): /* input data (one Input DataDescription Block follows) */ + offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep, io_data_object); + break; + case(0x02): /* output data (one Output DataDescription Block follows) */ + offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep, io_data_object); + break; + case(0x03): /* input and output data (one Input and one Output DataDescription Block follows) */ + offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep, io_data_object); + offset = dissect_DataDescription(tvb, offset, pinfo, sub_tree, drep, io_data_object); + break; + default: /* will not execute because of the line preceding the switch */ + break; + } + + proto_item_append_text(sub_item, ": Subslot:0x%x, Ident:0x%x Properties:0x%x", + u16SubslotNr, u32SubmoduleIdentNumber, u16SubmoduleProperties); + proto_item_set_len(sub_item, offset - u32SubStart); + } + + proto_item_set_len(api_item, offset - u32ApiStart); + } + + return offset; +} + + +/* dissect the ModuleDiffBlock */ +static int +dissect_ModuleDiffBlock_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16NumberOfAPIs; + guint32 u32Api; + guint16 u16NumberOfModules; + guint16 u16SlotNr; + guint32 u32ModuleIdentNumber; + guint16 u16ModuleState; + guint16 u16NumberOfSubmodules; + guint16 u16SubslotNr; + guint32 u32SubmoduleIdentNumber; + guint16 u16SubmoduleState; + proto_item *api_item; + proto_tree *api_tree; + guint32 u32ApiStart; + proto_item *module_item; + proto_tree *module_tree; + guint32 u32ModuleStart; + proto_item *sub_item; + proto_tree *sub_tree; + proto_item *submodule_item; + proto_tree *submodule_tree; + guint32 u32SubStart; + + conversation_t *conversation; + stationInfo *station_info; + wmem_list_frame_t *frame; + moduleDiffInfo *module_diff_info; + moduleDiffInfo *cmp_module_diff_info; + + ARUUIDFrame *current_aruuid_frame = NULL; + guint32 current_aruuid = 0; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* NumberOfAPIs */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_number_of_apis, &u16NumberOfAPIs); + + proto_item_append_text(item, ": APIs:%u", u16NumberOfAPIs); + + while (u16NumberOfAPIs--) { + api_item = proto_tree_add_item(tree, hf_pn_io_api_tree, tvb, offset, 0, ENC_NA); + api_tree = proto_item_add_subtree(api_item, ett_pn_io_api); + u32ApiStart = offset; + + /* API */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_api, &u32Api); + /* NumberOfModules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, api_tree, drep, + hf_pn_io_number_of_modules, &u16NumberOfModules); + + proto_item_append_text(api_item, ": %u, Modules: %u", + u32Api, u16NumberOfModules); + + proto_item_append_text(item, ", Modules:%u", u16NumberOfModules); + + while (u16NumberOfModules--) { + module_item = proto_tree_add_item(api_tree, hf_pn_io_module_tree, tvb, offset, 0, ENC_NA); + module_tree = proto_item_add_subtree(module_item, ett_pn_io_module); + u32ModuleStart = offset; + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* ModuleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_module_ident_number, &u32ModuleIdentNumber); + /* ModuleState */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_module_state, &u16ModuleState); + /* NumberOfSubmodules */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, module_tree, drep, + hf_pn_io_number_of_submodules, &u16NumberOfSubmodules); + + proto_item_append_text(module_item, ": Slot 0x%x, Ident: 0x%x State: %s Submodules: %u", + u16SlotNr, u32ModuleIdentNumber, + val_to_str(u16ModuleState, pn_io_module_state, "(0x%x)"), + u16NumberOfSubmodules); + + + if (!PINFO_FD_VISITED(pinfo)) { + /* Get current conversation endpoints using MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + } + + current_aruuid_frame = pn_find_aruuid_frame_setup(pinfo); + + if (current_aruuid_frame != NULL) { + current_aruuid = current_aruuid_frame->aruuid.data1; + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, current_aruuid); + + if (station_info != NULL) { + pn_find_dcp_station_info(station_info, conversation); + + for (frame = wmem_list_head(station_info->diff_module); frame != NULL; frame = wmem_list_frame_next(frame)) { + cmp_module_diff_info = (moduleDiffInfo*)wmem_list_frame_data(frame); + if (cmp_module_diff_info->slotNr == u16SlotNr) { + /* Found identical existing object */ + break; + } + } + + if (frame == NULL) { + /* new diffModuleInfo data incoming */ + module_diff_info = wmem_new(wmem_file_scope(), moduleDiffInfo); + module_diff_info->slotNr = u16SlotNr; + module_diff_info->modulID = u32ModuleIdentNumber; + wmem_list_append(station_info->diff_module, module_diff_info); + } + } + } + + proto_item_append_text(item, ", Submodules:%u", u16NumberOfSubmodules); + + while (u16NumberOfSubmodules--) { + sub_item = proto_tree_add_item(module_tree, hf_pn_io_submodule_tree, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_submodule); + u32SubStart = offset; + + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + /* SubmoduleIdentNumber */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_submodule_ident_number, &u32SubmoduleIdentNumber); + /* SubmoduleState */ + submodule_item = proto_tree_add_item(sub_tree, hf_pn_io_submodule_state, tvb, offset, 2, ENC_BIG_ENDIAN); + submodule_tree = proto_item_add_subtree(submodule_item, ett_pn_io_submodule_state); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_format_indicator, &u16SubmoduleState); + if (u16SubmoduleState & 0x8000) { + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_ident_info, &u16SubmoduleState); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_ar_info, &u16SubmoduleState); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_fault, &u16SubmoduleState); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_maintenance_demanded, &u16SubmoduleState); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_maintenance_required, &u16SubmoduleState); + dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_advice, &u16SubmoduleState); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_add_info, &u16SubmoduleState); + } else { + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, submodule_tree, drep, + hf_pn_io_submodule_state_detail, &u16SubmoduleState); + } + + proto_item_append_text(sub_item, ": Subslot 0x%x, IdentNumber: 0x%x, State: 0x%x", + u16SubslotNr, u32SubmoduleIdentNumber, u16SubmoduleState); + + proto_item_set_len(sub_item, offset - u32SubStart); + } /* NumberOfSubmodules */ + + proto_item_set_len(module_item, offset - u32ModuleStart); + } + + proto_item_set_len(api_item, offset - u32ApiStart); + } + + return offset; +} + + +/* dissect the IsochronousModeData block */ +static int +dissect_IsochronousModeData_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + guint16 u16SlotNr; + guint16 u16SubslotNr; + guint16 u16ControllerApplicationCycleFactor; + guint16 u16TimeDataCycle; + guint32 u32TimeIOInput; + guint32 u32TimeIOOutput; + guint32 u32TimeIOInputValid; + guint32 u32TimeIOOutputValid; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* SlotNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + /* Subslotnumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + /* ControllerApplicationCycleFactor */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_controller_appl_cycle_factor, &u16ControllerApplicationCycleFactor); + /* TimeDataCycle */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_time_data_cycle, &u16TimeDataCycle); + /* TimeIOInput (ns) */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_time_io_input, &u32TimeIOInput); + /* TimeIOOutput (ns) */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_time_io_output, &u32TimeIOOutput); + /* TimeIOInputValid (ns) */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_time_io_input_valid, &u32TimeIOInputValid); + /* TimeIOOutputValid (ns) */ + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_time_io_output_valid, &u32TimeIOOutputValid); + + + return offset+1; +} + +static int +dissect_CommunityName_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, const guint8 *drep _U_, int hfindex) +{ + guint8 u8CommunityNameLength; + proto_item* sub_item; + proto_item* sub_tree; + + /* CommunityNameLength */ + u8CommunityNameLength = tvb_get_guint8(tvb, offset); + sub_item = proto_tree_add_item(tree, hfindex, tvb, offset, u8CommunityNameLength + 1, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_snmp_command_name); + + proto_tree_add_item(sub_tree, hf_pn_io_snmp_community_name_length, tvb, offset, 1, DREP_ENC_INTEGER(drep)); + offset += 1; + + /* community Name */ + proto_tree_add_item(sub_tree, hf_pn_io_snmp_community_name, tvb, offset, u8CommunityNameLength, ENC_ASCII | ENC_NA); + + proto_item_append_text(sub_item, ": %s", + tvb_get_string_enc(wmem_packet_scope(), tvb, offset, u8CommunityNameLength, ENC_ASCII|ENC_NA)); + + offset += u8CommunityNameLength; + return offset; +} + +/* dissect the CIMSNMPAdjust block */ +static int +dissect_CIMSNMPAdjust_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint16 u16StartsAtOffset = offset; + guint16 u16padding; + + if (u8BlockVersionHigh!=1 || u8BlockVersionLow!=0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* SNMPControl */ + proto_tree_add_item(tree, hf_pn_io_snmp_control, tvb, offset, 2, DREP_ENC_INTEGER(drep)); + offset += 2; + + offset = dissect_CommunityName_block(tvb, offset, pinfo, tree, drep, hf_pn_io_snmp_read_community_name); + offset = dissect_CommunityName_block(tvb, offset, pinfo, tree, drep, hf_pn_io_snmp_write_community_name); + + u16padding = u16BodyLength - (offset - u16StartsAtOffset); + if (u16padding > 0) + offset = dissect_pn_padding(tvb, offset, pinfo, tree, u16padding); + + return offset; +} + +/* dissect the MultipleBlockHeader block */ +static int +dissect_MultipleBlockHeader_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16BodyLength) +{ + guint32 u32Api; + guint16 u16SlotNr; + guint16 u16SubslotNr; + tvbuff_t *new_tvb; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + proto_item_append_text(item, ": Api:0x%x Slot:%u Subslot:0x%x", + u32Api, u16SlotNr, u16SubslotNr); + + new_tvb = tvb_new_subset_length(tvb, offset, u16BodyLength-10); + offset = dissect_blocks(new_tvb, 0, pinfo, tree, drep); + + /*offset += u16BodyLength;*/ + + return offset; +} + +/* dissect Combined Object Container Content block */ +static int +dissect_COContainerContent_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16Index, guint32 *u32RecDataLen, pnio_ar_t **ar) +{ + guint32 u32Api; + guint16 u16SlotNr; + guint16 u16SubslotNr; + + if(u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, tree, drep, + hf_pn_io_api, &u32Api); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_slot_nr, &u16SlotNr); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_subslot_nr, &u16SubslotNr); + + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 2); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_index, &u16Index); + + proto_item_append_text(item, ": Api:0x%x Slot:%u Subslot:0x%x Index:0x%x", + u32Api, u16SlotNr, u16SubslotNr, u16Index); + + if(u16Index != 0x80B0) { + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, u32RecDataLen, ar); + } + + return offset; +} + + +static const gchar * +indexReservedForProfiles(guint16 u16Index) +{ + /* "reserved for profiles" */ + if (u16Index >= 0xb000 && u16Index <= 0xbfff) { + return "Reserved for Profiles (subslot specific)"; + } + if (u16Index >= 0xd000 && u16Index <= 0xdfff) { + return "Reserved for Profiles (slot specific)"; + } + if (u16Index >= 0xec00 && u16Index <= 0xefff) { + return "Reserved for Profiles (AR specific)"; + } + if (u16Index >= 0xf400 && u16Index <= 0xf7ff) { + return "Reserved for Profiles (API specific)"; + } + if (u16Index >= 0xfc00 /* up to 0xffff */) { + return "Reserved for Profiles (device specific)"; + } + + return NULL; +} + + +/* dissect the RecordDataReadQuery block */ +static int +dissect_RecordDataReadQuery_block(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, proto_item *item _U_, guint8 *drep _U_, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow, + guint16 u16Index, guint16 u16BodyLength) +{ + const gchar *userProfile; + + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + /* user specified format? */ + if (u16Index < 0x8000) { + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, u16BodyLength, "User Specified Data"); + return offset; + } + + /* "reserved for profiles"? */ + userProfile = indexReservedForProfiles(u16Index); + if (userProfile != NULL) { + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, u16BodyLength, userProfile); + return offset; + } + + return dissect_pn_undecoded(tvb, offset, pinfo, tree, u16BodyLength); +} + +/* dissect the RS_GetEvent block */ +static int +dissect_RS_GetEvent_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, + guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + offset = dissect_RS_EventInfo(tvb, offset, pinfo, tree, drep); + return offset; +} + +/* dissect the RS_AdjustControl */ +static int +dissect_RS_AdjustControl(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep, + guint16 *u16RSBodyLength, guint16 *u16RSBlockType) +{ + guint16 u16ChannelNumber; + guint16 u16SoEMaxScanDelay; + proto_item *sub_item; + proto_tree *sub_tree; + guint8 u8SoEAdjustSpecifierReserved; + guint8 u8SoEAdjustSpecifierIndicent; + + switch (*u16RSBlockType) { + case(0xc010): /* SoE_DigitalInputObserver */ + + /* ChannelNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_channel_number, &u16ChannelNumber); + + /* SoE_MaxScanDelay */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_soe_max_scan_delay, &u16SoEMaxScanDelay); + + /* SoE_AdjustSpecifier */ + sub_item = proto_tree_add_item(tree, hf_pn_io_soe_adjust_specifier, tvb, offset, 1, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_soe_adjust_specifier); + + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_soe_adjust_specifier_reserved, &u8SoEAdjustSpecifierReserved); + + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_soe_adjust_specifier_incident, &u8SoEAdjustSpecifierIndicent); + + /* Padding 2 + 2 + 1 = 5 */ + /* Therefore we need 3 byte padding to make the block u32 aligned */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 3); + break; + default: + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, *u16RSBodyLength, "UserData"); + break; + } + return offset; +} + +/* dissect the RS_AdjustBlock */ +static int +dissect_RS_AdjustBlock(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + + guint16 u16RSBodyLength; + guint16 u16RSBlockType; + + sub_item = proto_tree_add_item(tree, hf_pn_io_rs_adjust_block, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_rs_adjust_block); + + /* RS_BlockHeader */ + offset = dissect_RS_BlockHeader(tvb, offset, pinfo, sub_tree, sub_item, drep, + &u16RSBodyLength, &u16RSBlockType); + + /* RS_AdjustControl */ + offset = dissect_RS_AdjustControl(tvb, offset, pinfo, sub_tree, drep, + &u16RSBodyLength, &u16RSBlockType); + + return offset; +} + +/* dissect the RS_AdjustInfo */ +static int +dissect_RS_AdjustInfo(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16NumberofEntries; + + sub_item = proto_tree_add_item(tree, hf_pn_io_rs_adjust_info, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_rs_adjust_info); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_number_of_rs_event_info, &u16NumberofEntries); + + while (u16NumberofEntries > 0) { + u16NumberofEntries--; + offset = dissect_RS_AdjustBlock(tvb, offset, pinfo, sub_tree, drep); + } + return offset; +} + +/* dissect the RS_AdjustObserver block */ +static int +dissect_RS_AdjustObserver_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, + guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + offset = dissect_RS_AdjustInfo(tvb, offset, pinfo, tree, drep); + return offset; +} + +static int +dissect_RS_AckInfo(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep) +{ + guint16 u16RSSpecifierSequenceNumber; + + /* RS_Specifier.SequenceNumber */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_io_rs_specifier_sequence, &u16RSSpecifierSequenceNumber); + + return offset; +} + +/* dissect the RS_AckEvent block */ +static int +dissect_RS_AckEvent_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 *drep, + guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_io_block_version, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + offset = dissect_RS_AckInfo(tvb, offset, pinfo, tree, drep); + return offset; +} + +/* dissect one PN-IO block (depending on the block type) */ +static int +dissect_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 *u16Index, guint32 *u32RecDataLen, pnio_ar_t **ar) +{ + guint16 u16BlockType; + guint16 u16BlockLength; + guint8 u8BlockVersionHigh; + guint8 u8BlockVersionLow; + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + guint16 u16BodyLength; + proto_item *header_item; + proto_tree *header_tree; + gint remainingBytes; + + /* from here, we only have big endian (network byte ordering)!!! */ + drep[0] &= ~DREP_LITTLE_ENDIAN; + + sub_item = proto_tree_add_item(tree, hf_pn_io_block, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_block); + u32SubStart = offset; + + header_item = proto_tree_add_item(sub_tree, hf_pn_io_block_header, tvb, offset, 6, ENC_NA); + header_tree = proto_item_add_subtree(header_item, ett_pn_io_block_header); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, header_tree, drep, + hf_pn_io_block_type, &u16BlockType); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, header_tree, drep, + hf_pn_io_block_length, &u16BlockLength); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, header_tree, drep, + hf_pn_io_block_version_high, &u8BlockVersionHigh); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, header_tree, drep, + hf_pn_io_block_version_low, &u8BlockVersionLow); + + proto_item_append_text(header_item, ": Type=%s, Length=%u(+4), Version=%u.%u", + val_to_str(u16BlockType, pn_io_block_type, "Unknown (0x%04x)"), + u16BlockLength, u8BlockVersionHigh, u8BlockVersionLow); + + proto_item_set_text(sub_item, "%s", + val_to_str(u16BlockType, pn_io_block_type, "Unknown (0x%04x)")); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", + val_to_str_const(u16BlockType, pn_io_block_type, "Unknown")); + + /* block length is without type and length fields, but with version field */ + /* as it's already dissected, remove it */ + u16BodyLength = u16BlockLength - 2; + remainingBytes = tvb_reported_length_remaining(tvb, offset); + if (remainingBytes < 0) + remainingBytes = 0; + if (remainingBytes +2 < u16BodyLength) + { + proto_item_append_text(sub_item, " Block_Length: %d greater than remaining Bytes, trying with Blocklen = remaining (%d)", u16BodyLength, remainingBytes); + u16BodyLength = remainingBytes; + } + switch (u16BlockType) { + case(0x0001): + case(0x0002): + dissect_AlarmNotification_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16BodyLength); + break; + case(0x0008): + dissect_IODWriteReqHeader_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16Index, u32RecDataLen, ar); + break; + case(0x0009): + dissect_IODReadReqHeader_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16Index, u32RecDataLen, ar); + break; + case(0x0010): + dissect_DiagnosisData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16BodyLength); + break; + case(0x0012): /* ExpectedIdentificationData */ + case(0x0013): /* RealIdentificationData */ + dissect_IdentificationData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0014): + dissect_SubstituteValue_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16BodyLength); + break; + case(0x0015): + dissect_RecordInputDataObjectElement_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0016): + dissect_RecordOutputDataObjectElement_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + /* 0x0017 reserved */ + case(0x0018): + dissect_ARData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0019): + dissect_LogData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x001A): + dissect_APIData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x001B): + dissect_SRLData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0020): + dissect_IandM0_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0021): + dissect_IandM1_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0022): + dissect_IandM2_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0023): + dissect_IandM3_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0024): + dissect_IandM4_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0025): + dissect_IandM5_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh,u8BlockVersionLow); + break; + case(0x0030): + dissect_IandM0FilterData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0031): + dissect_IandM0FilterData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0032): + dissect_IandM0FilterData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0034): + dissect_IandM5Data_block(tvb, offset, pinfo, sub_tree, sub_item, drep); + break; + case(0x0035): + dissect_AssetManagementData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0036): + dissect_AM_FullInformation_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0037): + dissect_AM_HardwareOnlyInformation_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0038): + dissect_AM_FirmwareOnlyInformation_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0101): + dissect_ARBlockReq_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + ar); + break; + case(0x0102): + dissect_IOCRBlockReq_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + *ar); + break; + case(0x0103): + dissect_AlarmCRBlockReq_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + *ar); + break; + case(0x0104): + dissect_ExpectedSubmoduleBlockReq_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0106): + dissect_MCRBlockReq_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0107): + dissect_SubFrameBlock_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0108): + case(0x8108): + dissect_ARVendorBlockReq_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0109): + dissect_IRInfoBlock_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x010A): + dissect_SRInfoBlock_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x010C): + dissect_RSInfoBlock_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0110): + case(0x0111): + case(0x0112): + case(0x0113): + case(0x0114): + case(0x0116): + case(0x0117): + dissect_ControlPlugOrConnect_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, ar, u16BlockType); + break; + + case(0x0118): + dissect_ControlBlockPrmBegin(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength, ar); + break; + + case(0x0119): + dissect_SubmoduleListBlock(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength, ar); + break; + + case(0x0200): /* PDPortDataCheck */ + dissect_PDPortData_Check_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16BodyLength); + break; + case(0x0201): + dissect_PDevData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0202): /*dissect_PDPortData_Adjust_block */ + dissect_PDPortData_Adjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16BodyLength); + break; + case(0x0203): + dissect_PDSyncData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0204): + dissect_IsochronousModeData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0205): + dissect_PDIRData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0206): + dissect_PDIRGlobalData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0207): + dissect_PDIRFrameData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16BodyLength); + break; + case(0x0208): + dissect_PDIRBeginEndData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16BodyLength); + break; + case(0x0209): + dissect_AdjustDomainBoundary_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x020A): + dissect_CheckPeers_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x020B): + dissect_CheckLineDelay_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x020C): + dissect_CheckMAUType_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x020E): + dissect_AdjustMAUType_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x020F): + dissect_PDPortDataReal_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0210): + dissect_AdjustMulticastBoundary_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0211): + dissect_PDInterfaceMrpDataAdjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0212): + dissect_PDInterfaceMrpDataReal_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0213): + dissect_PDInterfaceMrpDataCheck_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0214): + case(0x0215): + dissect_PDPortMrpData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0216): + dissect_MrpManagerParams_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0217): + dissect_MrpClientParams_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0218): + dissect_MrpRTModeManagerData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0219): + dissect_MrpRingStateData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x021A): + dissect_MrpRTStateData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x021B): + dissect_AdjustPortState_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x021C): + dissect_CheckPortState_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x021D): + dissect_MrpRTModeClientData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x021E): + dissect_CheckSyncDifference_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x021F): + dissect_CheckMAUTypeDifference_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0220): + dissect_PDPortFODataReal_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0221): + dissect_FiberOpticManufacturerSpecific_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0222): + dissect_PDPortFODataAdjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0223): + dissect_PDPortFODataCheck_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0224): + dissect_AdjustPeerToPeerBoundary_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0225): + dissect_AdjustDCPBoundary_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0226): + dissect_AdjustPreambleLength_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0227): + dissect_CheckMAUTypeExtension_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0228): + dissect_FiberOpticDiagnosisInfo_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0229): + dissect_AdjustMAUTypeExtension_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x022A): + dissect_PDIRSubframeData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x022B): + dissect_PDSubFrameBlock_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x022C): + dissect_PDPortDataRealExtended_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + + case(0x0230): + dissect_PDPortFODataCheck_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0231): + dissect_MrpInstanceDataAdjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0232): + dissect_MrpInstanceDataReal_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0233): + dissect_MrpInstanceDataCheck_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0240): + dissect_PDInterfaceDataReal_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0241) : + dissect_PDRsiInstances_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0250): + dissect_PDInterfaceAdjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0251): + dissect_PDPortStatistic_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0260): + dissect_OwnPort_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0261): + dissect_Neighbors_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0270): + dissect_TSNNetworkControlDataReal_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0271): + dissect_TSNNetworkControlDataAdjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0272): + dissect_TSNDomainPortConfig_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0273): + dissect_TSNDomainQueueConfig_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0274): + dissect_TSNTimeData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0275): + dissect_TSNStreamPathDataReal_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, FALSE); + break; + case(0x0276): + dissect_TSNSyncTreeData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0277): + dissect_TSNUploadNetworkAttributes_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0278): + dissect_TSNForwardingDelay_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0279): + dissect_TSNExpectedNetworkAttributes_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x027A): + dissect_TSNStreamPathDataReal_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, TRUE); + break; + case(0x027B): + dissect_TSNDomainPortIngressRateLimiter_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x027C): + dissect_TSNDomainQueueRateLimiter_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x027D): + dissect_TSNPortID_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x027E): + dissect_TSNExpectedNeighbor_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0300): + dissect_CIMSNMPAdjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0400): + dissect_MultipleBlockHeader_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0401): + dissect_COContainerContent_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, *u16Index, u32RecDataLen, ar); + break; + case(0x0500): + dissect_RecordDataReadQuery_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, *u16Index, u16BodyLength); + break; + case(0x0600): + dissect_FSHello_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0601): + dissect_FSParameter_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0608): + dissect_PDInterfaceFSUDataAdjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x010B): + case(0x0609): + dissect_ARFSUDataAdjust_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x0810): + dissect_PE_EntityFilterData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0811): + dissect_PE_EntityStatusData_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0900): + dissect_RS_AdjustObserver_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0901): + dissect_RS_GetEvent_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0902): + dissect_RS_AckEvent_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0f00) : + dissect_Maintenance_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x0f05): + dissect_PE_Alarm_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x8001): + case(0x8002): + dissect_Alarm_ack_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x8008): + dissect_IODWriteResHeader_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16Index, u32RecDataLen, ar); + break; + case(0x8009): + dissect_IODReadResHeader_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, + u16Index, u32RecDataLen, ar); + break; + case(0x8101): + dissect_ARBlockRes_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, ar); + break; + case(0x8102): + dissect_IOCRBlockRes_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, *ar); + break; + case(0x8103): + dissect_AlarmCRBlockRes_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, *ar); + break; + case(0x8104): + dissect_ModuleDiffBlock_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow); + break; + case(0x8106): + dissect_ARServerBlock(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, u16BodyLength); + break; + case(0x8110): + case(0x8111): + case(0x8112): + case(0x8113): + case(0x8114): + case(0x8116): + case(0x8117): + case(0x8118): + dissect_ControlPlugOrConnect_block(tvb, offset, pinfo, sub_tree, sub_item, drep, u8BlockVersionHigh, u8BlockVersionLow, ar, u16BlockType); + break; + default: + dissect_pn_undecoded(tvb, offset, pinfo, sub_tree, u16BodyLength); + } + offset += u16BodyLength; + + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +/* dissect any PN-IO block */ +static int +dissect_a_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + + if (ar != NULL) { + pnio_ar_info(tvb, pinfo, tree, ar); + } + + return offset; +} + +/* dissect any number of PN-IO blocks */ +int +dissect_blocks(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + + + while (tvb_captured_length(tvb) > (guint) offset) { + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + u16Index++; + } + + if (ar != NULL) { + pnio_ar_info(tvb, pinfo, tree, ar); + } + + return offset; +} + + +/* dissect a PN-IO (DCE-RPC) request header */ +static int +dissect_IPNIO_rqst_header(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32ArgsMax; + guint32 u32ArgsLen; + guint32 u32MaxCount; + guint32 u32Offset; + guint32 u32ArraySize; + + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-CM"); + + /* args_max */ + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, + hf_pn_io_args_max, &u32ArgsMax); + /* args_len */ + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, + hf_pn_io_args_len, &u32ArgsLen); + + sub_item = proto_tree_add_item(tree, hf_pn_io_array, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io); + u32SubStart = offset; + + /* RPC array header */ + offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, di, drep, + hf_pn_io_array_max_count, &u32MaxCount); + offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, di, drep, + hf_pn_io_array_offset, &u32Offset); + offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, di, drep, + hf_pn_io_array_act_count, &u32ArraySize); + + proto_item_append_text(sub_item, ": Max: %u, Offset: %u, Size: %u", + u32MaxCount, u32Offset, u32ArraySize); + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +/* dissect a PN-IO (DCE-RPC) response header */ +static int +dissect_IPNIO_resp_header(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32ArgsLen; + guint32 u32MaxCount; + guint32 u32Offset; + guint32 u32ArraySize; + + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-CM"); + + offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep); + + /* args_len */ + offset = dissect_ndr_uint32(tvb, offset, pinfo, tree, di, drep, + hf_pn_io_args_len, &u32ArgsLen); + + sub_item = proto_tree_add_item(tree, hf_pn_io_array, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io); + u32SubStart = offset; + + /* RPC array header */ + offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, di, drep, + hf_pn_io_array_max_count, &u32MaxCount); + offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, di, drep, + hf_pn_io_array_offset, &u32Offset); + offset = dissect_ndr_uint32(tvb, offset, pinfo, sub_tree, di, drep, + hf_pn_io_array_act_count, &u32ArraySize); + + proto_item_append_text(sub_item, ": Max: %u, Offset: %u, Size: %u", + u32MaxCount, u32Offset, u32ArraySize); + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +/* dissect a PN-IO request */ +static int +dissect_IPNIO_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + + offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_blocks(tvb, offset, pinfo, tree, drep); + + return offset; +} + + +/* dissect a PN-IO response */ +static int +dissect_IPNIO_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + + offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_blocks(tvb, offset, pinfo, tree, drep); + + return offset; +} + +/* dissect a PROFIDrive parameter request */ +static int +dissect_ProfiDriveParameterRequest(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint8 request_reference; + guint8 request_id; + guint8 do_id; + guint8 no_of_parameters; + guint8 addr_idx; + proto_item *profidrive_item; + proto_tree *profidrive_tree; + + profidrive_item = proto_tree_add_item(tree, hf_pn_io_block, tvb, offset, 0, ENC_NA); + profidrive_tree = proto_item_add_subtree(profidrive_item, ett_pn_io_profidrive_parameter_request); + proto_item_set_text(profidrive_item, "PROFIDrive Parameter Request: "); + + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, profidrive_tree, drep, + hf_pn_io_profidrive_request_reference, &request_reference); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, profidrive_tree, drep, + hf_pn_io_profidrive_request_id, &request_id); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, profidrive_tree, drep, + hf_pn_io_profidrive_do_id, &do_id); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, profidrive_tree, drep, + hf_pn_io_profidrive_no_of_parameters, &no_of_parameters); + + proto_item_append_text(profidrive_item, "ReqRef:0x%02x, ReqId:%s, DO:%u, NoOfParameters:%u", + request_reference, val_to_str_const(request_id, pn_io_profidrive_request_id_vals, "Unknown"), + do_id, no_of_parameters); + + col_add_fstr(pinfo->cinfo, COL_INFO, "PROFIDrive Write Request, ReqRef:0x%02x, %s DO:%u", + request_reference, + request_id==0x01 ? "Read" : + request_id==0x02 ? "Change" : + "", + do_id); + + /* Parameter address list */ + for(addr_idx=0; addr_idx1) { + col_append_fstr(pinfo->cinfo, COL_INFO, ", P%d[%d..%d]", parameter, idx, idx+no_of_elems-1); + } + else { + col_append_fstr(pinfo->cinfo, COL_INFO, ", P%d[%d]", parameter, idx); + } + } + + /* in case of change request parameter value list */ + if (request_id == 0x02) { + for(addr_idx=0; addr_idxcinfo, COL_INFO, "PROFIDrive Read Response, ReqRef:0x%02x, RspId:%s", + request_reference, + val_to_str_const(response_id, pn_io_profidrive_response_id_vals, "Unknown response")); + /* in case of parameter response value list */ + if (response_id == 0x01) { + for(addr_idx=0; addr_idx offset) + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + if (end_offset > offset) + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + } + break; + + case(0xB050): + case(0xB051): + case(0xB060): + case(0xB061): + + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + break; + + + /*** multiple blocks possible ***/ + case(0x8000): /* ExpectedIdentificationData for one subslot */ + case(0x8001): /* RealIdentificationData for one subslot */ + case(0x800a): /* Diagnosis in channel decoding for one subslot */ + case(0x800b): /* Diagnosis in all codings for one subslot */ + case(0x800c): /* Diagnosis, Maintenance, Qualified and Status for one subslot */ + + case(0x802a): /* PDPortDataReal */ + case(0x802b): /* PDPortDataCheck */ + case(0x802d): /* Expected PDSyncData for one subslot with SyncID value 0 for PTCPoverRTA */ + case(0x802e): /* Expected PDSyncData for one subslot with SyncID value 0 for PTCPoverRTC */ + case(0x802f): /* PDPortDataAdjust */ + case(0x8030): /* IsochronousModeData for one subslot */ + case(0x8031): /* PDTimeData for one subslot */ + case(0x8032): + case(0x8033): + case(0x8034): + case(0x8035): + case(0x8036): + case(0x8037): + case(0x8038): + case(0x8039): + case(0x803a): + case(0x803b): + case(0x803c): + case(0x803d): + case(0x803e): + case(0x803f): + case(0x8040): /* Expected PDSyncData for one subslot with SyncID value 2 ... 30 */ + case(0x8041): + case(0x8042): + case(0x8043): + case(0x8044): + case(0x8045): + case(0x8046): + case(0x8047): + case(0x8048): + case(0x8049): + case(0x804a): + case(0x804b): + case(0x804c): + case(0x804d): + case(0x804e): + case(0x804f): /* Expected PDSyncData for one subslot with SyncID value 31 */ + case(0x8055): /* PDPortMrpIcDataAdjust for one subslot */ + case(0x8056): /* PDPortMrpIcDataCheck for one subslot */ + case(0x8057): /* PDPortMrpIcDataReal for one subslot */ + case(0x8072): /* PDPortStatistic for one subslot */ + case(0xc000): /* ExpectedIdentificationData for one slot */ + case(0xc001): /* RealIdentificationData for one slot */ + case(0xc00a): /* Diagnosis in channel coding for one slot */ + case(0xc00b): /* Diagnosis in all codings for one slot */ + case(0xc00c): /* Diagnosis, Maintenance, Qualified and Status for one slot */ + + case(0xe000): /* ExpectedIdentificationData for one AR */ + case(0xe001): /* RealIdentificationData for one AR */ + case(0xe00a): /* Diagnosis in channel decoding for one AR */ + case(0xe00b): /* Diagnosis in all codings for one AR */ + case(0xe00c): /* Diagnosis, Maintenance, Qualified and Status for one AR */ + case(0xE060): /* RS_GetEvent (using RecordDataRead service) */ + case(0xf000): /* RealIdentificationData for one API */ + case(0xf00a): /* Diagnosis in channel decoding for one API */ + case(0xf00b): /* Diagnosis in all codings for one API */ + case(0xf00c): /* Diagnosis, Maintenance, Qualified and Status for one API */ + case(0xf80c): /* Diagnosis, Maintenance, Qualified and Status for one device */ + case(0xf841): /* PDRealData */ + case(0xf842): /* PDExpectedData */ + offset = dissect_blocks(tvb, offset, pinfo, tree, drep); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, u32RecDataLen); + } + + return offset; +} + + +/* dissect a PN-IO read response */ +static int +dissect_IPNIO_Read_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16Index = 0; + guint32 u32RecDataLen = 0; + pnio_ar_t *ar = NULL; + + offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, di, drep); + + /* When PNIOStatus is Error */ + if (!tvb_captured_length_remaining(tvb, offset)) + return offset; + + /* IODReadHeader */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + + /* RecordDataRead */ + if (u32RecDataLen != 0) { + offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen); + } + + if (ar != NULL) { + pnio_ar_info(tvb, pinfo, tree, ar); + } + + return offset; +} + +/* F-Parameter record data object */ +static int +dissect_ProfiSafeParameterRequest(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16Index, wmem_list_frame_t *frame) +{ + proto_item *f_item; + proto_tree *f_tree; + proto_item *flags1_item; + proto_tree *flags1_tree; + proto_item *flags2_item; + proto_tree *flags2_tree; + guint16 src_addr; + guint16 dst_addr; + guint16 wd_time; + guint16 par_crc; + guint32 ipar_crc = 0; + guint8 prm_flag1; + guint8 prm_flag1_chck_seq; + guint8 prm_flag1_chck_ipar; + guint8 prm_flag1_sil; + guint8 prm_flag1_crc_len; + guint8 prm_flag1_crc_seed; + guint8 prm_flag1_reserved; + guint8 prm_flag2; + guint8 prm_flag2_reserved; + guint8 prm_flag2_f_block_id; + guint8 prm_flag2_f_par_version; + + conversation_t *conversation; + stationInfo *station_info; + ioDataObject *io_data_object; + wmem_list_frame_t *frame_out; + + ARUUIDFrame *current_aruuid_frame = NULL; + guint32 current_aruuid = 0; + + f_item = proto_tree_add_item(tree, hf_pn_io_block, tvb, offset, 0, ENC_NA); + f_tree = proto_item_add_subtree(f_item, ett_pn_io_profisafe_f_parameter); + proto_item_set_text(f_item, "F-Parameter: "); + + flags1_item = proto_tree_add_item(f_tree, hf_pn_io_ps_f_prm_flag1, tvb, offset, 1, ENC_BIG_ENDIAN); + flags1_tree = proto_item_add_subtree(flags1_item, ett_pn_io_profisafe_f_parameter_prm_flag1); + + /* dissection of F_Prm_Flag1 */ + dissect_dcerpc_uint8(tvb, offset, pinfo, flags1_tree, drep, + hf_pn_io_ps_f_prm_flag1_chck_seq, &prm_flag1_chck_seq); + dissect_dcerpc_uint8(tvb, offset, pinfo, flags1_tree, drep, + hf_pn_io_ps_f_prm_flag1_chck_ipar, &prm_flag1_chck_ipar); + dissect_dcerpc_uint8(tvb, offset, pinfo, flags1_tree, drep, + hf_pn_io_ps_f_prm_flag1_sil, &prm_flag1_sil); + dissect_dcerpc_uint8(tvb, offset, pinfo, flags1_tree, drep, + hf_pn_io_ps_f_prm_flag1_crc_len, &prm_flag1_crc_len); + dissect_dcerpc_uint8(tvb, offset, pinfo, flags1_tree, drep, + hf_pn_io_ps_f_prm_flag1_crc_seed, &prm_flag1_crc_seed); + dissect_dcerpc_uint8(tvb, offset, pinfo, flags1_tree, drep, + hf_pn_io_ps_f_prm_flag1_reserved, &prm_flag1_reserved); + prm_flag1 = prm_flag1_chck_seq|prm_flag1_chck_ipar|prm_flag1_sil|prm_flag1_crc_len|prm_flag1_crc_seed|prm_flag1_reserved; + offset++; + + flags2_item = proto_tree_add_item(f_tree, hf_pn_io_ps_f_prm_flag2, tvb, offset, 1, ENC_BIG_ENDIAN); + flags2_tree = proto_item_add_subtree(flags2_item, ett_pn_io_profisafe_f_parameter_prm_flag2); + + /* dissection of F_Prm_Flag2 */ + dissect_dcerpc_uint8(tvb, offset, pinfo, flags2_tree, drep, + hf_pn_io_ps_f_prm_flag2_reserved, &prm_flag2_reserved); + dissect_dcerpc_uint8(tvb, offset, pinfo, flags2_tree, drep, + hf_pn_io_ps_f_prm_flag2_f_block_id, &prm_flag2_f_block_id); + dissect_dcerpc_uint8(tvb, offset, pinfo, flags2_tree, drep, + hf_pn_io_ps_f_prm_flag2_f_par_version, &prm_flag2_f_par_version); + prm_flag2 = prm_flag2_reserved|prm_flag2_f_block_id|prm_flag2_f_par_version; + offset++; + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, f_item, drep, + hf_pn_io_ps_f_src_adr, &src_addr); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, f_item, drep, + hf_pn_io_ps_f_dest_adr, &dst_addr); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, f_item, drep, + hf_pn_io_ps_f_wd_time, &wd_time); + + /* Dissection for F_iPar_CRC: see F_Prm_Flag2 -> F_Block_ID */ + if( (prm_flag2_f_block_id & 0x08) && !(prm_flag2_f_block_id & 0x20) ) { + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, f_item, drep, + hf_pn_io_ps_f_ipar_crc, &ipar_crc); + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, f_item, drep, + hf_pn_io_ps_f_par_crc, &par_crc); + + + /* Differniate between ipar_crc and no_ipar_crc */ + if( (prm_flag2_f_block_id & 0x08) && !(prm_flag2_f_block_id & 0x20) ) { /* include ipar_crc display */ + col_append_fstr(pinfo->cinfo, COL_INFO, + ", F-Parameter record, prm_flag1:0x%02x, prm_flag2:0x%02x, src:0x%04x," + " dst:0x%04x, wd_time:%d, ipar_crc:0x%04x, crc:0x%04x", + prm_flag1, prm_flag2, src_addr, dst_addr, wd_time, ipar_crc, par_crc); + + proto_item_append_text(f_item, "prm_flag1:0x%02x, prm_flag2:0x%02x, src:0x%04x, dst:0x%04x, wd_time:%d, ipar_crc:0x%04x, par_crc:0x%04x", + prm_flag1, prm_flag2, src_addr, dst_addr, wd_time, ipar_crc, par_crc); + } + else { /* exclude ipar_crc display */ + col_append_fstr(pinfo->cinfo, COL_INFO, + ", F-Parameter record, prm_flag1:0x%02x, prm_flag2:0x%02x, src:0x%04x," + " dst:0x%04x, wd_time:%d, crc:0x%04x", + prm_flag1, prm_flag2, src_addr, dst_addr, wd_time, par_crc); + + proto_item_append_text(f_item, "prm_flag1:0x%02x, prm_flag2:0x%02x, src:0x%04x, dst:0x%04x, wd_time:%d, par_crc:0x%04x", + prm_flag1, prm_flag2, src_addr, dst_addr, wd_time, par_crc); + } + + if (!PINFO_FD_VISITED(pinfo)) { + /* Get current conversation endpoints using MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, if no "Ident OK" frame as been dissected yet! + * Need to switch dl_src & dl_dst, as current packet is sent by controller and not by device. + * All conversations are based on Device MAC as addr1 */ + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_NONE, 0, 0, 0); + } + + current_aruuid_frame = pn_find_aruuid_frame_setup(pinfo); + + if (current_aruuid_frame != NULL) { + current_aruuid = current_aruuid_frame->aruuid.data1; + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, current_aruuid); + + if (station_info != NULL) { + pn_find_dcp_station_info(station_info, conversation); + + if (frame != NULL) { + io_data_object = (ioDataObject*)wmem_list_frame_data(frame); + + io_data_object->f_par_crc1 = par_crc; + io_data_object->f_src_adr = src_addr; + io_data_object->f_dest_adr = dst_addr; + io_data_object->f_crc_seed = prm_flag1 & 0x40; + if (!(prm_flag1 & 0x10)) { + if (prm_flag1 & 0x20) { + io_data_object->f_crc_len = 4; + } else { + io_data_object->f_crc_len = 3; + } + } + } + + /* Find same module within output data to saved data */ + for (frame_out = wmem_list_head(station_info->ioobject_data_out); frame_out != NULL; frame_out = wmem_list_frame_next(frame_out)) { + io_data_object = (ioDataObject*)wmem_list_frame_data(frame_out); + if (u16Index == io_data_object->fParameterIndexNr && /* Check F-Parameter Indexnumber */ + io_data_object->profisafeSupported && /* Arrayelement has to be PS-Module */ + io_data_object->f_par_crc1 == 0) { /* Find following object with no f_par_crc1 */ + + io_data_object->f_par_crc1 = par_crc; + io_data_object->f_src_adr = src_addr; + io_data_object->f_dest_adr = dst_addr; + io_data_object->f_crc_seed = prm_flag1 & 0x40; + if (!(prm_flag1 & 0x10)) { + if (prm_flag1 & 0x20) { + io_data_object->f_crc_len = 4; + } else { + io_data_object->f_crc_len = 3; + } + } + + break; + } + } + } + } + + return offset; +} + +static int +dissect_RecordDataWrite(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16Index, guint32 u32RecDataLen) +{ + conversation_t *conversation; + stationInfo *station_info; + wmem_list_frame_t *frame; + ioDataObject *io_data_object; + + const gchar *userProfile; + pnio_ar_t *ar = NULL; + + ARUUIDFrame *current_aruuid_frame = NULL; + guint32 current_aruuid = 0; + + /* PROFISafe */ + /* Get current conversation endpoints using MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, if no "Ident OK" frame as been dissected yet! + * Need to switch dl_src & dl_dst, as current packet is sent by controller and not by device. + * All conversations are based on Device MAC as addr1 */ + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_NONE, 0, 0, 0); + } + + current_aruuid_frame = pn_find_aruuid_frame_setup(pinfo); + + if (current_aruuid_frame != NULL) { + current_aruuid = current_aruuid_frame->aruuid.data1; + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, current_aruuid); + + if (station_info != NULL) { + pn_find_dcp_station_info(station_info, conversation); + + if (!PINFO_FD_VISITED(pinfo)) { + /* Search within the entire existing list for current input object data */ + for (frame = wmem_list_head(station_info->ioobject_data_in); frame != NULL; frame = wmem_list_frame_next(frame)) { + io_data_object = (ioDataObject*)wmem_list_frame_data(frame); + if (u16Index == io_data_object->fParameterIndexNr && /* Check F-Parameter Indexnumber */ + io_data_object->profisafeSupported && /* Arrayelement has to be PS-Module */ + io_data_object->f_par_crc1 == 0) { /* Find following object with no f_par_crc1 */ + + return dissect_ProfiSafeParameterRequest(tvb, offset, pinfo, tree, drep, u16Index, frame); + } + } + } + else { + /* User clicked another time the frame to see the data -> PROFIsafe data has already been saved + * Check whether the device contains an PROFIsafe supported submodule. + */ + + for (frame = wmem_list_head(station_info->ioobject_data_in); frame != NULL; frame = wmem_list_frame_next(frame)) { + io_data_object = (ioDataObject*)wmem_list_frame_data(frame); + if (u16Index == io_data_object->fParameterIndexNr && /* Check F-Parameter Indexnumber */ + io_data_object->profisafeSupported) { /* Arrayelement has to be PS-Module */ + + return dissect_ProfiSafeParameterRequest(tvb, offset, pinfo, tree, drep, u16Index, frame); + } + } + + for (frame = wmem_list_head(station_info->ioobject_data_out); frame != NULL; frame = wmem_list_frame_next(frame)) { + io_data_object = (ioDataObject*)wmem_list_frame_data(frame); + if (u16Index == io_data_object->fParameterIndexNr && /* Check F-Parameter Indexnumber */ + io_data_object->profisafeSupported) { /* Arrayelement has to be PS-Module */ + + return dissect_ProfiSafeParameterRequest(tvb, offset, pinfo, tree, drep, u16Index, frame); + } + } + } + } + /* profidrive parameter request */ + if (u16Index == 0xb02e || u16Index == 0xb02f || u16Index == 0x002f) { + return dissect_ProfiDriveParameterRequest(tvb, offset, pinfo, tree, drep); + } + + /* user specified format? */ + if (u16Index < 0x8000) { + return dissect_pn_user_data(tvb, offset, pinfo, tree, u32RecDataLen, "User Specified Data"); + } + + + + /* "reserved for profiles"? */ + userProfile = indexReservedForProfiles(u16Index); + if (userProfile != NULL) { + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, u32RecDataLen, userProfile); + return offset; + } + + /* see: pn_io_index */ + switch (u16Index) { + case(0x8020): /* PDIRSubframeData */ + case(0x801e): /* SubstituteValues for one subslot */ + case(0x802b): /* PDPortDataCheck for one subslot */ + case(0x802c): /* PDirData for one subslot */ + case(0x802d): /* Expected PDSyncData for one subslot with SyncID value 0 for PTCPoverRTA */ + case(0x802e): /* Expected PDSyncData for one subslot with SyncID value 0 for PTCPoverRTC */ + case(0x802f): /* PDPortDataAdjust for one subslot */ + case(0x8030): /* IsochronousModeData for one subslot */ + case(0x8031): /* PDTimeData for one subslot */ + case(0x8051): /* PDInterfaceMrpDataCheck for one subslot */ + case(0x8052): /* PDInterfaceMrpDataAdjust for one subslot */ + case(0x8053): /* PDPortMrpDataAdjust for one subslot */ + case(0x8055): /* PDPortMrpIcDataAdjust for one subslot */ + case(0x8056): /* PDPortMrpIcDataCheck for one subslot */ + case(0x8061): /* PDPortFODataCheck for one subslot */ + case(0x8062): /* PDPortFODataAdjust for one subslot */ + case(0x8063): /* PDPortSFPDataCheck for one subslot */ + case(0x8070): /* PDNCDataCheck for one subslot */ + case(0x8071): /* PDInterfaceAdjust */ + case(0x8090): /* PDInterfaceFSUDataAdjust */ + case(0x80B0): /* CombinedObjectContainer*/ + case(0x80CF): /* RS_AdjustObserver */ + case(0x8200): /* CIMSNMPAdjust */ + case(0xaff1): /* I&M1 */ + case(0xaff2): /* I&M2 */ + case(0xaff3): /* I&M3 */ + case(0xe050): /* FastStartUp data for one AR */ + case(0xe061): /* RS_AckEvent (using RecordDataWrite service) */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, u32RecDataLen); + } + + return offset; +} + +#define PN_IO_MAX_RECURSION_DEPTH 100 + +static int +dissect_IODWriteReq(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, pnio_ar_t **ar, guint recursion_count) +{ + guint16 u16Index = 0; + guint32 u32RecDataLen = 0; + + if (++recursion_count >= PN_IO_MAX_RECURSION_DEPTH) { + proto_tree_add_expert(tree, pinfo, &ei_pn_io_max_recursion_depth_reached, + tvb, 0, 0); + return tvb_captured_length(tvb); + } + + /* IODWriteHeader */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, ar); + + /* IODWriteMultipleReq? */ + if (u16Index == 0xe040) { + while (tvb_captured_length_remaining(tvb, offset) > 0) { + offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep, ar, recursion_count++); + } + } else { + tvbuff_t *new_tvb = tvb_new_subset_length(tvb, offset, u32RecDataLen); + /* RecordDataWrite */ + offset += dissect_RecordDataWrite(new_tvb, 0, pinfo, tree, drep, u16Index, u32RecDataLen); + + /* Padding */ + switch (offset % 4) { + case(3): + offset += 1; + break; + case(2): + offset += 2; + break; + case(1): + offset += 3; + break; + default: /* will not execute because of the line preceding the switch */ + break; + } + } + + return offset; +} + +/* dissect a PN-IO write request */ +static int +dissect_IPNIO_Write_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + pnio_ar_t *ar = NULL; + guint recursion_count = 0; + + offset = dissect_IPNIO_rqst_header(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep, &ar, recursion_count); + + if (ar != NULL) { + pnio_ar_info(tvb, pinfo, tree, ar); + } + + return offset; +} + + + +static int +dissect_IODWriteRes(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + + + /* IODWriteResHeader */ + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + + /* IODWriteMultipleRes? */ + if (u16Index == 0xe040) { + while (tvb_captured_length_remaining(tvb, offset) > 0) { + offset = dissect_block(tvb, offset, pinfo, tree, drep, &u16Index, &u32RecDataLen, &ar); + } + } + + if (ar != NULL) { + pnio_ar_info(tvb, pinfo, tree, ar); + } + + return offset; +} + + +/* dissect a PN-IO write response */ +static int +dissect_IPNIO_Write_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + + offset = dissect_IPNIO_resp_header(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep); + + return offset; +} + + +/* dissect any number of PN-RSI blocks */ +int +dissect_rsi_blocks(tvbuff_t* tvb, int offset, + packet_info* pinfo, proto_tree* tree, guint8* drep, guint32 u32FOpnumOffsetOpnum, int type) +{ + pnio_ar_t* ar = NULL; + guint recursion_count = 0; + guint16 u16Index = 0; + guint32 u32RecDataLen = 0; + + + switch (u32FOpnumOffsetOpnum) { + case(0x0): // Connect request or response + offset = dissect_blocks(tvb, offset, pinfo, tree, drep); + break; + case(0x2): // Read request or response + offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen); + break; + case(0x3): // Write request or response + if (type == PDU_TYPE_REQ) + offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep, &ar, recursion_count); + else if (type == PDU_TYPE_RSP) + offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep); + break; + case(0x4): // Control request or response + offset = dissect_blocks(tvb, offset, pinfo, tree, drep); + break; + case(0x5): // ReadImplicit request or response + offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen); + break; + case(0x6): // ReadConnectionless request or response + offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen); + break; + case(0x7): // ReadNotification request or response + offset = dissect_RecordDataRead(tvb, offset, pinfo, tree, drep, u16Index, u32RecDataLen); + break; + case(0x8): // PrmWriteMore request or response + if (type == PDU_TYPE_REQ) + offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep, &ar, recursion_count); + else if (type == PDU_TYPE_RSP) + offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep); + break; + case(0x9): // PrmWriteEnd request or response + if (type == PDU_TYPE_REQ) + offset = dissect_IODWriteReq(tvb, offset, pinfo, tree, drep, &ar, recursion_count); + else if (type == PDU_TYPE_RSP) + offset = dissect_IODWriteRes(tvb, offset, pinfo, tree, drep); + break; + default: + col_append_str(pinfo->cinfo, COL_INFO, "Reserved"); + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb)); + break; + } + + if (ar != NULL) { + pnio_ar_info(tvb, pinfo, tree, ar); + } + + return offset; +} + + +/* dissect the IOxS (IOCS, IOPS) field */ +static int +dissect_PNIO_IOxS(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int hfindex) +{ + + if (tree) { + guint8 u8IOxS; + proto_item *ioxs_item; + proto_tree *ioxs_tree; + + u8IOxS = tvb_get_guint8(tvb, offset); + + /* add ioxs subtree */ + ioxs_item = proto_tree_add_uint(tree, hfindex, tvb, offset, 1, u8IOxS); + proto_item_append_text(ioxs_item, + " (%s%s)", + (u8IOxS & 0x01) ? "another IOxS follows " : "", + (u8IOxS & 0x80) ? "good" : "bad"); + ioxs_tree = proto_item_add_subtree(ioxs_item, ett_pn_io_ioxs); + + proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_datastate, tvb, offset, 1, u8IOxS); + proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_instance, tvb, offset, 1, u8IOxS); + proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_res14, tvb, offset, 1, u8IOxS); + proto_tree_add_uint(ioxs_tree, hf_pn_io_ioxs_extension, tvb, offset, 1, u8IOxS); + } + + return offset + 1; +} + + +/* dissect a PN-IO Cyclic Service Data Unit (on top of PN-RT protocol) */ +static int +dissect_PNIO_C_SDU(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep _U_) +{ + proto_tree *data_tree = NULL; + /* gint iTotalLen = 0; */ + /* gint iSubFrameLen = 0; */ + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO"); + + if (tree) { + proto_item *data_item; + data_item = proto_tree_add_protocol_format(tree, proto_pn_io, tvb, offset, tvb_captured_length(tvb), + "PROFINET IO Cyclic Service Data Unit: %u bytes", tvb_captured_length(tvb)); + data_tree = proto_item_add_subtree(data_item, ett_pn_io_rtc); + } + + /*dissect_dcerpc_uint16(tvb, offset, pinfo, data_tree, drep, hf_pn_io_packedframe_SFCRC, &u16SFCRC);*/ + if (dissect_CSF_SDU_heur(tvb, pinfo, data_tree, NULL)) + return(tvb_captured_length(tvb)); + + /* XXX - dissect the remaining data */ + /* this will be one or more DataItems followed by an optional GAP and RTCPadding */ + /* as we don't have the required context information to dissect the specific DataItems, */ + /* this will be tricky :-( */ + /* actual: there may be an IOxS but most case there isn't so better display a data-stream */ + /* offset = dissect_PNIO_IOxS(tvb, offset, pinfo, data_tree, drep, hf_pn_io_ioxs); */ + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset), + "User Data (including GAP and RTCPadding)"); + + return offset; +} + + +/* dissect a PN-IO RTA PDU (on top of PN-RT protocol) */ +static int +dissect_PNIO_RTA(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16AlarmDstEndpoint; + guint16 u16AlarmSrcEndpoint; + guint8 u8PDUType; + guint8 u8PDUVersion; + guint8 u8WindowSize; + guint8 u8Tack; + guint16 u16SendSeqNum; + guint16 u16AckSeqNum; + guint16 u16VarPartLen; + int start_offset = offset; + guint16 u16Index = 0; + guint32 u32RecDataLen; + pnio_ar_t *ar = NULL; + + + proto_item *rta_item; + proto_tree *rta_tree; + + proto_item *sub_item; + proto_tree *sub_tree; + + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-AL"); + + rta_item = proto_tree_add_protocol_format(tree, proto_pn_io, tvb, offset, tvb_captured_length(tvb), + "PROFINET IO Alarm"); + rta_tree = proto_item_add_subtree(rta_item, ett_pn_io_rta); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_io_alarm_dst_endpoint, &u16AlarmDstEndpoint); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_io_alarm_src_endpoint, &u16AlarmSrcEndpoint); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: 0x%x, Dst: 0x%x", + u16AlarmSrcEndpoint, u16AlarmDstEndpoint); + + /* PDU type */ + sub_item = proto_tree_add_item(rta_tree, hf_pn_io_pdu_type, tvb, offset, 1, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pdu_type); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdu_type_type, &u8PDUType); + u8PDUType &= 0x0F; + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_pdu_type_version, &u8PDUVersion); + u8PDUVersion >>= 4; + proto_item_append_text(sub_item, ", Type: %s, Version: %u", + val_to_str_const(u8PDUType, pn_io_pdu_type, "Unknown"), + u8PDUVersion); + + /* additional flags */ + sub_item = proto_tree_add_item(rta_tree, hf_pn_io_add_flags, tvb, offset, 1, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_add_flags); + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_window_size, &u8WindowSize); + u8WindowSize &= 0x0F; + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_io_tack, &u8Tack); + u8Tack >>= 4; + proto_item_append_text(sub_item, ", Window Size: %u, Tack: %u", + u8WindowSize, u8Tack); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_io_send_seq_num, &u16SendSeqNum); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_io_ack_seq_num, &u16AckSeqNum); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_io_var_part_len, &u16VarPartLen); + + switch ( u8PDUType & 0x0F) { + case(1): /* Data-RTA */ + col_append_str(pinfo->cinfo, COL_INFO, ", Data-RTA"); + offset = dissect_block(tvb, offset, pinfo, rta_tree, drep, &u16Index, &u32RecDataLen, &ar); + break; + case(2): /* NACK-RTA */ + col_append_str(pinfo->cinfo, COL_INFO, ", NACK-RTA"); + /* no additional data */ + break; + case(3): /* ACK-RTA */ + col_append_str(pinfo->cinfo, COL_INFO, ", ACK-RTA"); + /* no additional data */ + break; + case(4): /* ERR-RTA */ + col_append_str(pinfo->cinfo, COL_INFO, ", ERR-RTA"); + offset = dissect_PNIO_status(tvb, offset, pinfo, rta_tree, drep); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb)); + } + + proto_item_set_len(rta_item, offset - start_offset); + + return offset; +} + + +/* possibly dissect a PN-IO related PN-RT packet */ +static gboolean +dissect_PNIO_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + void *data) +{ + guint8 drep_data = 0; + guint8 *drep = &drep_data; + /* the sub tvb will NOT contain the frame_id here! */ + guint16 u16FrameID = GPOINTER_TO_UINT(data); + heur_dtbl_entry_t *hdtbl_entry; + conversation_t* conversation; + guint8 isTimeAware = FALSE; + + /* + * In case the packet is a protocol encoded in the basic PNIO transport stream, + * give that protocol a chance to make a heuristic dissection, before we continue + * to dissect it as a normal PNIO packet. + */ + if (dissector_try_heuristic(heur_pn_subdissector_list, tvb, pinfo, tree, &hdtbl_entry, NULL)) + return TRUE; + + /* TimeAwareness Information needed for dissecting RTC3 - RTSteam frames */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + + if (conversation != NULL) { + isTimeAware = GPOINTER_TO_UINT(conversation_get_proto_data(conversation, proto_pn_io_time_aware_status)); + } + + /* is this a (none DFP) PNIO class 3 data packet? */ + /* frame id must be in valid range (cyclic Real-Time, class=3) */ + if (((u16FrameID >= 0x0100 && u16FrameID <= 0x06FF) || /* RTC3 non redundant */ + (u16FrameID >= 0x0700 && u16FrameID <= 0x0fff)) && /* RTC3 redundant */ + !isTimeAware) { + dissect_CSF_SDU_heur(tvb, pinfo, tree, data); + return TRUE; + } + + /* is this a PNIO class stream data packet? */ + /* frame id must be in valid range (cyclic Real-Time, class=Stream) */ + if (((u16FrameID >= 0x1000 && u16FrameID <= 0x2FFF) || + (u16FrameID >= 0x3800 && u16FrameID <= 0x3FFF)) && + isTimeAware) { + dissect_CSF_SDU_heur(tvb, pinfo, tree, data); + return TRUE; + } + + /* The following range is reserved for following developments */ + /* frame id must be in valid range (Reserved) and + * first byte (CBA version field) has to be != 0x11 */ + if (u16FrameID >= 0x4000 && u16FrameID <= 0x7fff) { + dissect_PNIO_C_SDU(tvb, 0, pinfo, tree, drep); + return TRUE; + } + + /* is this a PNIO class 1 data packet? */ + /* frame id must be in valid range (cyclic Real-Time, class=1) and + * first byte (CBA version field) has to be != 0x11 */ + if (u16FrameID >= 0x8000 && u16FrameID < 0xbfff) { + dissect_PNIO_C_SDU_RTC1(tvb, 0, pinfo, tree, drep, u16FrameID); + return TRUE; + } + + /* is this a PNIO class 1 (legacy) data packet? */ + /* frame id must be in valid range (cyclic Real-Time, class=1, legacy) and + * first byte (CBA version field) has to be != 0x11 */ + if (u16FrameID >= 0xc000 && u16FrameID < 0xfbff) { + dissect_PNIO_C_SDU_RTC1(tvb, 0, pinfo, tree, drep, u16FrameID); + return TRUE; + } + + /* is this a PNIO high priority alarm packet? */ + if (u16FrameID == 0xfc01) { + col_set_str(pinfo->cinfo, COL_INFO, "Alarm High"); + + dissect_PNIO_RTA(tvb, 0, pinfo, tree, drep); + return TRUE; + } + + /* is this a PNIO low priority alarm packet? */ + if (u16FrameID == 0xfe01) { + col_set_str(pinfo->cinfo, COL_INFO, "Alarm Low"); + + dissect_PNIO_RTA(tvb, 0, pinfo, tree, drep); + return TRUE; + } + + /* is this a Remote Service Interface (RSI) packet*/ + if (u16FrameID == 0xfe02) { + dissect_PNIO_RSI(tvb, 0, pinfo, tree, drep); + return TRUE; + } + + /* this PN-RT packet doesn't seem to be PNIO specific */ + return FALSE; +} + + + +static gboolean +pn_io_ar_conv_valid(packet_info *pinfo, void *user_data _U_) +{ + void* profinet_type = p_get_proto_data(pinfo->pool, pinfo, proto_pn_io, 0); + + return ((profinet_type != NULL) && (GPOINTER_TO_UINT(profinet_type) == 10)); +} + +static gchar * +pn_io_ar_conv_filter(packet_info *pinfo, void *user_data _U_) +{ + pnio_ar_t *ar = (pnio_ar_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pn_io, 0); + void* profinet_type = p_get_proto_data(pinfo->pool, pinfo, proto_pn_io, 0); + char *buf; + address controllermac_addr, devicemac_addr; + + if ((profinet_type == NULL) || (GPOINTER_TO_UINT(profinet_type) != 10) || (ar == NULL)) { + return NULL; + } + + set_address(&controllermac_addr, AT_ETHER, 6, ar->controllermac); + set_address(&devicemac_addr, AT_ETHER, 6, ar->devicemac); + + buf = ws_strdup_printf( + "pn_io.ar_uuid == %s || " /* ARUUID */ + "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s) || " /* Alarm CR (contr -> dev) */ + "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s)", /* Alarm CR (dev -> contr) */ + guid_to_str(pinfo->pool, (const e_guid_t*) &ar->aruuid), + ar->controlleralarmref, address_to_str(pinfo->pool, &controllermac_addr), + ar->devicealarmref, address_to_str(pinfo->pool, &devicemac_addr)); + return buf; +} + +static gchar * +pn_io_ar_conv_data_filter(packet_info *pinfo, void *user_data _U_) +{ + pnio_ar_t *ar = (pnio_ar_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pn_io, 0); + void* profinet_type = p_get_proto_data(pinfo->pool, pinfo, proto_pn_io, 0); + char *buf, *controllermac_str, *devicemac_str, *guid_str; + address controllermac_addr, devicemac_addr; + + if ((profinet_type == NULL) || (GPOINTER_TO_UINT(profinet_type) != 10) || (ar == NULL)) { + return NULL; + } + + set_address(&controllermac_addr, AT_ETHER, 6, ar->controllermac); + set_address(&devicemac_addr, AT_ETHER, 6, ar->devicemac); + + controllermac_str = address_to_str(pinfo->pool, &controllermac_addr); + devicemac_str = address_to_str(pinfo->pool, &devicemac_addr); + guid_str = guid_to_str(pinfo->pool, (const e_guid_t*) &ar->aruuid); + if (ar->arType == 0x0010) /* IOCARSingle using RT_CLASS_3 */ + { + buf = ws_strdup_printf( + "pn_io.ar_uuid == %s || " /* ARUUID */ + "(pn_rt.frame_id == 0x%x) || (pn_rt.frame_id == 0x%x) || " + "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s) || " /* Alarm CR (contr -> dev) */ + "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s)", /* Alarm CR (dev -> contr) */ + guid_str, + ar->inputframeid, ar->outputframeid, + ar->controlleralarmref, controllermac_str, + ar->devicealarmref, devicemac_str); + } + else + { + buf = ws_strdup_printf( + "pn_io.ar_uuid == %s || " /* ARUUID */ + "(pn_rt.frame_id == 0x%x && eth.src == %s && eth.dst == %s) || " /* Input CR && dev MAC -> contr MAC */ + "(pn_rt.frame_id == 0x%x && eth.src == %s && eth.dst == %s) || " /* Output CR && contr MAC -> dev MAC */ + "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s) || " /* Alarm CR (contr -> dev) */ + "(pn_io.alarm_src_endpoint == 0x%x && eth.src == %s)", /* Alarm CR (dev -> contr) */ + guid_str, + ar->inputframeid, devicemac_str, controllermac_str, + ar->outputframeid, controllermac_str, devicemac_str, + ar->controlleralarmref, controllermac_str, + ar->devicealarmref, devicemac_str); + } + return buf; +} + + + +/* the PNIO dcerpc interface table */ +static dcerpc_sub_dissector pn_io_dissectors[] = { + { 0, "Connect", dissect_IPNIO_rqst, dissect_IPNIO_resp }, + { 1, "Release", dissect_IPNIO_rqst, dissect_IPNIO_resp }, + { 2, "Read", dissect_IPNIO_rqst, dissect_IPNIO_Read_resp }, + { 3, "Write", dissect_IPNIO_Write_rqst, dissect_IPNIO_Write_resp }, + { 4, "Control", dissect_IPNIO_rqst, dissect_IPNIO_resp }, + { 5, "Read Implicit", dissect_IPNIO_rqst, dissect_IPNIO_Read_resp }, + { 0, NULL, NULL, NULL } +}; + + +static void +pnio_cleanup(void) { + g_list_free(pnio_ars); + pnio_ars = NULL; +} + + +static void +pnio_setup(void) { + aruuid_frame_setup_list = wmem_list_new(wmem_file_scope()); + pnio_time_aware_frame_map = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); +} + + +void +proto_register_pn_io (void) +{ + static hf_register_info hf[] = { + { &hf_pn_io_opnum, + { "Operation", "pn_io.opnum", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_reserved16, + { "Reserved", "pn_io.reserved16", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_array, + { "Array", "pn_io.array", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_args_max, + { "ArgsMaximum", "pn_io.args_max", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_args_len, + { "ArgsLength", "pn_io.args_len", + FT_UINT32, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_array_max_count, + { "MaximumCount", "pn_io.array_max_count", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_array_offset, + { "Offset", "pn_io.array_offset", + FT_UINT32, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_array_act_count, + { "ActualCount", "pn_io.array_act_count", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_ar_data, + { "ARDATA for AR:", "pn_io.ar_data", + FT_NONE, BASE_NONE, 0x0, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ar_type, + { "ARType", "pn_io.ar_type", + FT_UINT16, BASE_HEX, VALS(pn_io_ar_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_cminitiator_macadd, + { "CMInitiatorMacAdd", "pn_io.cminitiator_mac_add", + FT_ETHER, BASE_NONE, 0x0, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_cminitiator_objectuuid, + { "CMInitiatorObjectUUID", "pn_io.cminitiator_uuid", + FT_GUID, BASE_NONE, 0x0, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_parameter_server_objectuuid, + { "ParameterServerObjectUUID", "pn_io.parameter_server_objectuuid", + FT_GUID, BASE_NONE, 0x0, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties, + { "ARProperties", "pn_io.ar_properties", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_state, + { "State", "pn_io.ar_properties.state", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_state), 0x00000007, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_supervisor_takeover_allowed, + { "SupervisorTakeoverAllowed", "pn_io.ar_properties.supervisor_takeover_allowed", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_supervisor_takeover_allowed), 0x00000008, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_parameterization_server, + { "ParameterizationServer", "pn_io.ar_properties.parameterization_server", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_parameterization_server), 0x00000010, + NULL, HFILL } + }, + { &hf_pn_io_artype_req, + { "ARType", "pn_io.artype_req", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + { &hf_pn_io_ar_properties_companion_ar, + { "CompanionAR", "pn_io.ar_properties.companion_ar", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_companion_ar), 0x00000600, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_achnowledge_companion_ar, + { "AcknowledgeCompanionAR", "pn_io.ar_properties.acknowledge_companion_ar", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_acknowldege_companion_ar), 0x00000800, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_reserved, + { "Reserved", "pn_io.ar_properties.reserved", + FT_UINT32, BASE_HEX, NULL, 0x0FFFF000, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_time_aware_system, + { "TimeAwareSystem", "pn_io.ar_properties.time_aware_system", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_time_aware_system), 0x10000000, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_combined_object_container_with_legacy_startupmode, + { "CombinedObjectContainer", "pn_io.ar_properties.combined_object_container", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_combined_object_container_with_legacy_startupmode), 0x20000000, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_combined_object_container_with_advanced_startupmode, + { "CombinedObjectContainer", "pn_io.ar_properties.combined_object_container", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_combined_object_container_with_advanced_startupmode), 0x20000000, + NULL, HFILL } + }, + { &hf_pn_io_arproperties_StartupMode, + { "StartupMode", "pn_io.ar_properties.StartupMode", + FT_UINT32, BASE_HEX, VALS(pn_io_arpropertiesStartupMode), 0x40000000, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_pull_module_alarm_allowed, + { "PullModuleAlarmAllowed", "pn_io.ar_properties.pull_module_alarm_allowed", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_pull_module_alarm_allowed), 0x80000000, + NULL, HFILL } + }, + { &hf_pn_RedundancyInfo, + { "RedundancyInfo.EndPoint", "pn_io.srl_data.redundancyInfo", + FT_UINT16, BASE_HEX, VALS(pn_io_RedundancyInfo), 0x0003, + NULL, HFILL } + }, + { &hf_pn_RedundancyInfo_reserved, + { "RedundancyInfo.reserved", "pn_io.srl_data.redundancyInfoReserved", + FT_UINT16, BASE_HEX, NULL, 0xFFFC, + NULL, HFILL } + }, + { &hf_pn_io_number_of_ARDATAInfo, + { "ARDataInfo.NumberOfEntries", "pn_io.number_of_ARDATAInfo", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_cminitiator_activitytimeoutfactor, + { "CMInitiatorActivityTimeoutFactor", "pn_io.cminitiator_activitytimeoutfactor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, /* XXX - special values */ + { &hf_pn_io_cminitiator_udprtport, + { "CMInitiatorUDPRTPort", "pn_io.cminitiator_udprtport", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, /* XXX - special values */ + { &hf_pn_io_station_name_length, + { "StationNameLength", "pn_io.station_name_length", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_cminitiator_station_name, + { "CMInitiatorStationName", "pn_io.cminitiator_station_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_parameter_server_station_name, + { "ParameterServerStationName", "pn_io.parameter_server_station_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_cmresponder_macadd, + { "CMResponderMacAdd", "pn_io.cmresponder_macadd", + FT_ETHER, BASE_NONE, 0x0, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_cmresponder_udprtport, + { "CMResponderUDPRTPort", "pn_io.cmresponder_udprtport", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, /* XXX - special values */ + { &hf_pn_io_number_of_iocrs, + { "NumberOfIOCRs", "pn_io.number_of_iocrs", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_tree, + { "IOCR", "pn_io.iocr_tree", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_type, + { "IOCRType", "pn_io.iocr_type", + FT_UINT16, BASE_HEX, VALS(pn_io_iocr_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_reference, + { "IOCRReference", "pn_io.iocr_reference", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_SubframeOffset, + { "-> SubframeOffset", "pn_io.subframe_offset", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_SubframeData, + { "SubframeData", "pn_io.subframe_data", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_RedundancyDataHoldFactor, + { "RedundancyDataHoldFactor", "pn_io.RedundancyDataHoldFactor", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_RedundancyDataHoldFactor), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_sr_properties, + { "SRProperties", "pn_io.sr_properties", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_sr_properties_InputValidOnBackupAR_with_SRProperties_Mode_0, + { "InputValidOnBackupAR", "pn_io.sr_properties.InputValidOnBackupAR", + FT_BOOLEAN, 32, TFS(&tfs_pn_io_sr_properties_BackupAR_with_SRProperties_Mode_0), 0x00000001, + NULL, HFILL } + }, + { &hf_pn_io_sr_properties_InputValidOnBackupAR_with_SRProperties_Mode_1, + { "InputValidOnBackupAR", "pn_io.sr_properties.InputValidOnBackupAR", + FT_BOOLEAN, 32, TFS(&tfs_pn_io_sr_properties_BackupAR_with_SRProperties_Mode_1), 0x00000001, + NULL, HFILL } + }, + { &hf_pn_io_sr_properties_Reserved_1, + { "Reserved_1", "pn_io.sr_properties.Reserved_1", + FT_BOOLEAN, 32, TFS(&tfs_pn_io_sr_properties_Reserved1), 0x00000002, + NULL, HFILL } + }, + { &hf_pn_io_sr_properties_Mode, + { "Mode", "pn_io.sr_properties.Mode", + FT_BOOLEAN, 32, TFS(&tfs_pn_io_sr_properties_Mode), 0x00000004, + NULL, HFILL } + }, + { &hf_pn_io_sr_properties_Reserved_2, + { "Reserved_2", "pn_io.sr_properties.Reserved_2", + FT_UINT32, BASE_HEX, NULL, 0x0000FFF8, + NULL, HFILL } + }, + { &hf_pn_io_sr_properties_Reserved_3, + { "Reserved_3", "pn_io.sr_properties.Reserved_3", + FT_UINT32, BASE_HEX, NULL, 0xFFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_arvendor_strucidentifier_if0_low, + { "APStructureIdentifier: Vendor specific", "pn_io.structidentifier_api_0_low", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_arvendor_strucidentifier_if0_high, + { "APStructureIdentifier: Administrative number for common profiles", "pn_io.structidentifier_api_0_high", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_arvendor_strucidentifier_if0_is8000, + { "APStructureIdentifier: Extended identification rules", "pn_io.tructidentifier_api_0_is8000", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_arvendor_strucidentifier_not0, + { "APStructureIdentifier: Administrative number for application profiles", "pn_io.tructidentifier_api_not_0", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_lt, + { "LT", "pn_io.lt", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties, + { "IOCRProperties", "pn_io.iocr_properties", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties_rtclass, + { "RTClass", "pn_io.iocr_properties.rtclass", + FT_UINT32, BASE_HEX, VALS(pn_io_iocr_properties_rtclass), 0x0000000F, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties_reserved_1, + { "Reserved1", "pn_io.iocr_properties.reserved1", + FT_UINT32, BASE_HEX, NULL, 0x00000FF0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties_media_redundancy, + { "MediaRedundancy", "pn_io.iocr_properties.media_redundancy", + FT_UINT32, BASE_HEX, VALS(pn_io_iocr_properties_media_redundancy), 0x00000800, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties_reserved_2, + { "Reserved2", "pn_io.iocr_properties.reserved2", + FT_UINT32, BASE_HEX, NULL, 0x00FFF000, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties_reserved_3, + { "Reserved3", "pn_io.iocr_properties.reserved3", + FT_UINT32, BASE_HEX, NULL, 0x0F000000, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties_fast_forwarding_mac_adr, + { "FastForwardingMACAdr", "pn_io.iocr_properties.fast_forwarding_mac_adr", + FT_UINT32, BASE_HEX, NULL, 0x20000000, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties_distributed_subframe_watchdog, + { "DistributedSubFrameWatchDog", "pn_io.iocr_properties.distributed_subframe_watchdog", + FT_UINT32, BASE_HEX, NULL, 0x40000000, + NULL, HFILL } + }, + { &hf_pn_io_iocr_properties_full_subframe_structure, + { "FullSubFrameStructure", "pn_io.iocr_properties.full_subframe_structure", + FT_UINT32, BASE_HEX, NULL, 0x80000000, + NULL, HFILL } + }, + { &hf_pn_io_SFIOCRProperties, + { "SFIOCRProperties", "pn_io.SFIOCRProperties", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_DistributedWatchDogFactor, + { "SFIOCRProperties.DistributedWatchDogFactor", "pn_io.SFIOCRProperties.DistributedWatchDogFactor", + FT_UINT32, BASE_HEX, NULL, 0x000000FF, + NULL, HFILL } + }, + { &hf_pn_io_RestartFactorForDistributedWD, + { "SFIOCRProperties.RestartFactorForDistributedWD", "pn_io.SFIOCRProperties.RestartFactorForDistributedWD", + FT_UINT32, BASE_HEX, NULL, 0x0000ff00, + NULL, HFILL } + }, + { &hf_pn_io_SFIOCRProperties_DFPmode, + { "SFIOCRProperties.DFPmode", "pn_io.SFIOCRProperties.DFPmode", + FT_UINT32, BASE_HEX, NULL, 0x00FF0000, + NULL, HFILL } + }, + { &hf_pn_io_SFIOCRProperties_reserved_1, + { "SFIOCRProperties.reserved_1", "pn_io.SFIOCRProperties.reserved_1", + FT_UINT32, BASE_HEX, NULL, 0x0F000000, + NULL, HFILL } + }, + { &hf_pn_io_SFIOCRProperties_reserved_2, + { "SFIOCRProperties.reserved_2", "pn_io.SFIOCRProperties.reserved_2", + FT_UINT32, BASE_HEX, NULL, 0x10000000, + NULL, HFILL } + }, + { &hf_pn_io_SFIOCRProperties_DFPType, + { "SFIOCRProperties.DFPType", "pn_io.SFIOCRProperties.DFPType", + FT_UINT32, BASE_HEX, VALS(pn_io_SFIOCRProperties_DFPType_vals), 0x20000000, + NULL, HFILL } + }, + { &hf_pn_io_SFIOCRProperties_DFPRedundantPathLayout, + { "SFIOCRProperties.DFPRedundantPathLayout", "pn_io.SFIOCRProperties.DFPRedundantPathLayout", + FT_UINT32, BASE_HEX, VALS(pn_io_DFPRedundantPathLayout_decode), 0x40000000, + NULL, HFILL } + }, + { &hf_pn_io_SFIOCRProperties_SFCRC16, + { "SFIOCRProperties.SFCRC16", "pn_io.SFIOCRProperties.SFCRC16", + FT_UINT32, BASE_HEX, VALS(pn_io_SFCRC16_Decode), 0x80000000, + NULL, HFILL } + }, + { &hf_pn_io_data_length, + { "DataLength", "pn_io.data_length", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ir_frame_data, + { "Frame data", "pn_io.ir_frame_data", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_id, + { "FrameID", "pn_io.frame_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_send_clock_factor, + { "SendClockFactor", "pn_io.send_clock_factor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, /* XXX - special values */ + { &hf_pn_io_reduction_ratio, + { "ReductionRatio", "pn_io.reduction_ratio", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, /* XXX - special values */ + { &hf_pn_io_phase, + { "Phase", "pn_io.phase", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_sequence, + { "Sequence", "pn_io.sequence", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_send_offset, + { "FrameSendOffset", "pn_io.frame_send_offset", + FT_UINT32, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_data_properties, + { "FrameDataProperties", "pn_io.frame_data_properties", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_data_properties_forwarding_Mode, + { "ForwardingMode", "pn_io.frame_data_properties_forwardingMode", + FT_UINT32, BASE_HEX, VALS(hf_pn_io_frame_data_properties_forwardingMode), 0x01, + NULL, HFILL } + }, + { &hf_pn_io_frame_data_properties_FastForwardingMulticastMACAdd, + { "FastForwardingMulticastMACAdd", "pn_io.frame_data_properties_MulticastMACAdd", + FT_UINT32, BASE_HEX, VALS(hf_pn_io_frame_data_properties_FFMulticastMACAdd), 0x06, + NULL, HFILL } + }, + { &hf_pn_io_frame_data_properties_FragmentMode, + { "FragmentationMode", "pn_io.frame_data_properties_FragMode", + FT_UINT32, BASE_HEX, VALS(hf_pn_io_frame_data_properties_FragMode), 0x18, + NULL, HFILL } + }, + { &hf_pn_io_frame_data_properties_reserved_1, + { "Reserved_1", "pn_io.frame_data.reserved_1", + FT_UINT32, BASE_HEX, NULL, 0x0000FFE0, + NULL, HFILL } + }, + { &hf_pn_io_frame_data_properties_reserved_2, + { "Reserved_2", "pn_io.frame_data.reserved_2", + FT_UINT32, BASE_HEX, NULL, 0xFFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_watchdog_factor, + { "WatchdogFactor", "pn_io.watchdog_factor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_data_hold_factor, + { "DataHoldFactor", "pn_io.data_hold_factor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_tag_header, + { "IOCRTagHeader", "pn_io.iocr_tag_header", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocr_multicast_mac_add, + { "IOCRMulticastMACAdd", "pn_io.iocr_multicast_mac_add", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_apis, + { "NumberOfAPIs", "pn_io.number_of_apis", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_io_data_objects, + { "NumberOfIODataObjects", "pn_io.number_of_io_data_objects", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_iocs, + { "NumberOfIOCS", "pn_io.number_of_iocs", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocs_frame_offset, + { "IOCSFrameOffset", "pn_io.iocs_frame_offset", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_alarmcr_type, + { "AlarmCRType", "pn_io.alarmcr_type", + FT_UINT16, BASE_HEX, VALS(pn_io_alarmcr_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_alarmcr_properties, + { "AlarmCRProperties", "pn_io.alarmcr_properties", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_alarmcr_properties_priority, + { "priority", "pn_io.alarmcr_properties.priority", + FT_UINT32, BASE_HEX, VALS(pn_io_alarmcr_properties_priority), 0x00000001, + NULL, HFILL } + }, + { &hf_pn_io_alarmcr_properties_transport, + { "Transport", "pn_io.alarmcr_properties.transport", + FT_UINT32, BASE_HEX, VALS(pn_io_alarmcr_properties_transport), 0x00000002, + NULL, HFILL } + }, + { &hf_pn_io_alarmcr_properties_reserved, + { "Reserved", "pn_io.alarmcr_properties.reserved", + FT_UINT32, BASE_HEX, NULL, 0xFFFFFFFC, + NULL, HFILL } + }, + { &hf_pn_io_rta_timeoutfactor, + { "RTATimeoutFactor", "pn_io.rta_timeoutfactor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, /* XXX - special values */ + { &hf_pn_io_rta_retries, + { "RTARetries", "pn_io.rta_retries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, /* XXX - only values 3 - 15 allowed */ + { &hf_pn_io_localalarmref, + { "LocalAlarmReference", "pn_io.localalarmref", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, /* XXX - special values */ + { &hf_pn_io_remotealarmref, + { "RemoteAlarmReference", "pn_io.remotealarmref", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, /* XXX - special values */ + { &hf_pn_io_maxalarmdatalength, + { "MaxAlarmDataLength", "pn_io.maxalarmdatalength", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, /* XXX - only values 200 - 1432 allowed */ + { &hf_pn_io_alarmcr_tagheaderhigh, + { "AlarmCRTagHeaderHigh", "pn_io.alarmcr_tagheaderhigh", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, /* XXX - 16 bitfield! */ + { &hf_pn_io_alarmcr_tagheaderlow, + { "AlarmCRTagHeaderLow", "pn_io.alarmcr_tagheaderlow", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, /* XXX - 16 bitfield!*/ + { &hf_pn_io_api_tree, + { "API", "pn_io.api_tree", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_module_tree, + { "Module", "pn_io.module_tree", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_submodule_tree, + { "Submodule", "pn_io.submodule_tree", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_io_data_object, + { "IODataObject", "pn_io.io_data_object", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_io_data_object_frame_offset, + { "IODataObjectFrameOffset", "pn_io.io_data_object.frame_offset", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_io_cs, + { "IOCS", "pn_io.io_cs", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_substitutionmode, + { "Substitutionmode", "pn_io.substitutionmode", + FT_UINT16, BASE_HEX, VALS(pn_io_substitutionmode), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_IRData_uuid, + { "IRDataUUID", "pn_io.IRData_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ar_uuid, + { "ARUUID", "pn_io.ar_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_target_ar_uuid, + { "TargetARUUID", "pn_io.target_ar_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ar_discriminator, + { "Discriminator", "pn_io.ar_discriminator", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ar_configid, + { "ConfigID", "pn_io.ar_configid", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ar_arnumber, + { "ARnumber", "pn_io.ar_arnumber", + FT_UINT16, BASE_HEX, VALS(pn_io_ar_arnumber), 0x0007, + NULL, HFILL } + }, + { &hf_pn_io_ar_arresource, + { "ARresource", "pn_io.ar_arresource", + FT_UINT16, BASE_HEX, VALS(pn_io_ar_arresource), 0x0018, + NULL, HFILL } + }, + { &hf_pn_io_ar_arreserved, + { "ARreserved", "pn_io.ar_arreserved", + FT_UINT16, BASE_HEX, NULL, 0xFFE0, + NULL, HFILL } + }, + { &hf_pn_io_ar_selector, + { "Selector", "pn_io.ar_selector", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_api, + { "API", "pn_io.api", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_slot_nr, + { "SlotNumber", "pn_io.slot_nr", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_subslot_nr, + { "SubslotNumber", "pn_io.subslot_nr", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_index, + { "Index", "pn_io.index", + FT_UINT16, BASE_HEX, VALS(pn_io_index), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_seq_number, + { "SeqNumber", "pn_io.seq_number", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_record_data_length, + { "RecordDataLength", "pn_io.record_data_length", + FT_UINT32, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_add_val1, + { "AdditionalValue1", "pn_io.add_val1", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_add_val2, + { "AdditionalValue2", "pn_io.add_val2", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_block_header, + { "BlockHeader", "pn_io.block_header", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_block_type, + { "BlockType", "pn_io.block_type", + FT_UINT16, BASE_HEX, VALS(pn_io_block_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_block_length, + { "BlockLength", "pn_io.block_length", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_block_version_high, + { "BlockVersionHigh", "pn_io.block_version_high", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_block_version_low, + { "BlockVersionLow", "pn_io.block_version_low", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_sessionkey, + { "SessionKey", "pn_io.session_key", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_control_alarm_sequence_number, + { "AlarmSequenceNumber", "pn_io.control_alarm_sequence_number", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_control_command, + { "ControlCommand", "pn_io.control_command", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_control_command_reserved, + { "ControlBlockProperties.reserved", "pn_io.control_properties_reserved", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_control_command_prmend, + { "PrmEnd", "pn_io.control_command.prmend", + FT_UINT16, BASE_DEC, NULL, 0x0001, + NULL, HFILL } + }, + { &hf_pn_io_control_command_applready, + { "ApplicationReady", "pn_io.control_command.applready", + FT_UINT16, BASE_DEC, NULL, 0x0002, + NULL, HFILL } + }, + { &hf_pn_io_control_command_release, + { "Release", "pn_io.control_command.release", + FT_UINT16, BASE_DEC, NULL, 0x0004, + NULL, HFILL } + }, + { &hf_pn_io_control_command_done, + { "Done", "pn_io.control_command.done", + FT_UINT16, BASE_DEC, NULL, 0x0008, + NULL, HFILL } + }, + { &hf_pn_io_control_command_ready_for_companion, + { "ReadyForCompanion", "pn_io.control_command.ready_for_companion", + FT_UINT16, BASE_DEC, NULL, 0x0010, + NULL, HFILL } + }, + { &hf_pn_io_control_command_ready_for_rt_class3, + { "ReadyForRT Class 3", "pn_io.control_command.ready_for_rt_class3", + FT_UINT16, BASE_DEC, NULL, 0x0020, + NULL, HFILL } + }, + { &hf_pn_io_control_command_prmbegin, + { "PrmBegin", "pn_io.control_command.prmbegin", + FT_UINT16, BASE_DEC, VALS(pn_io_control_properties_prmbegin_vals), 0x0040, + NULL, HFILL } + }, + { &hf_pn_io_control_command_reserved_7_15, + { "ControlBlockProperties.reserved", "pn_io.control_properties_reserved_7_15", + FT_UINT16, BASE_HEX, NULL, 0xFF80, + NULL, HFILL } + }, + { &hf_pn_io_control_block_properties, + { "ControlBlockProperties", "pn_io.control_block_properties", + FT_UINT16, BASE_HEX, VALS(pn_io_control_properties_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_control_block_properties_applready, + { "ControlBlockProperties", "pn_io.control_block_properties.appl_ready", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_control_block_properties_applready_bit0, + { "ApplicationReady.Bit0", "pn_io.control_block_properties.appl_ready_bit0", + FT_UINT16, BASE_HEX, VALS(pn_io_control_properties_application_ready_bit0_vals), 0x0001, + NULL, HFILL } + }, + { &hf_pn_io_control_block_properties_applready_bit1, + { "ApplicationReady.Bit1", "pn_io.control_block_properties.appl_ready_bit1", + FT_UINT16, BASE_HEX, VALS(pn_io_control_properties_application_ready_bit1_vals), 0x0002, + NULL, HFILL } + }, + { &hf_pn_io_control_block_properties_applready_otherbits, + { "ApplicationReady.Bit2-15(reserved)", "pn_io.control_block_properties.appl_ready_otherbits", + FT_UINT16, BASE_HEX, NULL, 0xFFFC, + NULL, HFILL } + }, + { &hf_pn_io_SubmoduleListEntries, + { "NumberOfEntries", "pn_io.SubmoduleListEntries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_block, + { "Block", "pn_io.block", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_alarm_type, + { "AlarmType", "pn_io.alarm_type", + FT_UINT16, BASE_HEX, VALS(pn_io_alarm_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_alarm_specifier, + { "AlarmSpecifier", "pn_io.alarm_specifier", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_alarm_specifier_sequence, + { "SequenceNumber", "pn_io.alarm_specifier.sequence", + FT_UINT16, BASE_HEX, NULL, 0x07FF, + NULL, HFILL } + }, + { &hf_pn_io_alarm_specifier_channel, + { "ChannelDiagnosis", "pn_io.alarm_specifier.channel", + FT_UINT16, BASE_HEX, NULL, 0x0800, + NULL, HFILL } + }, + { &hf_pn_io_alarm_specifier_manufacturer, + { "ManufacturerSpecificDiagnosis", "pn_io.alarm_specifier.manufacturer", + FT_UINT16, BASE_HEX, NULL, 0x1000, + NULL, HFILL } + }, + { &hf_pn_io_alarm_specifier_submodule, + { "SubmoduleDiagnosisState", "pn_io.alarm_specifier.submodule", + FT_UINT16, BASE_HEX, NULL, 0x2000, + NULL, HFILL } + }, + { &hf_pn_io_alarm_specifier_ardiagnosis, + { "ARDiagnosisState", "pn_io.alarm_specifier.ardiagnosis", + FT_UINT16, BASE_HEX, NULL, 0x8000, + NULL, HFILL } + }, + { &hf_pn_io_alarm_dst_endpoint, + { "AlarmDstEndpoint", "pn_io.alarm_dst_endpoint", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_alarm_src_endpoint, + { "AlarmSrcEndpoint", "pn_io.alarm_src_endpoint", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pdu_type, + { "PDUType", "pn_io.pdu_type", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pdu_type_type, + { "Type", "pn_io.pdu_type.type", + FT_UINT8, BASE_HEX, VALS(pn_io_pdu_type), 0x0F, + NULL, HFILL } + }, + { &hf_pn_io_pdu_type_version, + { "Version", "pn_io.pdu_type.version", + FT_UINT8, BASE_HEX, NULL, 0xF0, + NULL, HFILL } + }, + { &hf_pn_io_add_flags, + { "AddFlags", "pn_io.add_flags", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_window_size, + { "WindowSize", "pn_io.window_size", + FT_UINT8, BASE_DEC, NULL, 0x0F, + NULL, HFILL } + }, + { &hf_pn_io_tack, + { "TACK", "pn_io.tack", + FT_UINT8, BASE_HEX, NULL, 0xF0, + NULL, HFILL } + }, + { &hf_pn_io_send_seq_num, + { "SendSeqNum", "pn_io.send_seq_num", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ack_seq_num, + { "AckSeqNum", "pn_io.ack_seq_num", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_var_part_len, + { "VarPartLen", "pn_io.var_part_len", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_module_ident_number, + { "ModuleIdentNumber", "pn_io.module_ident_number", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_submodule_ident_number, + { "SubmoduleIdentNumber", "pn_io.submodule_ident_number", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_number_of_modules, + { "NumberOfModules", "pn_io.number_of_modules", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_module_properties, + { "ModuleProperties", "pn_io.module_properties", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_module_state, + { "ModuleState", "pn_io.module_state", + FT_UINT16, BASE_HEX, VALS(pn_io_module_state), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_submodules, + { "NumberOfSubmodules", "pn_io.number_of_submodules", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_submodule_properties, + { "SubmoduleProperties", "pn_io.submodule_properties", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_submodule_properties_type, + { "Type", "pn_io.submodule_properties.type", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_properties_type), 0x0003, + NULL, HFILL } + }, + { &hf_pn_io_submodule_properties_shared_input, + { "SharedInput", "pn_io.submodule_properties.shared_input", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_properties_shared_input), 0x0004, + NULL, HFILL } + }, + { &hf_pn_io_submodule_properties_reduce_input_submodule_data_length, + { "ReduceInputSubmoduleDataLength", "pn_io.submodule_properties.reduce_input_submodule_data_length", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_properties_reduce_input_submodule_data_length), 0x0008, + NULL, HFILL } + }, + { &hf_pn_io_submodule_properties_reduce_output_submodule_data_length, + { "ReduceOutputSubmoduleDataLength", "pn_io.submodule_properties.reduce_output_submodule_data_length", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_properties_reduce_output_submodule_data_length), 0x0010, + NULL, HFILL } + }, + { &hf_pn_io_submodule_properties_discard_ioxs, + { "DiscardIOXS", "pn_io.submodule_properties.discard_ioxs", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_properties_discard_ioxs), 0x0020, + NULL, HFILL } + }, + { &hf_pn_io_submodule_properties_reserved, + { "Reserved", "pn_io.submodule_properties.reserved", + FT_UINT16, BASE_HEX, NULL, 0xFFC0, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state, + { "SubmoduleState", "pn_io.submodule_state", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_format_indicator, + { "FormatIndicator", "pn_io.submodule_state.format_indicator", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_format_indicator), 0x8000, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_add_info, + { "AddInfo", "pn_io.submodule_state.add_info", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_add_info), 0x0007, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_advice, + { "Advice", "pn_io.submodule_state.advice", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_advice), 0x0008, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_maintenance_required, + { "MaintenanceRequired", "pn_io.submodule_state.maintenance_required", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_maintenance_required), 0x0010, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_maintenance_demanded, + { "MaintenanceDemanded", "pn_io.submodule_state.maintenance_demanded", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_maintenance_demanded), 0x0020, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_fault, + { "Fault", "pn_io.submodule_state.fault", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_fault), 0x0040, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_ar_info, + { "ARInfo", "pn_io.submodule_state.ar_info", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_ar_info), 0x0780, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_ident_info, + { "IdentInfo", "pn_io.submodule_state.ident_info", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_ident_info), 0x7800, + NULL, HFILL } + }, + { &hf_pn_io_submodule_state_detail, + { "Detail", "pn_io.submodule_state.detail", + FT_UINT16, BASE_HEX, VALS(pn_io_submodule_state_detail), 0x7FFF, + NULL, HFILL } + }, + { &hf_pn_io_data_description_tree, + { "DataDescription", "pn_io.data_description_tree", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_data_description, + { "DataDescription", "pn_io.data_description", + FT_UINT16, BASE_HEX, VALS(pn_io_data_description), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_submodule_data_length, + { "SubmoduleDataLength", "pn_io.submodule_data_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_iocs, + { "LengthIOCS", "pn_io.length_iocs", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_iops, + { "LengthIOPS", "pn_io.length_iops", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_iocs, + { "IOCS", "pn_io.ioxs", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iops, + { "IOPS", "pn_io.iops", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ioxs_extension, + { "Extension (1:another IOxS follows/0:no IOxS follows)", "pn_io.ioxs.extension", + FT_UINT8, BASE_HEX, NULL, 0x01, + NULL, HFILL } + }, + { &hf_pn_io_ioxs_res14, + { "Reserved (should be zero)", "pn_io.ioxs.res14", + FT_UINT8, BASE_HEX, NULL, 0x1E, + NULL, HFILL } + }, + { &hf_pn_io_ioxs_instance, + { "Instance (only valid, if DataState is bad)", + "pn_io.ioxs.instance", FT_UINT8, BASE_HEX, VALS(pn_io_ioxs), + 0x60, NULL, HFILL } + }, + { &hf_pn_io_ioxs_datastate, + { "DataState (1:good/0:bad)", "pn_io.ioxs.datastate", + FT_UINT8, BASE_HEX, NULL, 0x80, + NULL, HFILL } + }, + { &hf_pn_io_address_resolution_properties, + { "AddressResolutionProperties", "pn_io.address_resolution_properties", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mci_timeout_factor, + { "MCITimeoutFactor", "pn_io.mci_timeout_factor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_provider_station_name, + { "ProviderStationName", "pn_io.provider_station_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_user_structure_identifier, + { "UserStructureIdentifier", "pn_io.user_structure_identifier", + FT_UINT16, BASE_HEX, VALS(pn_io_user_structure_identifier), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_user_structure_identifier_manf, + { "UserStructureIdentifier manufacturer specific", "pn_io.user_structure_identifier_manf", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ar_properties_reserved_1, + { "Reserved_1", "pn_io.ar_properties.reserved_1", + FT_UINT32, BASE_HEX, NULL, 0x000000E0, + NULL, HFILL }}, + { &hf_pn_io_ar_properties_device_access, + { "DeviceAccess", "pn_io.ar_properties.device_access", + FT_UINT32, BASE_HEX, VALS(pn_io_arproperties_DeviceAccess), 0x00000100, + NULL, HFILL }}, + { &hf_pn_io_subframe_data, + { "SubFrameData", "pn_io.subframe_data", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_subframe_reserved2, + { "Reserved2", "pn_io.subframe_data.reserved2", + FT_UINT32, BASE_HEX, NULL, 0xFFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_subframe_data_length, + { "DataLength", "pn_io.subframe_data.data_length", + FT_UINT32, BASE_HEX, NULL, 0x0000FF00, + NULL, HFILL } + }, + { &hf_pn_io_subframe_reserved1, + { "Reserved1", "pn_io.subframe_data.reserved1", + FT_UINT32, BASE_HEX, NULL, 0x00000080, + NULL, HFILL } + }, + { &hf_pn_io_subframe_data_position, + { "DataPosition", "pn_io.subframe_data.position", + FT_UINT32, BASE_HEX, NULL, 0x0000007F, + NULL, HFILL } + }, + { &hf_pn_io_subframe_data_reserved1, + { "Reserved1", "pn_io.subframe_data.reserved_1", + FT_UINT32, BASE_HEX, NULL, 0x00000080, + NULL, HFILL } + }, + { &hf_pn_io_subframe_data_reserved2, + { "Reserved2", "pn_io.subframe_data.reserved_2", + FT_UINT32, BASE_HEX, NULL, 0xFFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_channel_number, + { "ChannelNumber", "pn_io.channel_number", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_channel_properties, + { "ChannelProperties", "pn_io.channel_properties", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_channel_properties_type, + { "Type", "pn_io.channel_properties.type", + FT_UINT16, BASE_HEX, VALS(pn_io_channel_properties_type), 0x00FF, + NULL, HFILL } + }, + { &hf_pn_io_channel_properties_accumulative, + { "Accumulative", "pn_io.channel_properties.accumulative", + FT_UINT16, BASE_HEX, VALS(pn_io_channel_properties_accumulative_vals), 0x0100, + NULL, HFILL } + }, + { &hf_pn_io_NumberOfSubframeBlocks, + { "NumberOfSubframeBlocks", "pn_io.NumberOfSubframeBlocks", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_channel_properties_maintenance, + { "Maintenance (Severity)", "pn_io.channel_properties.maintenance", + FT_UINT16, BASE_HEX, VALS(pn_io_channel_properties_maintenance), 0x0600, + NULL, HFILL } + }, + { &hf_pn_io_channel_properties_specifier, + { "Specifier", "pn_io.channel_properties.specifier", + FT_UINT16, BASE_HEX, VALS(pn_io_channel_properties_specifier), 0x1800, + NULL, HFILL } + }, + { &hf_pn_io_channel_properties_direction, + { "Direction", "pn_io.channel_properties.direction", + FT_UINT16, BASE_HEX, VALS(pn_io_channel_properties_direction), 0xE000, + NULL, HFILL } + }, + + { &hf_pn_io_channel_error_type, + { "ChannelErrorType", "pn_io.channel_error_type", + FT_UINT16, BASE_HEX, VALS(pn_io_channel_error_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type0", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8000, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type0800", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8000), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8001, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type8001", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8001), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8002, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type8002", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8002), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8003, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type8003", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8003), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8004, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type8004", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8004), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8005, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type8005", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8005), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8007, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type8007", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8007), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8008, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type8008", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8008), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x800A, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type800A", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x800A), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x800B, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type800B", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x800B), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x800C, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type800C", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x800C), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type0x8010, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type8010", + FT_UINT16, BASE_HEX, VALS(pn_io_ext_channel_error_type0x8010), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_error_type, + { "ExtChannelErrorType", "pn_io.ext_channel_error_type", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ext_channel_add_value, + { "ExtChannelAddValue", "pn_io.ext_channel_add_value", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_qualified_channel_qualifier, + { "QualifiedChannelQualifier", "pn_io.qualified_channel_qualifier", + FT_UINT32, BASE_HEX, VALS(pn_io_qualified_channel_qualifier), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ptcp_subdomain_id, + { "PTCPSubdomainID", "pn_io.ptcp_subdomain_id", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ir_data_id, + { "IRDataID", "pn_io.ir_data_id", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_max_bridge_delay, + { "MaxBridgeDelay", "pn_io.max_bridge_delay", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_ports, + { "NumberOfPorts", "pn_io.number_of_ports", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_max_port_tx_delay, + { "MaxPortTxDelay", "pn_io.max_port_tx_delay", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_max_port_rx_delay, + { "MaxPortRxDelay", "pn_io.max_port_rx_delay", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_max_line_rx_delay, + { "MaxLineRxDelay", "pn_io.max_line_rx_delay", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_yellowtime, + { "YellowTime", "pn_io.yellowtime", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_reserved_interval_begin, + { "ReservedIntervalBegin", "pn_io.reserved_interval_begin", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_reserved_interval_end, + { "ReservedIntervalEnd", "pn_io.reserved_interval_end", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pllwindow, + { "PLLWindow", "pn_io.pllwindow", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_sync_send_factor, + { "SyncSendFactor", "pn_io.sync_send_factor", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_sync_properties, + { "SyncProperties", "pn_io.sync_properties", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_sync_frame_address, + { "SyncFrameAddress", "pn_io.sync_frame_address", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ptcp_timeout_factor, + { "PTCPTimeoutFactor", "pn_io.ptcp_timeout_factor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ptcp_takeover_timeout_factor, + { "PTCPTakeoverTimeoutFactor", "pn_io.ptcp_takeover_timeout_factor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ptcp_master_startup_time, + { "PTCPMasterStartupTime", "pn_io.ptcp_master_startup_time", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ptcp_master_priority_1, + { "PTCP_MasterPriority1", "pn_io.ptcp_master_priority_1", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ptcp_master_priority_2, + { "PTCP_MasterPriority2", "pn_io.ptcp_master_priority_2", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ptcp_length_subdomain_name, + { "PTCPLengthSubdomainName", "pn_io.ptcp_length_subdomain_name", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ptcp_subdomain_name, + { "PTCPSubdomainName", "pn_io.ptcp_subdomain_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_MultipleInterfaceMode_NameOfDevice, + { "MultipleInterfaceMode.NameOfDevice", "pn_io.MultipleInterfaceMode_NameOfDevice", + FT_UINT32, BASE_HEX, VALS(pn_io_MultipleInterfaceMode_NameOfDevice), 0x01, + NULL, HFILL } + }, + { &hf_pn_io_MultipleInterfaceMode_reserved_1, + { "MultipleInterfaceMode.Reserved_1", "pn_io.MultipleInterfaceMode_reserved_1", + FT_UINT32, BASE_HEX, NULL, 0xFFFE, + NULL, HFILL } + }, + { &hf_pn_io_MultipleInterfaceMode_reserved_2, + { "MultipleInterfaceMode.Reserved_2", "pn_io.MultipleInterfaceMode_reserved_2", + FT_UINT32, BASE_HEX, NULL, 0xFFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_counter_status, + { "CounterStatus", "pn_io.CounterStatus", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_counter_status_ifInOctets, + { "CounterStatus.ifInOctets", "pn_io.CounterStatus.ifInOctets", + FT_BOOLEAN, 16, TFS(&pn_io_pdportstatistic_counter_status_contents), 0x0001, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_counter_status_ifOutOctets, + { "CounterStatus.ifOutOctets", "pn_io.CounterStatus.ifOutOctets", + FT_BOOLEAN, 16, TFS(&pn_io_pdportstatistic_counter_status_contents), 0x0002, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_counter_status_ifInDiscards, + { "CounterStatus.ifInDiscards", "pn_io.CounterStatus.ifInDiscards", + FT_BOOLEAN, 16, TFS(&pn_io_pdportstatistic_counter_status_contents), 0x0004, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_counter_status_ifOutDiscards, + { "CounterStatus.ifOutDiscards", "pn_io.CounterStatus.ifOutDiscards", + FT_BOOLEAN, 16, TFS(&pn_io_pdportstatistic_counter_status_contents), 0x0008, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_counter_status_ifInErrors, + { "CounterStatus.ifInErrors", "pn_io.CounterStatus.ifInErrors", + FT_BOOLEAN, 16, TFS(&pn_io_pdportstatistic_counter_status_contents), 0x0010, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_counter_status_ifOutErrors, + { "CounterStatus.ifOutErrors", "pn_io.CounterStatus.ifOutErrors", + FT_BOOLEAN, 16, TFS(&pn_io_pdportstatistic_counter_status_contents), 0x0020, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_counter_status_reserved, + { "CounterStatus.Reserved", "pn_io.CounterStatus.Reserved", + FT_UINT16, BASE_HEX, VALS(pn_io_pdportstatistic_counter_status_reserved), 0xFFC0, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_ifInOctets, + { "ifInOctets", "pn_io.ifInOctets", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_ifOutOctets, + { "ifOutOctets", "pn_io.ifOutOctets", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_ifInDiscards, + { "ifInDiscards", "pn_io.ifInDiscards", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_ifOutDiscards, + { "ifOutDiscards", "pn_io.ifOutDiscards", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_ifInErrors, + { "ifInErrors", "pn_io.ifInErrors", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pdportstatistic_ifOutErrors, + { "ifOutErrors", "pn_io.ifOutErrors", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_domain_boundary, + { "DomainBoundary", "pn_io.domain_boundary", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_domain_boundary_ingress, + { "DomainBoundaryIngress", "pn_io.domain_boundary.ingress", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_domain_boundary_egress, + { "DomainBoundaryEgress", "pn_io.domain_boundary.egress", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_multicast_boundary, + { "MulticastBoundary", "pn_io.multicast_boundary", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_adjust_properties, + { "AdjustProperties", "pn_io.adjust_properties", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_PreambleLength, + { "Preamble Length", "pn_io.preamble_length", + FT_UINT16, BASE_DEC_HEX, VALS(pn_io_preamble_length), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_max_supported_record_size, + { "MaxSupportedRecordSize", "pn_io.tsn_upload_network_attributes.max_supported_record_size", + FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_max_supported_record_size_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_transfer_time_tx, + { "TransferTimeTX", "pn_io.tsn_upload_network_attributes.transfer_time_tx", + FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_transfer_time_tx_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_transfer_time_rx, + { "TransferTimeRX", "pn_io.tsn_upload_network_attributes.transfer_time_rx", + FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_transfer_time_rx_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_number_of_queues, + { "NumberOfQueues", "pn_io.tsn_port_id_block.number_of_queues", + FT_UINT8, BASE_HEX, VALS(pn_io_tsn_number_of_queues_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_forwarding_delay_block_number_of_entries, + { "TSNForwardingDelayBlockNumberOfEntries", "pn_io.tsn_forward_delaying_block.number_of_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_port_id_block_number_of_entries, + { "TSNPortIDBlockNumberOfEntries", "pn_io.tsn_port_id_block.number_of_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_expected_neighbor_block_number_of_entries, + { "TSNExpectedNeighborBlockNumberOfEntries", "pn_io.tsn_expected_neighbor_block.number_of_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_port_capabilities_time_aware, + { "TSNPortCapabilities.TimeAware", "pn_io.tsn_port_capabilities.time_aware", + FT_UINT8, BASE_HEX, VALS(pn_io_tsn_port_capabilities_time_aware_vals), 0x01, + NULL, HFILL } + }, + { &hf_pn_io_tsn_port_capabilities_preemption, + { "TSNPortCapabilities.Preemption", "pn_io.tsn_port_capabilities.preemption", + FT_UINT8, BASE_HEX, VALS(pn_io_tsn_port_capabilities_preemption_vals), 0x02, + NULL, HFILL } + }, + { &hf_pn_io_tsn_port_capabilities_queue_masking, + { "TSNPortCapabilities.QueueMasking", "pn_io.tsn_port_capabilities.queue_masking", + FT_UINT8, BASE_HEX, VALS(pn_io_tsn_port_capabilities_queue_masking_vals), 0x04, + NULL, HFILL } + }, + { &hf_pn_io_tsn_port_capabilities_reserved, + { "TSNPortCapabilities.Reserved", "pn_io.tsn_port_capabilities_reserved", + FT_UINT8, BASE_HEX, NULL, 0xF8, + NULL, HFILL } + }, + { &hf_pn_io_tsn_forwarding_group, + { "ForwardingGroup", "pn_io.tsn_port_id_block.forwarding_group", + FT_UINT8, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_forwarding_group_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_forwarding_group_ingress, + { "ForwardingGroupIngress", "pn_io.tsn_port_id_block.forwarding_group_ingress", + FT_UINT8, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_forwarding_group_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_forwarding_group_egress, + { "ForwardingGroupEgress", "pn_io.tsn_port_id_block.forwarding_group_egress", + FT_UINT8, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_forwarding_group_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_stream_class, + { "StreamClass", "pn_io.tsn_forwarding_delay_entry.stream_class", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_stream_class_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_dependent_forwarding_delay, + { "DependentForwardDelay", "pn_io.tsn_forwarding_delay_entry.dependent_forwarding_delay", + FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_dependent_forwarding_delay_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_independent_forwarding_delay, + { "IndependentForwardDelay", "pn_io.tsn_forwarding_delay_entry.independent_forwarding_delay", + FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_independent_forwarding_delay_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_nme_parameter_uuid, + { "NMEParameterUUID", "pn_io.tsn_nme_parameter_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config, + { "TSNDomainVIDConfig", "pn_io.tsn_domain_vid_config", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_stream_high_vid, + { "TSNDomainVIDConfig.StreamHighVID", "pn_io.tsn_domain_vid_config.stream_high_vid", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_domain_vid_config_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_stream_high_red_vid, + { "TSNDomainVIDConfig.StreamHighRedVID", "pn_io.tsn_domain_vid_config.stream_high_red_vid", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_domain_vid_config_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_stream_low_vid, + { "TSNDomainVIDConfig.StreamLowVID", "pn_io.tsn_domain_vid_config.stream_low_vid", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_domain_vid_config_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_stream_low_red_vid, + { "TSNDomainVIDConfig.StreamLowRedVID", "pn_io.tsn_domain_vid_config.stream_low_red_vid", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_domain_vid_config_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_non_stream_vid, + { "TSNDomainVIDConfig.NonStreamVID", "pn_io.tsn_domain_vid_config.non_stream_vid", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_domain_vid_config_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_non_stream_vid_B, + { "TSNDomainVIDConfig.NonStreamVIDB", "pn_io.tsn_domain_vid_config.non_stream_vid_B", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_domain_vid_config_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_non_stream_vid_C, + { "TSNDomainVIDConfig.NonStreamVIDC", "pn_io.tsn_domain_vid_config.non_stream_vid_C", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_domain_vid_config_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_non_stream_vid_D, + { "TSNDomainVIDConfig.NonStreamVIDD", "pn_io.tsn_domain_vid_config.non_stream_vid_D", + FT_UINT16, BASE_HEX, VALS(pn_io_tsn_domain_vid_config_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_vid_config_reserved, + { "TSNDomainVIDConfig.Reserved", "pn_io.tsn_domain_vid_config.reserved", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_tsn_domain_port_config_entries, + { "TSNDomainPortConfig.NumberOfEntries", "pn_io.tsn_domain_port_config.number_of_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_tsn_time_data_block_entries, + { "TSNTimeDataBlock.NumberOfEntries", "pn_io.tsn_time_data_block.number_of_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_tsn_domain_queue_rate_limiter_entries, + { "TSNDomainQueueRateLimiter.NumberOfEntries", "pn_io.tsn_domain_queue_rate_limiter.number_of_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_tsn_domain_port_ingress_rate_limiter_entries, + { "TSNDomainPortIngressRateLimiter.NumberOfEntries", "pn_io.tsn_domain_port_ingress_limiter.number_of_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_config, + { "TSNDomainPortConfig", "pn_io.tsn_domain_port_config", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_config_preemption_enabled, + { "TSNDomainPortConfig.PreemptionEnabled", "pn_io.tsn_domain_port_config.preemption_enabled", + FT_UINT8, BASE_HEX, VALS(pn_io_tsn_domain_port_config_preemption_enabled_vals), 0x01, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_config_boundary_port_config, + { "TSNDomainPortConfig.BoundaryPortConfig", "pn_io.tsn_domain_port_config.boundary_port_config", + FT_UINT8, BASE_HEX, VALS(pn_io_tsn_domain_port_config_boundary_port_config_vals), 0x0E, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_config_reserved, + { "TSNDomainPortConfig.Reserved", "pn_io.tsn_domain_port_config.reserved", + FT_UINT8, BASE_HEX, NULL, 0xF0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_ingress_rate_limiter, + { "TSNDomainPortIngressRateLimiter", "pn_io.tsn_domain_port_ingress_rate_limiter", + FT_UINT64, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_ingress_rate_limiter_cir, + { "TSNDomainPortIngressRateLimiter.Cir", "pn_io.tsn_domain_port_ingress_rate_limiter.cir", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_port_ingress_rate_limiter_cir), 0x000000000000FFFF, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_ingress_rate_limiter_cbs, + { "TSNDomainPortIngressRateLimiter.Cbs", "pn_io.tsn_domain_port_ingress_rate_limiter.cbs", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_port_ingress_rate_limiter_cbs), 0x00000000FFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_ingress_rate_limiter_envelope, + { "TSNDomainPortIngressRateLimiter.Envelope", "pn_io.tsn_domain_port_ingress_rate_limiter.envelope", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_port_ingress_rate_limiter_envelope), 0x0000FFFF00000000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_ingress_rate_limiter_rank, + { "TSNDomainPortIngressRateLimiter.Rank", "pn_io.tsn_domain_port_ingress_rate_limiter.rank", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_port_ingress_rate_limiter_rank), 0xFFFF000000000000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_rate_limiter, + { "TSNDomainQueueRateLimiter", "pn_io.tsn_domain_port_queue_rate_limiter", + FT_UINT64, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_rate_limiter_cir, + { "TSNDomainQueueRateLimiter.Cir", "pn_io.tsn_domain_port_queue_rate_limiter.cir", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_queue_rate_limiter_cir), 0x000000000000FFFF, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_rate_limiter_cbs, + { "TSNDomainQueueRateLimiter.Cbs", "pn_io.tsn_domain_port_queue_rate_limiter.cbs", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_queue_rate_limiter_cbs), 0x00000000FFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_rate_limiter_envelope, + { "TSNDomainQueueRateLimiter.Envelope", "pn_io.tsn_domain_port_queue_rate_limiter.envelope", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_queue_rate_limiter_envelope), 0x000000FF00000000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_rate_limiter_rank, + { "TSNDomainQueueRateLimiter.Rank", "pn_io.tsn_domain_port_queue_rate_limiter.rank", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_queue_rate_limiter_rank), 0x0000FF0000000000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_rate_limiter_queue_id, + { "TSNDomainQueueRateLimiter.QueueID", "pn_io.tsn_domain_port_queue_rate_limiter.queue_id", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_queue_rate_limiter_queue_id), 0x00FF000000000000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_rate_limiter_reserved, + { "TSNDomainQueueRateLimiter.Reserved", "pn_io.tsn_domain_port_queue_rate_limiter.reserved", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_queue_rate_limiter_reserved), 0xFF00000000000000, + NULL, HFILL } + }, + { &hf_pn_io_number_of_tsn_domain_queue_config_entries, + { "TSNDomainQueueConfig.NumberOfEntries", "pn_io.tsn_domain_queue_config.number_of_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_config, + { "TSNDomainQueueConfig", "pn_io.tsn_domain_queue_config", + FT_UINT64, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_config_queue_id, + { "TSNDomainQueueConfig.QueueID", "pn_io.tsn_domain_queue_config.queue_id", + FT_UINT64, BASE_HEX, NULL, 0xF, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_config_tci_pcp, + { "TSNDomainQueueConfig.TciPcp", "pn_io.tsn_domain_queue_config.tci_pcp", + FT_UINT64, BASE_HEX, NULL, 0x70, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_config_shaper, + { "TSNDomainQueueConfig.Shaper", "pn_io.tsn_domain_queue_config.shaper", + FT_UINT64, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_queue_config_shaper), 0x3F80, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_config_preemption_mode, + { "TSNDomainQueueConfig.PreemptionMode", "pn_io.tsn_domain_queue_config.preemption_mode", + FT_UINT64, BASE_HEX, NULL, 0xC000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_config_unmask_time_offset, + { "TSNDomainQueueConfig.UnmaskTimeOffset", "pn_io.tsn_domain_queue_config.unmask_time_offset", + FT_UINT64, BASE_HEX, NULL, 0xFFFFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_queue_config_mask_time_offset, + { "TSNDomainQueueConfig.MaskTimeOffset", "pn_io.tsn_domain_queue_config.mask_time_offset", + FT_UINT64, BASE_HEX, NULL, 0xFFFFFF0000000000, + NULL, HFILL } + }, + { &hf_pn_io_network_deadline, + { "NetworkDeadline", "pn_io.network_deadline", + FT_UINT32, BASE_DEC | BASE_RANGE_STRING, RVALS(pn_io_network_domain), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_domain_number, + { "TimeDomainNumber", "pn_io.time_domain_number", + FT_UINT16, BASE_HEX , VALS(pn_io_time_domain_number_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_pll_window, + { "TimePLLWindow", "pn_io.time_pll_window", + FT_UINT32, BASE_DEC , VALS(pn_io_time_pll_window_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_message_interval_factor, + { "MessageIntervalFactor", "pn_io.message_interval_factor", + FT_UINT32, BASE_DEC , VALS(pn_io_message_interval_factor_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_message_timeout_factor, + { "MessageTimeoutFactor", "pn_io.message_timeout_factor", + FT_UINT16, BASE_DEC | BASE_RANGE_STRING, RVALS(pn_io_message_timeout_factor), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_sync_properties, + { "TimeSyncProperties", "pn_io.time_sync_properties", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_sync_properties_role, + { "TimeSyncProperties.Role", "pn_io.time_sync_properties.role", + FT_UINT16, BASE_HEX, VALS(pn_io_time_sync_properties_vals), 0x3, + NULL, HFILL } + }, + { &hf_pn_io_time_sync_properties_reserved, + { "TimeSyncProperties.Reserved", "pn_io.time_sync_properties.reserved", + FT_UINT16, BASE_HEX, NULL, 0xFFFC, + NULL, HFILL } + }, + { &hf_pn_io_time_domain_uuid, + { "TimeDomainUUID", "pn_io.time_domain_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_domain_name_length, + { "TimeDomainNameLength", "pn_io.time_domain_name_length", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_domain_name, + { "TimeDomainName", "pn_io.time_domain_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_nme_name_uuid, + { "TSNNMENameUUID", "pn_io.tsn_nme_name_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_nme_name_length, + { "TSNNMENameLength", "pn_io.tsn_nme_name_length", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_nme_name, + { "TSNNMEName", "pn_io.tsn_nme_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_uuid, + { "TSNDomainUUID", "pn_io.tsn_domain_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_name_length, + { "TSNDomainNameLength", "pn_io.tsn_domain_name_length", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_name, + { "TSNDomainName", "pn_io.tsn_domain_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_fdb_command, + { "FDBCommand", "pn_io.tsn_fdb_command", + FT_UINT8, BASE_HEX, VALS(pn_io_tsn_fdb_command), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_dst_add, + { "DestinationAddress", "pn_io.tsn_dst_add", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_tsn_domain_sync_tree_entries, + { "NumberOfEntries", "pn_io.tsn_domain_sync_tree_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_port_id, + { "TSNDomainPortID", "pn_io.tsn_domain_port_id", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tsn_domain_sync_port_role, + { "SyncPortRole", "pn_io.tsn_domain_sync_port_rule", + FT_UINT8,BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_tsn_domain_sync_port_role_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mau_type, + { "MAUType", "pn_io.mau_type", + FT_UINT16, BASE_HEX, VALS(pn_io_mau_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mau_type_mode, + { "MAUTypeMode", "pn_io.mau_type_mode", + FT_UINT16, BASE_HEX, VALS(pn_io_mau_type_mode), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_dcp_boundary_value, + { "DCPBoundary", "pn_io.dcp_boundary_value", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_dcp_boundary_value_bit0, + { "DCPBoundary", "pn_io.dcp_boundary_value_bit0", + FT_UINT32, BASE_HEX, VALS(pn_io_dcp_boundary_value_bit0), 0x1, + NULL, HFILL } + }, + { &hf_pn_io_dcp_boundary_value_bit1, + { "DCPBoundary", "pn_io.dcp_boundary_value_bit1", + FT_UINT32, BASE_HEX, VALS(pn_io_dcp_boundary_value_bit1), 0x2, + NULL, HFILL } + }, + { &hf_pn_io_dcp_boundary_value_otherbits, + { "DCPBoundary", "pn_io.dcp_boundary_value_otherbits", + FT_UINT32, BASE_HEX, NULL, 0xFFFFFFFC, + NULL, HFILL } + }, + { &hf_pn_io_peer_to_peer_boundary_value, + { "AdjustPeerToPeer-Boundary", "pn_io.peer_to_peer_boundary_value", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_peer_to_peer_boundary_value_bit0, + { "AdjustPeerToPeer-Boundary", "pn_io.peer_to_peer_boundary_value_bit0", + FT_UINT32, BASE_HEX, VALS(pn_io_peer_to_peer_boundary_value_bit0), 0x1, + NULL, HFILL } + }, + { &hf_pn_io_peer_to_peer_boundary_value_bit1, + { "AdjustPeerToPeer-Boundary", "pn_io.peer_to_peer_boundary_value_bit1", + FT_UINT32, BASE_HEX, VALS(pn_io_peer_to_peer_boundary_value_bit1), 0x2, + NULL, HFILL } + }, + { &hf_pn_io_peer_to_peer_boundary_value_bit2, + { "AdjustPeerToPeer-Boundary", "pn_io.peer_to_peer_boundary_value_bit2", + FT_UINT32, BASE_HEX, VALS(pn_io_peer_to_peer_boundary_value_bit2), 0x4, + NULL, HFILL } + }, + { &hf_pn_io_peer_to_peer_boundary_value_otherbits, + { "AdjustPeerToPeer-Boundary", "pn_io.peer_to_peer_boundary_value_otherbits", + FT_UINT32, BASE_HEX, NULL, 0xFFFFFFF8, + NULL, HFILL } + }, + { &hf_pn_io_port_state, + { "PortState", "pn_io.port_state", + FT_UINT16, BASE_HEX, VALS(pn_io_port_state), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_link_state_port, + { "LinkState.Port", "pn_io.link_state_port", + FT_UINT8, BASE_HEX, VALS(pn_io_link_state_port), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_link_state_link, + { "LinkState.Link", "pn_io.link_state_link", + FT_UINT8, BASE_HEX, VALS(pn_io_link_state_link), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_line_delay, + { "LineDelay", "pn_io.line_delay", + FT_UINT32, BASE_HEX, NULL, 0x0, + "LineDelay in nanoseconds", HFILL } + }, + { &hf_pn_io_line_delay_value, + { "LineDelayValue", "pn_io.line_delay_value", + FT_UINT32, BASE_DEC | BASE_RANGE_STRING, RVALS(pn_io_line_delay_value), 0x7FFFFFFF, + NULL, HFILL } + }, + { &hf_pn_io_cable_delay_value, + { "CableDelayValue", "pn_io.cable_delay_value", + FT_UINT32, BASE_DEC | BASE_RANGE_STRING, RVALS(pn_io_cable_delay_value), 0x7FFFFFFF, + NULL, HFILL } + }, + { &hf_pn_io_line_delay_format_indicator, + { "LineDelayFormatIndicator", "pn_io.line_delay_format_indicator", + FT_UINT32, BASE_HEX, NULL, 0x80000000, + "LineDelay FormatIndicator", HFILL } + }, + { &hf_pn_io_number_of_peers, + { "NumberOfPeers", "pn_io.number_of_peers", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_peer_port_id, + { "LengthPeerPortID", "pn_io.length_peer_port_id", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_peer_port_id, + { "PeerPortID", "pn_io.peer_port_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_peer_chassis_id, + { "LengthPeerChassisID", "pn_io.length_peer_chassis_id", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_peer_chassis_id, + { "PeerChassisID", "pn_io.peer_chassis_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_neighbor, + { "Neighbor", "pn_io.neighbor", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_peer_port_name, + { "LengthPeerPortName", "pn_io.length_peer_port_name", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_peer_port_name, + { "PeerPortName", "pn_io.peer_port_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_peer_station_name, + { "LengthPeerStationName", "pn_io.length_peer_station_name", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_peer_station_name, + { "PeerStationName", "pn_io.peer_station_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_own_chassis_id, + { "LengthOwnChassisID", "pn_io.length_own_chassis_id", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_own_chassis_id, + { "OwnChassisID", "pn_io.own_chassis_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rtclass3_port_status, + { "RTClass3_PortStatus", "pn_io.rtclass3_port_status", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_own_port_id, + { "LengthOwnPortID", "pn_io.length_own_port_id", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_own_port_id, + { "OwnPortID", "pn_io.own_port_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_peer_macadd, + { "PeerMACAddress", "pn_io.peer_macadd", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_macadd, + { "MACAddress", "pn_io.macadd", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_media_type, + { "MediaType", "pn_io.media_type", + FT_UINT32, BASE_HEX, VALS(pn_io_media_type), 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_ethertype, + { "Ethertype", "pn_io.ethertype", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rx_port, + { "RXPort", "pn_io.rx_port", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_details, + { "FrameDetails", "pn_io.frame_details", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_details_sync_frame, + { "SyncFrame", "pn_io.frame_details.sync_frame", + FT_UINT8, BASE_HEX, VALS(pn_io_frame_details_sync_master_vals), 0x03, + NULL, HFILL } + }, + { &hf_pn_io_frame_details_meaning_frame_send_offset, + { "Meaning", "pn_io.frame_details.meaning_frame_send_offset", + FT_UINT8, BASE_HEX, VALS(pn_io_frame_details_meaning_frame_send_offset_vals), 0x0C, + NULL, HFILL } + }, + { &hf_pn_io_frame_details_reserved, + { "Reserved", "pn_io.frame_details.reserved", + FT_UINT8, BASE_HEX, NULL, 0xF0, + NULL, HFILL } + }, + { &hf_pn_io_nr_of_tx_port_groups, + { "NumberOfTxPortGroups", "pn_io.nr_of_tx_port_groups", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties, + { "TxPortGroupProperties", "pn_io.tx_port_properties", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties_bit0, + { "TxPortLocal", "pn_io.tx_port_properties_bit_0", + FT_UINT8, BASE_HEX, VALS(pn_io_txgroup_state), 0x01, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties_bit1, + { "TxPort_1", "pn_io.tx_port_properties_bit_1", + FT_UINT8, BASE_HEX, VALS(pn_io_txgroup_state), 0x02, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties_bit2, + { "TxPort_2", "pn_io.tx_port_properties_bit_2", + FT_UINT8, BASE_HEX, VALS(pn_io_txgroup_state), 0x04, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties_bit3, + { "TxPort_3", "pn_io.tx_port_properties_bit_3", + FT_UINT8, BASE_HEX, VALS(pn_io_txgroup_state), 0x08, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties_bit4, + { "TxPort_4", "pn_io.tx_port_properties_bit_4", + FT_UINT8, BASE_HEX, VALS(pn_io_txgroup_state), 0x10, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties_bit5, + { "TxPort_5", "pn_io.tx_port_properties_bit_5", + FT_UINT8, BASE_HEX, VALS(pn_io_txgroup_state), 0x20, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties_bit6, + { "TxPort_6", "pn_io.tx_port_properties_bit_6", + FT_UINT8, BASE_HEX, VALS(pn_io_txgroup_state), 0x40, + NULL, HFILL } + }, + { &hf_pn_io_TxPortGroupProperties_bit7, + { "TxPort_7", "pn_io.tx_port_properties_bit_7", + FT_UINT8, BASE_HEX, VALS(pn_io_txgroup_state), 0x80, + NULL, HFILL } + }, + + { &hf_pn_io_start_of_red_frame_id, + { "StartOfRedFrameID", "pn_io.start_of_red_frame_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_end_of_red_frame_id, + { "EndOfRedFrameID", "pn_io.end_of_red_frame_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ir_begin_end_port, + { "Port", "pn_io.ir_begin_end_port", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_assignments, + { "NumberOfAssignments", "pn_io.number_of_assignments", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_phases, + { "NumberOfPhases", "pn_io.number_of_phases", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_red_orange_period_begin_tx, + { "RedOrangePeriodBegin [TX]", "pn_io.red_orange_period_begin_tx", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_orange_period_begin_tx, + { "OrangePeriodBegin [TX]", "pn_io.orange_period_begin_tx", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_green_period_begin_tx, + { "GreenPeriodBegin [TX]", "pn_io.green_period_begin_tx", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_red_orange_period_begin_rx, + { "RedOrangePeriodBegin [RX]", "pn_io.red_orange_period_begin_rx", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_orange_period_begin_rx, + { "OrangePeriodBegin [RX]", "pn_io.orange_period_begin_rx", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_green_period_begin_rx, + { "GreenPeriodBegin [RX]", "pn_io.green_period_begin_rx", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_ir_tx_phase_assignment, + { "TXPhaseAssignment", "pn_io.tx_phase_assignment_sub", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_tx_phase_assignment_begin_value, + { "AssignedValueForReservedBegin", "pn_io.tx_phase_assignment_begin_value", + FT_UINT16, BASE_DEC, NULL, 0x000F, + NULL, HFILL } + }, + { &hf_pn_io_tx_phase_assignment_orange_begin, + { "AssignedValueForOrangeBegin", "pn_io.tx_phase_assignment_orange_begin", + FT_UINT16, BASE_DEC, NULL, 0x00F0, + NULL, HFILL } + }, + { &hf_pn_io_tx_phase_assignment_end_reserved, + { "AssignedValueForReservedEnd", "pn_io.tx_phase_assignment_end_reserved", + FT_UINT16, BASE_DEC, NULL, 0x0F00, + NULL, HFILL } + }, + { &hf_pn_io_tx_phase_assignment_reserved, + { "Reserved should be 0", "pn_io.tx_phase_assignment_reserved", + FT_UINT16, BASE_DEC, NULL, 0xF000, + NULL, HFILL } + }, + { &hf_pn_ir_rx_phase_assignment, + { "RXPhaseAssignment", "pn_io.rx_phase_assignment_sub", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_slot, + { "Slot", "pn_io.slot", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_subslot, + { "Subslot", "pn_io.subslot", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_slots, + { "NumberOfSlots", "pn_io.number_of_slots", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_subslots, + { "NumberOfSubslots", "pn_io.number_of_subslots", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_maintenance_required_power_budget, + { "MaintenanceRequiredPowerBudget", "pn_io.maintenance_required_power_budget", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_maintenance_demanded_power_budget, + { "MaintenanceDemandedPowerBudget", "pn_io.maintenance_demanded_power_budget", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_power_budget, + { "ErrorPowerBudget", "pn_io.error_power_budget", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_fiber_optic_type, + { "FiberOpticType", "pn_io.fiber_optic_type", + FT_UINT32, BASE_HEX, VALS(pn_io_fiber_optic_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_fiber_optic_cable_type, + { "FiberOpticCableType", "pn_io.fiber_optic_cable_type", + FT_UINT32, BASE_HEX, VALS(pn_io_fiber_optic_cable_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_controller_appl_cycle_factor, + { "ControllerApplicationCycleFactor", "pn_io.controller_appl_cycle_factor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_data_cycle, + { "TimeDataCycle", "pn_io.time_data_cycle", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_io_input, + { "TimeIOInput", "pn_io.time_io_input", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_io_output, + { "TimeIOOutput", "pn_io.time_io_output", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_io_input_valid, + { "TimeIOInputValid", "pn_io.time_io_input_valid", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_time_io_output_valid, + { "TimeIOOutputValid", "pn_io.time_io_output_valid", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_maintenance_status, + { "MaintenanceStatus", "pn_io.maintenance_status", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_maintenance_status_required, + { "Required", "pn_io.maintenance_status_required", + FT_UINT32, BASE_HEX, NULL, 0x0001, + NULL, HFILL } + }, + { &hf_pn_io_maintenance_status_demanded, + { "Demanded", "pn_io.maintenance_status_demanded", + FT_UINT32, BASE_HEX, NULL, 0x0002, + NULL, HFILL } + }, + { &hf_pn_io_vendor_id_high, + { "VendorIDHigh", "pn_io.vendor_id_high", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_vendor_id_low, + { "VendorIDLow", "pn_io.vendor_id_low", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_vendor_block_type, + { "VendorBlockType", "pn_io.vendor_block_type", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_order_id, + { "OrderID", "pn_io.order_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_serial_number, + { "IMSerialNumber", "pn_io.im_serial_number", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_hardware_revision, + { "IMHardwareRevision", "pn_io.im_hardware_revision", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + /* XXX - better use a simple char here -> vals */ + { &hf_pn_io_im_revision_prefix, + { "IMRevisionPrefix", "pn_io.im_revision_prefix", + FT_CHAR, BASE_HEX, VALS(pn_io_im_revision_prefix_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_sw_revision_functional_enhancement, + { "IMSWRevisionFunctionalEnhancement", "pn_io.im_sw_revision_functional_enhancement", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_revision_bugfix, + { "IM_SWRevisionBugFix", "pn_io.im_revision_bugfix", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_sw_revision_internal_change, + { "IMSWRevisionInternalChange", "pn_io.im_sw_revision_internal_change", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_revision_counter, + { "IMRevisionCounter", "pn_io.im_revision_counter", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_profile_id, + { "IMProfileID", "pn_io.im_profile_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_profile_specific_type, + { "IMProfileSpecificType", "pn_io.im_profile_specific_type", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_version_major, + { "IMVersionMajor", "pn_io.im_version_major", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_version_minor, + { "IMVersionMinor", "pn_io.im_version_minor", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_supported, + { "IM_Supported", "pn_io.im_supported", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_numberofentries, + { "NumberOfEntries", "pn_io.im_numberofentries", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_annotation, + { "IM Annotation", "pn_io.im_annotation", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_order_id, + { "IM Order ID", "pn_io.im_order_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_ars, + { "NumberOfARs", "pn_io.number_of_ars", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_cycle_counter, + { "CycleCounter", "pn_io.cycle_counter", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_data_status, + { "DataStatus", "pn_io.ds", + FT_UINT8, BASE_HEX, 0, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_data_status_res67, + { "Reserved (should be zero)", "pn_io.ds_res67", + FT_UINT8, BASE_HEX, 0, 0xc0, + NULL, HFILL } + }, + { &hf_pn_io_data_status_ok, + { "StationProblemIndicator (1:Ok/0:Problem)", "pn_io.ds_ok", + FT_UINT8, BASE_HEX, 0, 0x20, + NULL, HFILL } + }, + { &hf_pn_io_data_status_operate, + { "ProviderState (1:Run/0:Stop)", "pn_io.ds_operate", + FT_UINT8, BASE_HEX, 0, 0x10, + NULL, HFILL } + }, + { &hf_pn_io_data_status_res3, + { "Reserved (should be zero)", "pn_io.ds_res3", + FT_UINT8, BASE_HEX, 0, 0x08, + NULL, HFILL } + }, + { &hf_pn_io_data_status_valid, + { "DataValid (1:Valid/0:Invalid)", "pn_io.ds_valid", + FT_UINT8, BASE_HEX, 0, 0x04, + NULL, HFILL } + }, + { &hf_pn_io_data_status_res1, + { "primary AR of a given AR-set is present (0:One/ 1:None)", "pn_io.ds_res1", + FT_UINT8, BASE_HEX, 0, 0x02, + NULL, HFILL } + }, + { &hf_pn_io_data_status_primary, + { "State (1:Primary/0:Backup)", "pn_io.ds_primary", + FT_UINT8, BASE_HEX, 0, 0x01, + NULL, HFILL } + }, + { &hf_pn_io_transfer_status, + { "TransferStatus", "pn_io.transfer_status", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_actual_local_time_stamp, + { "ActualLocalTimeStamp", "pn_io.actual_local_time_stamp", + FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_local_time_stamp, + { "LocalTimeStamp", "pn_io.local_time_stamp", + FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_log_entries, + { "NumberOfLogEntries", "pn_io.number_of_log_entries", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_entry_detail, + { "EntryDetail", "pn_io.entry_detail", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ip_address, + { "IPAddress", "pn_io.ip_address", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_subnetmask, + { "Subnetmask", "pn_io.subnetmask", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_standard_gateway, + { "StandardGateway", "pn_io.standard_gateway", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_mrp_domain_uuid, + { "MRP_DomainUUID", "pn_io.mrp_domain_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_role, + { "MRP_Role", "pn_io.mrp_role", + FT_UINT16, BASE_HEX, VALS(pn_io_mrp_role_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_length_domain_name, + { "MRP_LengthDomainName", "pn_io.mrp_length_domain_name", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_domain_name, + { "MRP_DomainName", "pn_io.mrp_domain_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_instances, + { "NumberOfMrpInstances", "pn_io.mrp_Number_MrpInstances", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_instance, + { "Mrp_Instance", "pn_io.mrp_MrpInstance", + FT_UINT8, BASE_DEC, VALS(pn_io_mrp_instance_no), 0x0, + NULL, HFILL } + }, + + { &hf_pn_io_mrp_prio, + { "MRP_Prio", "pn_io.mrp_prio", + FT_UINT16, BASE_HEX, VALS(pn_io_mrp_prio_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_topchgt, + { "MRP_TOPchgT", "pn_io.mrp_topchgt", + FT_UINT16, BASE_DEC, NULL, 0x0, + "time base 10ms", HFILL } + }, + { &hf_pn_io_mrp_topnrmax, + { "MRP_TOPNRmax", "pn_io.mrp_topnrmax", + FT_UINT16, BASE_DEC, NULL, 0x0, + "number of iterations", HFILL } + }, + { &hf_pn_io_mrp_tstshortt, + { "MRP_TSTshortT", "pn_io.mrp_tstshortt", + FT_UINT16, BASE_DEC, NULL, 0x0, + "time base 1 ms", HFILL } + }, + { &hf_pn_io_mrp_tstdefaultt, + { "MRP_TSTdefaultT", "pn_io.mrp_tstdefaultt", + FT_UINT16, BASE_DEC, NULL, 0x0, + "time base 1ms", HFILL } + }, + { &hf_pn_io_mrp_tstnrmax, + { "MRP_TSTNRmax", "pn_io.mrp_tstnrmax", + FT_UINT16, BASE_DEC, NULL, 0x0, + "number of outstanding test indications causes ring failure", HFILL } + }, + { &hf_pn_io_mrp_check, + { "MRP_Check", "pn_io.mrp_check", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_check_mrm, + { "MRP_Check.MediaRedundancyManager", "pn_io.mrp_check.mrm", + FT_UINT32, BASE_HEX, VALS(pn_io_mrp_mrm_on), 0x01, + NULL, HFILL } + }, + { &hf_pn_io_mrp_check_mrpdomain, + { "MRP_Check.MRP_DomainUUID", "pn_io.mrp_check.domainUUID", + FT_UINT32, BASE_HEX, VALS(pn_io_mrp_checkUUID), 0x02, + NULL, HFILL } + }, + { &hf_pn_io_mrp_check_reserved_1, + { "MRP_Check.reserved_1", "pn_io.mrp_check_reserved_1", + FT_UINT32, BASE_HEX, NULL, 0xFFFFFC, + NULL, HFILL } + }, + { &hf_pn_io_mrp_check_reserved_2, + { "MRP_Check.reserved_2", "pn_io.mrp_check_reserved_2", + FT_UINT32, BASE_HEX, NULL, 0xFF000000, + NULL, HFILL } + }, + { &hf_pn_io_mrp_rtmode, + { "MRP_RTMode", "pn_io.mrp_rtmode", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_rtmode_rtclass12, + { "RTClass1_2", "pn_io.mrp_rtmode.class1_2", + FT_UINT32, BASE_HEX, VALS(pn_io_mrp_rtmode_rtclass12_vals), 0x00000001, + NULL, HFILL } + }, + { &hf_pn_io_mrp_rtmode_rtclass3, + { "RTClass1_3", "pn_io.mrp_rtmode.class3", + FT_UINT32, BASE_HEX, VALS(pn_io_mrp_rtmode_rtclass3_vals), 0x00000002, + NULL, HFILL } + }, + { &hf_pn_io_mrp_rtmode_reserved1, + { "Reserved_1", "pn_io.mrp_rtmode.reserved_1", + FT_UINT32, BASE_HEX, NULL, 0x00fffffc, + NULL, HFILL } + }, + { &hf_pn_io_mrp_rtmode_reserved2, + { "Reserved_2", "pn_io.mrp_rtmode.reserved_2", + FT_UINT32, BASE_HEX, NULL, 0xff000000, + NULL, HFILL } + }, + { &hf_pn_io_mrp_lnkdownt, + { "MRP_LNKdownT", "pn_io.mrp_lnkdownt", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Link down Interval in ms", HFILL } + }, + { &hf_pn_io_mrp_lnkupt, + { "MRP_LNKupT", "pn_io.mrp_lnkupt", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Link up Interval in ms", HFILL } + }, + { &hf_pn_io_mrp_lnknrmax, + { "MRP_LNKNRmax", "pn_io.mrp_lnknrmax", + FT_UINT16, BASE_HEX, NULL, 0x0, + "number of iterations", HFILL } + }, + { &hf_pn_io_mrp_version, + { "MRP_Version", "pn_io.mrp_version", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_substitute_active_flag, + { "SubstituteActiveFlag", "pn_io.substitute_active_flag", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_length_data, + { "LengthData", "pn_io.length_data", + FT_UINT16, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_ring_state, + { "MRP_RingState", "pn_io.mrp_ring_state", + FT_UINT16, BASE_HEX, VALS(pn_io_mrp_ring_state_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mrp_rt_state, + { "MRP_RTState", "pn_io.mrp_rt_state", + FT_UINT16, BASE_HEX, VALS(pn_io_mrp_rt_state_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_tag_function, + { "IM_Tag_Function", "pn_io.im_tag_function", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_tag_location, + { "IM_Tag_Location", "pn_io.im_tag_location", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_date, + { "IM_Date", "pn_io.im_date", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_descriptor, + { "IM_Descriptor", "pn_io.im_descriptor", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_fs_hello_mode, + { "FSHelloMode", "pn_io.fs_hello_mode", + FT_UINT32, BASE_HEX, VALS(pn_io_fs_hello_mode_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_fs_hello_interval, + { "FSHelloInterval", "pn_io.fs_hello_interval", + FT_UINT32, BASE_DEC, NULL, 0x0, + "ms before conveying a second DCP_Hello.req", HFILL } + }, + { &hf_pn_io_fs_hello_retry, + { "FSHelloRetry", "pn_io.fs_hello_retry", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_fs_hello_delay, + { "FSHelloDelay", "pn_io.fs_hello_delay", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_fs_parameter_mode, + { "FSParameterMode", "pn_io.fs_parameter_mode", + FT_UINT32, BASE_HEX, VALS(pn_io_fs_parameter_mode_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_fs_parameter_uuid, + { "FSParameterUUID", "pn_io.fs_parameter_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_check_sync_mode, + { "CheckSyncMode", "pn_io.check_sync_mode", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_check_sync_mode_reserved, + { "Reserved", "pn_io.check_sync_mode.reserved", + FT_UINT16, BASE_HEX, NULL, 0xFFFC, + NULL, HFILL } + }, + { &hf_pn_io_check_sync_mode_sync_master, + { "SyncMaster", "pn_io.check_sync_mode.sync_master", + FT_UINT16, BASE_HEX, NULL, 0x0002, + NULL, HFILL } + }, + { &hf_pn_io_check_sync_mode_cable_delay, + { "CableDelay", "pn_io.check_sync_mode.cable_delay", + FT_UINT16, BASE_HEX, NULL, 0x0001, + NULL, HFILL } + }, + /* PROFIsafe F-Parameter */ + { &hf_pn_io_ps_f_prm_flag1, + { "F_Prm_Flag1", "pn_io.ps.f_prm_flag1", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag1_chck_seq, + { "F_Check_SeqNr", "pn_io.ps.f_prm_flag1.f_check_seqnr", + FT_UINT8, BASE_HEX, VALS(pn_io_f_check_seqnr), 0x01, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag1_chck_ipar, + { "F_Check_iPar", "pn_io.ps.f_prm_flag1.f_check_ipar", + FT_UINT8, BASE_HEX, VALS(pn_io_f_check_ipar), 0x02, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag1_sil, + { "F_SIL", "pn_io.ps.f_prm_flag1.f_sil", + FT_UINT8, BASE_HEX, VALS(pn_io_f_sil), 0xc, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag1_crc_len, + { "F_CRC_Length", "pn_io.ps.f_prm_flag1.f_crc_len", + FT_UINT8, BASE_HEX, VALS(pn_io_f_crc_len), 0x30, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag1_crc_seed, + { "F_CRC_Seed", "pn_io.ps.f_prm_flag1.f_crc_seed", + FT_UINT8, BASE_HEX, VALS(pn_io_f_crc_seed), 0x40, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag1_reserved, + { "Reserved", "pn_io.ps.f_prm_flag1.reserved", + FT_UINT8, BASE_HEX, NULL, 0x80, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag2, + { "F_Prm_Flag2", "pn_io.ps.f_prm_flag2", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag2_reserved, + { "Reserved", "pn_io.ps.f_prm_flag2.reserved", + FT_UINT8, BASE_HEX, NULL, 0x07, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag2_f_block_id, + { "F_Block_ID", "pn_io.ps.f_prm_flag2.f_block_id", + FT_UINT8, BASE_HEX, VALS(pn_io_f_block_id), 0x38, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_prm_flag2_f_par_version, + { "F_Par_Version", "pn_io.ps.f_prm_flag2.f_par_version", + FT_UINT8, BASE_HEX, VALS(pn_io_f_par_version), 0xC0, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_wd_time, + { "F_WD_Time", "pn_io.ps.f_wd_time", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_ipar_crc, + { "F_iPar_CRC", "pn_io.ps.f_ipar_crc", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_par_crc, + { "F_Par_CRC", "pn_io.ps.f_par_crc", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_dest_adr, + { "F_Dest_Add", "pn_io.ps.f_dest_add", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_src_adr, + { "F_Source_Add", "pn_io.ps.f_source_add", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + /* profidrive parameter access */ + { &hf_pn_io_profidrive_request_reference, + { "RequestReference", "pn_io.profidrive.parameter.request_reference", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_request_id, + { "RequestID", "pn_io.profidrive.parameter.request_id", + FT_UINT8, BASE_HEX, VALS(pn_io_profidrive_request_id_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_do_id, + { "DO", "pn_io.profidrive.parameter.do", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_no_of_parameters, + { "NoOfParameters", "pn_io.profidrive.parameter.no_of_parameters", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_attribute, + { "Attribute", "pn_io.profidrive.parameter.attribute", + FT_UINT8, BASE_HEX, VALS(pn_io_profidrive_attribute_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_no_of_elems, + { "NoOfElements", "pn_io.profidrive.parameter.no_of_elems", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_number, + { "Parameter", "pn_io.profidrive.parameter.number", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_subindex, + { "Index", "pn_io.profidrive.parameter.index", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_response_id, + { "ResponseID", "pn_io.profidrive.parameter.response_id", + FT_UINT8, BASE_HEX, VALS(pn_io_profidrive_response_id_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_format, + { "Format", "pn_io.profidrive.parameter.format", + FT_UINT8, BASE_HEX, VALS(pn_io_profidrive_format_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_value_error, + { "Error Number", "pn_io.profidrive.parameter.error_num", + FT_UINT16, BASE_HEX, VALS(pn_io_profidrive_parameter_resp_errors), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_value_error_sub, + { "Error Subindex", "pn_io.profidrive.parameter.error_subindex", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_no_of_values, + { "NoOfValues", "pn_io.profidrive.parameter.no_of_values", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_value_byte, + { "Value", "pn_io.profidrive.parameter.value_b", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_value_word, + { "Value", "pn_io.profidrive.parameter.value_w", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_value_dword, + { "Value", "pn_io.profidrive.parameter.value_dw", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_value_float, + { "Value", "pn_io.profidrive.parameter.value_float", + FT_FLOAT, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_profidrive_param_value_string, + { "Value", "pn_io.profidrive.parameter.value_str", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_alarm_info_reserved_8_15, + { "RSAlarmInfo.Reserved2", "pn_io.rs_alarm_info_reserved_8_15", + FT_UINT16, BASE_HEX, NULL, 0xFF00, + NULL, HFILL } + }, + { &hf_pn_io_rs_alarm_info_reserved_0_7, + { "RSAlarmInfo.Reserved1", "pn_io.rs_alarm_info_reserved_0_7", + FT_UINT16, BASE_HEX, NULL, 0x00FF, + NULL, HFILL } + }, + { &hf_pn_io_rs_alarm_info, + { "RS Alarm Info", "pn_io.rs_alarm_info", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_event_info, + { "RS Event Info", "pn_io.rs_event_info", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_event_block, + { "RS Event Block", "pn_io.rs_event_block", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_adjust_block, + { "RS Adjust Block", "pn_io.rs_adjust_block", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_event_data_extension, + { "RS Event Data Extension", "pn_io.rs_event_data_extension", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_rs_event_info, + { "RSEventInfo.NumberOfEntries", "pn_io.number_of_rs_event_info", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_block_type, + { "RS Block Type", "pn_io.rs_block_type", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_rs_block_type), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_block_length, + { "RS Block Length", "pn_io.rs_block_length", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_specifier, + { "RS_Specifier", "pn_io.rs_specifier", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_specifier_sequence, + { "RS_Specifier.SequenceNumber", "pn_io.rs_specifier.sequence", + FT_UINT16, BASE_HEX, NULL, 0x07FF, + NULL, HFILL } + }, + { &hf_pn_io_rs_specifier_reserved, + { "RS_Specifier.Reserved", "pn_io.rs_specifier_reserved", + FT_UINT16, BASE_HEX, NULL, 0x3800, + NULL, HFILL } + }, + { &hf_pn_io_rs_specifier_specifier, + { "RS_Specifier.Specifier", "pn_io.rs_specifier.specifier", + FT_UINT16, BASE_HEX, VALS(pn_io_rs_specifier_specifier), 0xC000, + NULL, HFILL } + }, + { &hf_pn_io_rs_time_stamp, + { "RS_TimeStamp", "pn_io.rs_time_stamp", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_time_stamp_status, + { "RS_TimeStamp.Status", "pn_io.rs_time_stamp.status", + FT_UINT16, BASE_HEX, VALS(pn_io_rs_time_stamp_status), 0x0003, + NULL, HFILL } + }, + { &hf_pn_io_rs_time_stamp_value, + { "RS_TimeStamp.Value", "pn_io.rs_time_stamp.value", + FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_minus_error, + { "RS_MinusError", "pn_io.rs_minus_error", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_plus_error, + { "RS_PlusError", "pn_io.rs_plus_error", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_extension_block_type, + { "RS_ExtensionBlockType", "pn_io.rs_extension_block_type", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_extension_block_length, + { "RS_ExtensionBlockLength", "pn_io.rs_extension_block_length", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_reason_code, + { "RS_ReasonCode", "pn_io.rs_reason_code", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_reason_code_reason, + { "RS_ReasonCode.Reason", "pn_io.rs_reason_code.reason", + FT_UINT32, BASE_HEX, VALS(pn_io_rs_reason_code_reason), 0x0000FFFF, + NULL, HFILL } + }, + { &hf_pn_io_rs_reason_code_detail, + { "RS_ReasonCode.Detail", "pn_io.rs_reason_code.detail", + FT_UINT32, BASE_HEX, VALS(pn_io_rs_reason_code_detail), 0xFFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_rs_domain_identification, + { "RS_DomainIdentification", "pn_io.rs_domain_identification", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_master_identification, + { "RS_MasterIdentification", "pn_io.rs_master_identification", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_soe_digital_input_current_value, + { "SoE_DigitalInputCurrentValue", "pn_io.soe_digital_input_current_value", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_soe_digital_input_current_value_value, + { "SoE_DigitalInputCurrentValue.Value", "pn_io.soe_digital_input_current_value.value", + FT_UINT16, BASE_HEX, VALS(pn_io_soe_digital_input_current_value_value), 0x0001, + NULL, HFILL } + }, + { &hf_pn_io_soe_digital_input_current_value_reserved, + { "SoE_DigitalInputCurrentValue.Reserved", "pn_io.soe_digital_input_current_value.reserved", + FT_UINT16, BASE_HEX, NULL, 0xFFFE, + NULL, HFILL } + }, + { &hf_pn_io_am_device_identification, + { "AM_DeviceIdentification", "pn_io.am_device_identification", + FT_UINT64, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_device_identification_device_sub_id, + { "AM_DeviceIdentification.DeviceSubID", "pn_io.am_device_identification.device_sub_id", + FT_UINT64, BASE_HEX, NULL, 0x000000000000FFFF, + NULL, HFILL } + }, + { &hf_pn_io_am_device_identification_device_id, + { "AM_DeviceIdentification.DeviceID", "pn_io.am_device_identification.device_id", + FT_UINT64, BASE_HEX, NULL, 0x00000000FFFF0000, + NULL, HFILL } + }, + { &hf_pn_io_am_device_identification_vendor_id, + { "AM_DeviceIdentification.VendorID", "pn_io.am_device_identification.vendor_id", + FT_UINT64, BASE_HEX, NULL, 0x0000FFFF00000000, + NULL, HFILL } + }, + { &hf_pn_io_am_device_identification_organization, + { "AM_DeviceIdentification.Organization", "pn_io.am_device_identification.organization", + FT_UINT64, BASE_HEX, NULL, 0xFFFF000000000000, + NULL, HFILL } + }, + { &hf_pn_io_rs_adjust_info, + { "RS Adjust Info", "pn_io.rs_adjust_info", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_soe_max_scan_delay, + { "SoE_MaxScanDelay", "pn_io.soe_max_scan_delay", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_soe_adjust_specifier, + { "SoE_AdjustSpecifier", "pn_io.soe_adjust_specifier", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_soe_adjust_specifier_reserved, + { "SoE_AdjustSpecifier.Reserved", "pn_io.soe_adjust_specifier.reserved", + FT_UINT8, BASE_HEX, NULL, 0x3F, + NULL, HFILL } + }, + { &hf_pn_io_soe_adjust_specifier_incident, + { "SoE_AdjustSpecifier.Incident", "pn_io.soe_adjust_specifier.incident", + FT_UINT8, BASE_HEX, VALS(pn_io_soe_adjust_specifier_incident), 0xC0, + NULL, HFILL } + }, + { &hf_pn_io_rs_properties, + { "RSProperties", "pn_io.rs_properties", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_rs_properties_alarm_transport, + { "RSProperties", "pn_io.rs_properties", + FT_UINT32, BASE_HEX, VALS(pn_io_rs_properties_alarm_transport), 0x00000001, + NULL, HFILL } + }, + { &hf_pn_io_rs_properties_reserved1, + { "RSProperties.Reserved1", "pn_io.rs_properties.reserved1", + FT_UINT32, BASE_HEX, NULL, 0x00FFFFFE, + NULL, HFILL } + }, + { &hf_pn_io_rs_properties_reserved2, + { "RSProperties.Reserved2", "pn_io.rs_properties.reserved2", + FT_UINT32, BASE_HEX, NULL, 0xFF000000, + NULL, HFILL } + }, + { &hf_pn_io_asset_management_info, + { "Asset Management Info", "pn_io.asset_management_info", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_number_of_asset_management_info, + { "AssetManagementInfo.NumberOfEntries", "pn_io.number_of_asset_management_info", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_im_uniqueidentifier, + { "IM_UniqueIdentifier", "pn_io.IM_UniqueIdentifier", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_structure, + { "AM_Location.Structure", "pn_io.am_location.structure", + FT_UINT8, BASE_HEX, VALS(pn_io_am_location_structure_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location, + { "AM_Location", "pn_io.am_location", + FT_BYTES, BASE_NONE, NULL, 0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_0, + { "AM_Location Level 0", "pn_io.am_location.level_0", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_1, + { "AM_Location Level 1", "pn_io.am_location.level_1", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_2, + { "AM_Location Level 2", "pn_io.am_location.level_2", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_3, + { "AM_Location Level 3", "pn_io.am_location.level_3", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_4, + { "AM_Location Level 4", "pn_io.am_location.level_4", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_5, + { "AM_Location Level 5", "pn_io.am_location.level_5", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_6, + { "AM_Location Level 6", "pn_io.am_location.level_6", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_7, + { "AM_Location Level 7", "pn_io.am_location.level_7", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_8, + { "AM_Location Level 8", "pn_io.am_location.level_8", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_9, + { "AM_Location Level 9", "pn_io.am_location.level_9", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_10, + { "AM_Location Level 10", "pn_io.am_location.level_10", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_level_11, + { "AM_Location Level 11", "pn_io.am_location.level_11", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_am_location_level_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_reserved1, + { "AM_Location.Reserved1", "pn_io.am_location.reserved1", + FT_UINT8, BASE_HEX, VALS(pn_io_am_location_reserved_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_reserved2, + { "AM_Location.Reserved2", "pn_io.am_location.reserved2", + FT_UINT16, BASE_HEX, VALS(pn_io_am_location_reserved_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_reserved3, + { "AM_Location.Reserved3", "pn_io.am_location.reserved3", + FT_UINT16, BASE_HEX, VALS(pn_io_am_location_reserved_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_reserved4, + { "AM_Location.Reserved4", "pn_io.am_location.reserved4", + FT_UINT16, BASE_HEX, VALS(pn_io_am_location_reserved_vals), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_beginslotnum, + { "AM_Location.BeginSlotNumber", "pn_io.slot_nr", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_beginsubslotnum, + { "AM_Location.BeginSubSlotNumber", "pn_io.subslot_nr", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_endslotnum, + { "AM_Location.EndSlotNumber", "pn_io.slot_nr", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_location_endsubslotnum, + { "AM_Location.EndSubSlotNumber", "pn_io.subslot_nr", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_software_revision, + { "AM Software Revision", "pn_io.am_software_revision", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_hardware_revision, + { "AM Hardware Revision", "pn_io.am_hardware_revision", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_type_identification, + { "AM Type Identification", "pn_io.am_type_identification", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_am_reserved, + { "AM Reserved", "pn_io.am_reserved", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_mau_type_extension, + { "MAUTypeExtension", "pn_io.mau_type_extension", + FT_UINT16, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_mau_type_extension), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_pe_operational_mode, + { "PE_OperationalMode", "pn_io.pe_operationalmode", + FT_UINT8, BASE_HEX | BASE_RANGE_STRING, RVALS(pn_io_pe_operational_mode), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_snmp_control, + { "SNMPControl", "pn_io.snmp_control", + FT_UINT16, BASE_HEX, VALS(pn_io_snmp_control), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_snmp_community_name_length, + { "CommunityNameLength", "pn_io.snmp_community_name_length", + FT_UINT8, BASE_DEC_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_snmp_community_name, + { "CommunityName", "pn_io.snmp_community_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_snmp_read_community_name, + { "SNMP read only community name", "pn_io.snmp_read_community_name", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_snmp_write_community_name, + { "SNMP read write community name", "pn_io.snmp_write_community_name", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + }; + + static gint *ett[] = { + &ett_pn_io, + &ett_pn_io_block, + &ett_pn_io_block_header, + &ett_pn_io_rtc, + &ett_pn_io_rta, + &ett_pn_io_pdu_type, + &ett_pn_io_add_flags, + &ett_pn_io_control_command, + &ett_pn_io_ioxs, + &ett_pn_io_api, + &ett_pn_io_data_description, + &ett_pn_io_module, + &ett_pn_io_submodule, + &ett_pn_io_io_data_object, + &ett_pn_io_io_cs, + &ett_pn_io_ar_properties, + &ett_pn_io_iocr_properties, + &ett_pn_io_submodule_properties, + &ett_pn_io_alarmcr_properties, + &ett_pn_io_submodule_state, + &ett_pn_io_channel_properties, + &ett_pn_io_slot, + &ett_pn_io_subslot, + &ett_pn_io_maintenance_status, + &ett_pn_io_data_status, + &ett_pn_io_iocr, + &ett_pn_io_mrp_rtmode, + &ett_pn_io_control_block_properties, + &ett_pn_io_check_sync_mode, + &ett_pn_io_ir_frame_data, + &ett_pn_FrameDataProperties, + &ett_pn_io_ar_info, + &ett_pn_io_ar_data, + &ett_pn_io_ir_begin_end_port, + &ett_pn_io_ir_tx_phase, + &ett_pn_io_ir_rx_phase, + &ett_pn_io_subframe_data, + &ett_pn_io_SFIOCRProperties, + &ett_pn_io_frame_defails, + &ett_pn_io_profisafe_f_parameter, + &ett_pn_io_profisafe_f_parameter_prm_flag1, + &ett_pn_io_profisafe_f_parameter_prm_flag2, + &ett_pn_io_profidrive_parameter_request, + &ett_pn_io_profidrive_parameter_response, + &ett_pn_io_profidrive_parameter_address, + &ett_pn_io_profidrive_parameter_value, + &ett_pn_io_GroupProperties, + &ett_pn_io_rs_alarm_info, + &ett_pn_io_rs_event_info, + &ett_pn_io_rs_event_block, + &ett_pn_io_rs_adjust_block, + &ett_pn_io_rs_event_data_extension, + &ett_pn_io_rs_specifier, + &ett_pn_io_rs_time_stamp, + &ett_pn_io_am_device_identification, + &ett_pn_io_rs_reason_code, + &ett_pn_io_soe_digital_input_current_value, + &ett_pn_io_rs_adjust_info, + &ett_pn_io_soe_adjust_specifier, + &ett_pn_io_asset_management_info, + &ett_pn_io_asset_management_block, + &ett_pn_io_am_location, + &ett_pn_io_sr_properties, + &ett_pn_io_line_delay, + &ett_pn_io_counter_status, + &ett_pn_io_dcp_boundary, + &ett_pn_io_peer_to_peer_boundary, + &ett_pn_io_mau_type_extension, + &ett_pn_io_pe_operational_mode, + &ett_pn_io_neighbor, + &ett_pn_io_tsn_domain_vid_config, + &ett_pn_io_tsn_domain_port_config, + &ett_pn_io_tsn_domain_queue_config, + &ett_pn_io_tsn_domain_port_ingress_rate_limiter, + &ett_pn_io_tsn_domain_queue_rate_limiter, + &ett_pn_io_time_sync_properties, + &ett_pn_io_tsn_domain_port_id, + &ett_pn_io_snmp_command_name + }; + + static ei_register_info ei[] = { + { &ei_pn_io_block_version, { "pn_io.block_version.not_implemented", PI_UNDECODED, PI_WARN, "Block version not implemented yet!", EXPFILL }}, + { &ei_pn_io_ar_info_not_found, { "pn_io.ar_info_not_found", PI_UNDECODED, PI_NOTE, "IODWriteReq: AR information not found!", EXPFILL }}, + { &ei_pn_io_block_length, { "pn_io.block_length.invalid", PI_UNDECODED, PI_WARN, "Block length invalid!", EXPFILL }}, + { &ei_pn_io_unsupported, { "pn_io.profidrive.parameter.format.invalid", PI_UNDECODED, PI_WARN, "Unknown Formatvalue", EXPFILL }}, + { &ei_pn_io_mrp_instances, { "pn_io.mrp_Number_MrpInstances.invalid", PI_UNDECODED, PI_WARN, "Number of MrpInstances invalid", EXPFILL }}, + { &ei_pn_io_frame_id, { "pn_io.frame_id.changed", PI_UNDECODED, PI_WARN, "FrameID changed", EXPFILL }}, + { &ei_pn_io_iocr_type, { "pn_io.iocr_type.unknown", PI_UNDECODED, PI_WARN, "IOCRType undecoded!", EXPFILL }}, + { &ei_pn_io_localalarmref, { "pn_io.localalarmref.changed", PI_UNDECODED, PI_WARN, "AlarmCRBlockReq: local alarm ref changed", EXPFILL }}, + { &ei_pn_io_nr_of_tx_port_groups, { "pn_io.nr_of_tx_port_groups.not_allowed", PI_PROTOCOL, PI_WARN, "Not allowed value of NumberOfTxPortGroups", EXPFILL }}, + { &ei_pn_io_max_recursion_depth_reached, { "pn_io.max_recursion_depth_reached", PI_PROTOCOL, PI_WARN, "Maximum allowed recursion depth reached - stopping dissection", EXPFILL }} + }; + + module_t *pnio_module; + expert_module_t* expert_pn_io; + + proto_pn_io = proto_register_protocol ("PROFINET IO", "PNIO", "pn_io"); + + /* Register by name */ + register_dissector("pnio", dissect_PNIO_heur, proto_pn_io); + + /* Created to remove Decode As confusion */ + proto_pn_io_device = proto_register_protocol_in_name_only("PROFINET IO (Device)", "PNIO (Device Interface)", "pn_io_device", proto_pn_io, FT_PROTOCOL); + proto_pn_io_controller = proto_register_protocol_in_name_only("PROFINET IO (Controller)", "PNIO (Controller Interface)", "pn_io_controller", proto_pn_io, FT_PROTOCOL); + proto_pn_io_supervisor = proto_register_protocol_in_name_only("PROFINET IO (Supervisor)", "PNIO (Supervisor Interface)", "pn_io_supervisor", proto_pn_io, FT_PROTOCOL); + proto_pn_io_parameterserver = proto_register_protocol_in_name_only("PROFINET IO (Parameter Server)", "PNIO (Parameter Server Interface)", "pn_io_parameterserver", proto_pn_io, FT_PROTOCOL); + proto_pn_io_implicitar = proto_register_protocol_in_name_only("PROFINET IO (Implicit Ar)", "PNIO (Implicit Ar)", "pn_io_implicitar", proto_pn_io, FT_PROTOCOL); + proto_pn_io_apdu_status = proto_register_protocol_in_name_only("PROFINET IO (Apdu Status)", "PNIO (Apdu Status)", "pn_io_apdu_status", proto_pn_io, FT_PROTOCOL); + proto_pn_io_time_aware_status = proto_register_protocol_in_name_only("PROFINET IO (Time Aware Status)", "PNIO (Time Aware Status)", "pn_io_time_aware_status", proto_pn_io, FT_PROTOCOL); + + proto_register_field_array (proto_pn_io, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); + expert_pn_io = expert_register_protocol(proto_pn_io); + expert_register_field_array(expert_pn_io, ei, array_length(ei)); + + /* Register preferences */ + pnio_module = prefs_register_protocol(proto_pn_io, NULL); + prefs_register_bool_preference(pnio_module, "pnio_ps_selection", + "Enable detailed PROFIsafe dissection", + "Whether the PNIO dissector is allowed to use detailed PROFIsafe dissection of cyclic data frames", + &pnio_ps_selection); + prefs_register_directory_preference(pnio_module, "pnio_ps_networkpath", + "Folder containing GSD files", /* Title */ + "Place GSD files in this folder.", /* Descreption */ + &pnio_ps_networkpath); /* Variable in which to save the GSD file folder path */ + + /* subdissector code */ + register_dissector("pn_io", dissect_PNIO_heur, proto_pn_io); + heur_pn_subdissector_list = register_heur_dissector_list("pn_io", proto_pn_io); + + /* Initialise RTC1 dissection */ + init_pn_io_rtc1(proto_pn_io); + + /* Initialise RSI dissection */ + init_pn_rsi(proto_pn_io); + + /* Init functions of PNIO protocol */ + register_init_routine(pnio_setup); + + /* Cleanup functions of PNIO protocol */ + register_cleanup_routine(pnio_cleanup); + + register_conversation_filter("pn_io", "PN-IO AR", pn_io_ar_conv_valid, pn_io_ar_conv_filter, NULL); + register_conversation_filter("pn_io", "PN-IO AR (with data)", pn_io_ar_conv_valid, pn_io_ar_conv_data_filter, NULL); +} + + +void +proto_reg_handoff_pn_io (void) +{ + /* Register the protocols as dcerpc */ + dcerpc_init_uuid (proto_pn_io_device, ett_pn_io, &uuid_pn_io_device, ver_pn_io_device, pn_io_dissectors, hf_pn_io_opnum); + dcerpc_init_uuid (proto_pn_io_controller, ett_pn_io, &uuid_pn_io_controller, ver_pn_io_controller, pn_io_dissectors, hf_pn_io_opnum); + dcerpc_init_uuid (proto_pn_io_supervisor, ett_pn_io, &uuid_pn_io_supervisor, ver_pn_io_supervisor, pn_io_dissectors, hf_pn_io_opnum); + dcerpc_init_uuid (proto_pn_io_parameterserver, ett_pn_io, &uuid_pn_io_parameterserver, ver_pn_io_parameterserver, pn_io_dissectors, hf_pn_io_opnum); + dcerpc_init_uuid (proto_pn_io_implicitar, ett_pn_io, &uuid_pn_io_implicitar, ver_pn_io_implicitar, pn_io_dissectors, hf_pn_io_opnum); + + heur_dissector_add("pn_rt", dissect_PNIO_heur, "PROFINET IO", "pn_io_pn_rt", proto_pn_io, HEURISTIC_ENABLE); +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-dcom-cba-acco.c b/plugins/epan/profinet/packet-dcom-cba-acco.c new file mode 100644 index 00000000..6b3788a3 --- /dev/null +++ b/plugins/epan/profinet/packet-dcom-cba-acco.c @@ -0,0 +1,5158 @@ +/* packet-dcom-cba-acco.c + * Routines for DCOM CBA + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "packet-dcom-cba-acco.h" +#include + +void proto_register_dcom_cba_acco(void); +void proto_reg_handoff_dcom_cba_acco(void); + +static int hf_cba_acco_opnum = -1; + +static int hf_cba_acco_ping_factor = -1; + +static int hf_cba_acco_count = -1; + +static int hf_cba_acco_item = -1; +static int hf_cba_acco_data = -1; +static int hf_cba_acco_qc = -1; +static int hf_cba_acco_time_stamp = -1; + +static int hf_cba_acco_conn_qos_type = -1; +static int hf_cba_acco_conn_qos_value = -1; +static int hf_cba_acco_conn_state = -1; +static int hf_cba_acco_conn_cons_id = -1; +static int hf_cba_acco_conn_version = -1; +static int hf_cba_acco_conn_prov_id = -1; +static int hf_cba_acco_conn_provider = -1; +static int hf_cba_acco_conn_consumer = -1; +static int hf_cba_acco_conn_provider_item = -1; +static int hf_cba_acco_conn_consumer_item = -1; +static int hf_cba_acco_conn_substitute = -1; +static int hf_cba_acco_conn_epsilon = -1; +static int hf_cba_acco_conn_persist = -1; + +static int hf_cba_acco_cb_length = -1; +static int hf_cba_acco_cb_conn_data = -1; +static int hf_cba_acco_cb_version = -1; +static int hf_cba_acco_cb_flags = -1; +static int hf_cba_acco_cb_count = -1; +static int hf_cba_acco_cb_item = -1; +static int hf_cba_acco_cb_item_hole = -1; +static int hf_cba_acco_cb_item_length = -1; +static int hf_cba_acco_cb_item_data = -1; + +static int hf_cba_connect_in = -1; +static int hf_cba_disconnect_in = -1; +static int hf_cba_connectcr_in = -1; +static int hf_cba_disconnectcr_in = -1; +static int hf_cba_disconnectme_in = -1; +static int hf_cba_data_first_in = -1; +static int hf_cba_data_last_in = -1; + +/* static int hf_cba_acco_server_pICBAAccoCallback = -1; */ + +static int hf_cba_acco_server_first_connect = -1; + +static int hf_cba_acco_serversrt_prov_mac = -1; +static int hf_cba_acco_serversrt_cons_mac = -1; + +static int hf_cba_acco_serversrt_cr_id = -1; +static int hf_cba_acco_serversrt_cr_length = -1; +static int hf_cba_acco_serversrt_cr_flags = -1; +static int hf_cba_acco_serversrt_cr_flags_timestamped = -1; +static int hf_cba_acco_serversrt_cr_flags_reconfigure = -1; +static int hf_cba_acco_serversrt_record_length = -1; +/* static int hf_cba_acco_serversrt_action = -1; */ +static int hf_cba_acco_serversrt_last_connect = -1; + +static int hf_cba_getprovconnout = -1; + +static int hf_cba_type_desc_len = -1; + +static int hf_cba_connectincr = -1; +static int hf_cba_connectoutcr = -1; +static int hf_cba_connectin = -1; +static int hf_cba_connectout = -1; +static int hf_cba_getconnectionout = -1; +static int hf_cba_readitemout = -1; +static int hf_cba_writeitemin = -1; +static int hf_cba_addconnectionin = -1; +static int hf_cba_addconnectionout = -1; +static int hf_cba_getidout = -1; + +static int hf_cba_getconsconnout = -1; +static int hf_cba_diagconsconnout = -1; +static int hf_cba_acco_conn_error_state = -1; + +static int hf_cba_acco_info_max = -1; +static int hf_cba_acco_info_curr = -1; + +static int hf_cba_acco_cdb_cookie = -1; + +static int hf_cba_acco_rtauto = -1; + +static int hf_cba_acco_prov_crid = -1; + +static int hf_cba_acco_diag_req = -1; +static int hf_cba_acco_diag_in_length = -1; +static int hf_cba_acco_diag_out_length = -1; +static int hf_cba_acco_diag_data = -1; +static int hf_cba_acco_dcom_call = -1; +static int hf_cba_acco_srt_call = -1; + +gint ett_cba_connectincr = -1; +gint ett_cba_connectoutcr = -1; +gint ett_cba_connectin = -1; +gint ett_cba_connectout = -1; +gint ett_cba_getprovconnout = -1; +gint ett_cba_addconnectionin = -1; +gint ett_cba_addconnectionout = -1; +gint ett_cba_getidout = -1; +gint ett_cba_getconnectionout = -1; +gint ett_cba_readitemout = -1; +gint ett_cba_writeitemin = -1; +gint ett_cba_acco_serversrt_cr_flags = -1; +gint ett_cba_frame_info = -1; +gint ett_cba_conn_info = -1; + +static expert_field ei_cba_acco_pdev_find = EI_INIT; +static expert_field ei_cba_acco_prov_crid = EI_INIT; +static expert_field ei_cba_acco_conn_consumer = EI_INIT; +static expert_field ei_cba_acco_ldev_unknown = EI_INIT; +static expert_field ei_cba_acco_no_request_info = EI_INIT; +static expert_field ei_cba_acco_ipid_unknown = EI_INIT; +static expert_field ei_cba_acco_qc = EI_INIT; +static expert_field ei_cba_acco_pdev_find_unknown_interface = EI_INIT; +static expert_field ei_cba_acco_disconnect = EI_INIT; +static expert_field ei_cba_acco_connect = EI_INIT; + +static int proto_ICBAAccoMgt = -1; +static gint ett_ICBAAccoMgt = -1; +static e_guid_t uuid_ICBAAccoMgt = { 0xcba00041, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoMgt = 0; + +static int proto_ICBAAccoMgt2 = -1; +static e_guid_t uuid_ICBAAccoMgt2 = { 0xcba00046, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoMgt2 = 0; + +static int proto_ICBAAccoCallback = -1; +static gint ett_ICBAAccoCallback = -1; +static gint ett_ICBAAccoCallback_Buffer = -1; +static gint ett_ICBAAccoCallback_Item = -1; +static e_guid_t uuid_ICBAAccoCallback = { 0xcba00042, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoCallback = 0; + +static int proto_ICBAAccoCallback2 = -1; +static e_guid_t uuid_ICBAAccoCallback2 = { 0xcba00047, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoCallback2 = 0; + +static int proto_ICBAAccoServer = -1; +static gint ett_ICBAAccoServer = -1; +static e_guid_t uuid_ICBAAccoServer = { 0xcba00043, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoServer = 0; + +static int proto_ICBAAccoServer2 = -1; +static e_guid_t uuid_ICBAAccoServer2 = { 0xcba00048, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoServer2 = 0; + +static int proto_ICBAAccoServerSRT = -1; +static gint ett_ICBAAccoServerSRT = -1; +static e_guid_t uuid_ICBAAccoServerSRT = { 0xcba00045, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoServerSRT = 0; + +static int proto_ICBAAccoSync = -1; +static gint ett_ICBAAccoSync = -1; +static e_guid_t uuid_ICBAAccoSync = { 0xcba00044, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAAccoSync = 0; + + + +static const value_string cba_acco_qc_vals[] = { + { 0x1c, "BadOutOfService" }, + { 0x44, "UncertainLastUsableValue" }, + { 0x48, "UncertainSubstituteSet" }, + { 0x50, "UncertainSensorNotAccurate" }, + { 0x80, "GoodNonCascOk" }, + { 0, NULL } +}; + + +static const value_string cba_qos_type_vals[] = { + { 0x00, "Acyclic" }, + { 0x01, "Acyclic seconds" }, /* obsolete */ + { 0x02, "Acyclic status" }, + { 0x03, "Acyclic HMI" }, + { 0x20, "Constant" }, + { 0x30, "Cyclic Real-Time" }, + { 0, NULL } +}; + + +static const value_string cba_persist_vals[] = { + { 0x00, "Volatile" }, + { 0x01, "PendingPersistent" }, + { 0x02, "Persistent" }, + { 0, NULL } +}; + + +static const value_string cba_acco_conn_state_vals[] = { + { 0x00, "Passive" }, + { 0x01, "Active" }, + { 0, NULL } +}; + +#if 0 +static const value_string cba_acco_serversrt_action_vals[] = { + { 0x00, "Activate" }, + { 0x01, "Deactivate" }, + { 0x02, "Remove" }, + { 0, NULL } +}; +#endif + +static const value_string cba_acco_serversrt_last_connect_vals[] = { + { 0x00, "CR not complete" }, + { 0x01, "CR complete" }, + { 0, NULL } +}; + +static const value_string cba_acco_diag_req_vals[] = { + { 0x0000, "Function directory" }, + { 0x1000, "DevCat statistic" }, + { 0x2000, "Reset statistic" }, + { 0x3000, "Consumer Comm. Events" }, + { 0x4000, "Provider Comm. Events" }, + { 0, NULL } +}; + +static const true_false_string cba_acco_call_flags = { + "Consumer calls Provider (TRUE)", + "Provider calls Consumer (FALSE)" +}; + +static const value_string cba_qos_type_short_vals[] = { + { 0x00, "DCOM" }, + { 0x01, "DCOM(sec)" }, /* obsolete */ + { 0x02, "Status" }, + { 0x03, "HMI" }, + { 0x20, "Const" }, + { 0x30, "SRT" }, + { 0, NULL } +}; + + +typedef struct cba_frame_s { + cba_ldev_t *consparent; + cba_ldev_t *provparent; + GList *conns; + guint packet_connect; + guint packet_disconnect; + guint packet_disconnectme; + guint packet_first; + guint packet_last; + + guint16 length; + guint8 consmac[6]; + guint16 conscrid; + guint32 provcrid; + guint32 conncrret; + guint16 qostype; + guint16 qosvalue; + guint16 offset; +} cba_frame_t; + +typedef struct cba_connection_s { + cba_ldev_t *consparentacco; + cba_ldev_t *provparentacco; + cba_frame_t *parentframe; + guint packet_connect; + guint packet_disconnect; + guint packet_disconnectme; + guint packet_first; + guint packet_last; + + guint16 length; + guint32 consid; + guint32 provid; + const gchar *provitem; + guint32 connret; + guint16 typedesclen; + guint16 *typedesc; + guint16 qostype; + guint16 qosvalue; + guint16 frame_offset; +} cba_connection_t; + + +typedef struct server_frame_call_s { + guint frame_count; + cba_frame_t **frames; +} server_frame_call_t; + + +typedef struct server_connect_call_s { + guint conn_count; + cba_frame_t *frame; + cba_connection_t **conns; +} server_connect_call_t; + +typedef struct server_disconnectme_call_s { + cba_ldev_t *cons; + cba_ldev_t *prov; +} server_disconnectme_call_t; + + +GList *cba_pdevs; + +/* as we are a plugin, we cannot get this from libwireshark! */ +const true_false_string acco_flags_set_truth = { "Set", "Not set" }; + +static gboolean +cba_filter_valid(packet_info *pinfo, void *user_data _U_) +{ + void* profinet_type = p_get_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0); + + return ((profinet_type != NULL) && (GPOINTER_TO_UINT(profinet_type) < 10)); +} + +static gchar* +cba_build_filter(packet_info *pinfo, void *user_data _U_) +{ + gboolean is_tcp = proto_is_frame_protocol(pinfo->layers, "tcp"); + void* profinet_type = p_get_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0); + + if ((pinfo->net_src.type == AT_IPv4) && (pinfo->net_dst.type == AT_IPv4) && is_tcp) { + /* IPv4 */ + switch(GPOINTER_TO_UINT(profinet_type)) { + case 1: + return ws_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 0)", + address_to_str(pinfo->pool, &pinfo->net_dst), + address_to_str(pinfo->pool, &pinfo->net_src), + address_to_str(pinfo->pool, &pinfo->net_src), + address_to_str(pinfo->pool, &pinfo->net_dst)); + case 2: + return ws_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.dcom == 0)", + address_to_str(pinfo->pool, &pinfo->net_src), + address_to_str(pinfo->pool, &pinfo->net_dst), + address_to_str(pinfo->pool, &pinfo->net_dst), + address_to_str(pinfo->pool, &pinfo->net_src)); + case 3: + return ws_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.srt == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.srt == 0)", + address_to_str(pinfo->pool, &pinfo->net_dst), + address_to_str(pinfo->pool, &pinfo->net_src), + address_to_str(pinfo->pool, &pinfo->net_src), + address_to_str(pinfo->pool, &pinfo->net_dst)); + case 4: + return ws_strdup_printf("(ip.src eq %s and ip.dst eq %s and cba.acco.srt == 1) || (ip.src eq %s and ip.dst eq %s and cba.acco.srt == 0)", + address_to_str(pinfo->pool, &pinfo->net_src), + address_to_str(pinfo->pool, &pinfo->net_dst), + address_to_str(pinfo->pool, &pinfo->net_dst), + address_to_str(pinfo->pool, &pinfo->net_src)); + default: + return NULL; + } + } + + return NULL; +} + +#if 0 +static void +cba_connection_dump(cba_connection_t *conn, const char *role) +{ + if (conn->qostype != 0x30) { + ws_debug_printf(" %s#%5u: CID:0x%8x PID:0x%8x PItem:\"%s\" Type:%s QoS:%s/%u Ret:%s Data#%5u-#%5u", + role, + conn->packet_connect, + conn->consid, conn->provid, conn->provitem, + conn->typedesclen != 0 ? val_to_str(conn->typedesc[0], dcom_variant_type_vals, "Unknown (0x%08x)") : "-", + val_to_str(conn->qostype, cba_qos_type_short_vals, "0x%x"), conn->qosvalue, + conn->connret==0xffffffff ? "[pending]" : val_to_str(conn->connret, dcom_hresult_vals, "Unknown (0x%08x)"), + conn->packet_first, conn->packet_last); + } else { + ws_debug_printf(" %s#%5u: CID:0x%8x PID:0x%8x PItem:\"%s\" Type:%s QoS:%s/%u Ret:%s Off:%u", + role, + conn->packet_connect, + conn->consid, conn->provid, conn->provitem, + conn->typedesclen != 0 ? val_to_str(conn->typedesc[0], dcom_variant_type_vals, "Unknown (0x%08x)") : "-", + val_to_str(conn->qostype, cba_qos_type_short_vals, "0x%x"), conn->qosvalue, + conn->connret==0xffffffff ? "[pending]" : val_to_str(conn->connret, dcom_hresult_vals, "Unknown (0x%08x)"), + conn->frame_offset); + } +} + + +static void +cba_object_dump(void) +{ + GList *pdevs; + GList *ldevs; + GList *frames; + GList *conns; + cba_pdev_t *pdev; + cba_ldev_t *ldev; + cba_frame_t *frame; + address addr; + + + for(pdevs = cba_pdevs; pdevs != NULL; pdevs = g_list_next(pdevs)) { + pdev = pdevs->data; + set_address(&addr, AT_IPv4, 4, pdev->ip); + ws_debug_printf("PDev #%5u: %s IFs:%u", pdev->first_packet, address_to_str(pinfo->pool, &addr), + pdev->object ? g_list_length(pdev->object->interfaces) : 0); + + for(ldevs = pdev->ldevs; ldevs != NULL; ldevs = g_list_next(ldevs)) { + ldev = ldevs->data; + ws_debug_printf(" LDev#%5u: \"%s\" LDevIFs:%u AccoIFs:%u", ldev->first_packet, ldev->name, + ldev->ldev_object ? g_list_length(ldev->ldev_object->interfaces) : 0, + ldev->acco_object ? g_list_length(ldev->acco_object->interfaces) : 0); + for(frames = ldev->consframes; frames != NULL; frames = g_list_next(frames)) { + frame = frames->data; + ws_debug_printf(" ConsFrame#%5u: CCRID:0x%x PCRID:0x%x Len:%u Ret:%s Data#%5u-#%5u", + frame->packet_connect, frame->conscrid, frame->provcrid, frame->length, + frame->conncrret==0xffffffff ? "[pending]" : val_to_str(frame->conncrret, dcom_hresult_vals, "Unknown (0x%08x)"), + frame->packet_first, frame->packet_last); + for(conns = frame->conns; conns != NULL; conns = g_list_next(conns)) { + cba_connection_dump(conns->data, "ConsConn"); + } + } + for(frames = ldev->provframes; frames != NULL; frames = g_list_next(frames)) { + frame = frames->data; + ws_debug_printf(" ProvFrame#%5u: CCRID:0x%x PCRID:0x%x Len:%u Ret:%s Data#%5u-#%5u", + frame->packet_connect, frame->conscrid, frame->provcrid, frame->length, + frame->conncrret==0xffffffff ? "[pending]" : val_to_str(frame->conncrret, dcom_hresult_vals, "Unknown (0x%08x)"), + frame->packet_first, frame->packet_last); + for(conns = frame->conns; conns != NULL; conns = g_list_next(conns)) { + cba_connection_dump(conns->data, "ProvConn"); + } + } + for(conns = ldev->consconns; conns != NULL; conns = g_list_next(conns)) { + cba_connection_dump(conns->data, "ConsConn"); + } + for(conns = ldev->provconns; conns != NULL; conns = g_list_next(conns)) { + cba_connection_dump(conns->data, "ProvConn"); + } + } + } +} +#endif + + +cba_pdev_t * +cba_pdev_find(packet_info *pinfo, const address *addr, e_guid_t *ipid) +{ + cba_pdev_t *pdev; + dcom_interface_t *interf; + + + interf = dcom_interface_find(pinfo, addr, ipid); + if (interf != NULL) { + pdev = (cba_pdev_t *)interf->parent->private_data; + if (pdev == NULL) { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_pdev_find, "pdev_find: no pdev for IP:%s IPID:%s", + address_to_str(pinfo->pool, addr), guids_resolve_guid_to_str(ipid, pinfo->pool)); + } + } else { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_pdev_find_unknown_interface, "pdev_find: unknown interface of IP:%s IPID:%s", + address_to_str(pinfo->pool, addr), guids_resolve_guid_to_str(ipid, pinfo->pool)); + pdev = NULL; + } + + return pdev; +} + + +cba_pdev_t * +cba_pdev_add(packet_info *pinfo, const address *addr) +{ + GList *cba_iter; + cba_pdev_t *pdev; + + + /* find pdev */ + for(cba_iter = cba_pdevs; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + pdev = (cba_pdev_t *)cba_iter->data; + if (memcmp(pdev->ip, addr->data, 4) == 0) { + return pdev; + } + } + + /* not found, create a new */ + pdev = wmem_new(wmem_file_scope(), cba_pdev_t); + memcpy( (void *) (pdev->ip), addr->data, 4); + pdev->first_packet = pinfo->num; + pdev->ldevs = NULL; + pdev->object = NULL; + cba_pdevs = g_list_append(cba_pdevs, pdev); + + return pdev; +} + + +void +cba_pdev_link(packet_info *pinfo _U_, cba_pdev_t *pdev, dcom_interface_t *pdev_interf) +{ + + /* "crosslink" pdev interface and its object */ + pdev->object = pdev_interf->parent; + pdev_interf->private_data = pdev; + if (pdev_interf->parent) { + pdev_interf->parent->private_data = pdev; + } +} + + +void +cba_ldev_link(packet_info *pinfo _U_, cba_ldev_t *ldev, dcom_interface_t *ldev_interf) +{ + + /* "crosslink" interface and its object */ + ldev->ldev_object = ldev_interf->parent; + ldev_interf->private_data = ldev; + if (ldev_interf->parent) { + ldev_interf->parent->private_data = ldev; + } +} + + +void +cba_ldev_link_acco(packet_info *pinfo _U_, cba_ldev_t *ldev, dcom_interface_t *acco_interf) +{ + + /* "crosslink" interface and its object */ + ldev->acco_object = acco_interf->parent; + acco_interf->private_data = ldev; + if (acco_interf->parent) { + acco_interf->parent->private_data = ldev; + } +} + + +cba_ldev_t * +cba_ldev_add(packet_info *pinfo, cba_pdev_t *pdev, const char *name) +{ + GList *cba_iter; + cba_ldev_t *ldev; + + + /* find ldev */ + for(cba_iter = pdev->ldevs; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + ldev = (cba_ldev_t *)cba_iter->data; + if (strcmp(ldev->name, name) == 0) { + return ldev; + } + } + + /* not found, create a new */ + ldev = wmem_new(wmem_file_scope(), cba_ldev_t); + ldev->name = wmem_strdup(wmem_file_scope(), name); + ldev->first_packet = pinfo->num; + ldev->ldev_object = NULL; + ldev->acco_object = NULL; + ldev->parent = pdev; + + ldev->provframes = NULL; + ldev->consframes = NULL; + ldev->provconns = NULL; + ldev->consconns = NULL; + + pdev->ldevs = g_list_append(pdev->ldevs, ldev); + + return ldev; +} + + +cba_ldev_t * +cba_ldev_find(packet_info *pinfo, const address *addr, e_guid_t *ipid) { + dcom_interface_t *interf; + cba_ldev_t *ldev; + + + interf = dcom_interface_find(pinfo, addr, ipid); + if (interf != NULL) { + ldev = (cba_ldev_t *)interf->private_data; + + if (ldev == NULL) { + ldev = (cba_ldev_t *)interf->parent->private_data; + } + if (ldev == NULL) { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_ldev_unknown, "Unknown LDev of %s", + address_to_str(pinfo->pool, addr)); + } + } else { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_ipid_unknown, "Unknown IPID of %s", + address_to_str(pinfo->pool, addr)); + ldev = NULL; + } + + return ldev; +} + + +static cba_ldev_t * +cba_acco_add(packet_info *pinfo, const char *acco) +{ + char *ip_str; + char *delim; + guint32 ip; + cba_pdev_t *pdev; + cba_ldev_t *ldev; + address addr; + + + ip_str = g_strdup(acco); + delim = strchr(ip_str, '!'); + if (delim == NULL) { + g_free(ip_str); + return NULL; + } + *delim = 0; + + if (!get_host_ipaddr(ip_str, &ip)) { + g_free(ip_str); + return NULL; + } + + set_address(&addr, AT_IPv4, 4, &ip); + pdev = cba_pdev_add(pinfo, &addr); + delim++; + + ldev = cba_ldev_add(pinfo, pdev, delim); + + g_free(ip_str); + + return ldev; +} + + +static gboolean +cba_packet_in_range(packet_info *pinfo, guint packet_connect, guint packet_disconnect, guint packet_disconnectme) +{ + + if (packet_connect == 0) { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_connect, "cba_packet_in_range#%u: packet_connect not set?", pinfo->num); + } + + if (packet_connect == 0 || pinfo->num < packet_connect) { + return FALSE; + } + if (packet_disconnect != 0 && pinfo->num > packet_disconnect) { + return FALSE; + } + if (packet_disconnectme != 0 && pinfo->num > packet_disconnectme) { + return FALSE; + } + + return TRUE; +} + + +static void +cba_frame_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, cba_frame_t *frame) +{ + if (tree) { + proto_item *item; + proto_item *sub_item; + proto_tree *sub_tree; + + sub_tree = proto_tree_add_subtree_format(tree, tvb, 0, 0, ett_cba_frame_info, &sub_item, + "Cons:\"%s\" CCRID:0x%x Prov:\"%s\" PCRID:0x%x QoS:%s/%ums Len:%u", + frame->consparent ? frame->consparent->name : "", frame->conscrid, + frame->provparent ? frame->provparent->name : "", frame->provcrid, + val_to_str(frame->qostype, cba_qos_type_short_vals, "%u"), + frame->qosvalue, frame->length); + proto_item_set_generated(sub_item); + + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_qos_type, tvb, 0, 0, frame->qostype); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_qos_value, tvb, 0, 0, frame->qosvalue); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_serversrt_cr_id, tvb, 0, 0, frame->conscrid); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_prov_crid, tvb, 0, 0, frame->provcrid); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_serversrt_cr_length, tvb, 0, 0, frame->length); + proto_item_set_generated(item); + + if (frame->consparent != NULL) { + item = proto_tree_add_string(sub_tree, hf_cba_acco_conn_consumer, tvb, 0, 0, frame->consparent->name); + proto_item_set_generated(item); + } + if (frame->provparent != NULL) { + item = proto_tree_add_string(sub_tree, hf_cba_acco_conn_provider, tvb, 0, 0, frame->provparent->name); + proto_item_set_generated(item); + } + + item = proto_tree_add_uint(sub_tree, hf_cba_connectcr_in, + tvb, 0, 0, frame->packet_connect); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_data_first_in, + tvb, 0, 0, frame->packet_first); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_data_last_in, + tvb, 0, 0, frame->packet_last); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_disconnectcr_in, + tvb, 0, 0, frame->packet_disconnect); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_disconnectme_in, + tvb, 0, 0, frame->packet_disconnectme); + proto_item_set_generated(item); + } +} + + +static cba_frame_t * +cba_frame_connect(packet_info *pinfo, cba_ldev_t *cons_ldev, cba_ldev_t *prov_ldev, + guint16 qostype, guint16 qosvalue, const guint8 *consmac, guint16 conscrid, guint16 length) +{ + GList *cba_iter; + cba_frame_t *frame; + + /* find frame */ + for(cba_iter = cons_ldev->consframes; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + frame = (cba_frame_t *)cba_iter->data; + if ( frame->conscrid == conscrid && + memcmp(frame->consmac, consmac, 6) == 0 && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + return frame; + } + } + + frame = wmem_new(wmem_file_scope(), cba_frame_t); + + frame->consparent = cons_ldev; + frame->provparent = prov_ldev; + + frame->packet_connect = pinfo->num; + frame->packet_disconnect = 0; + frame->packet_disconnectme = 0; + frame->packet_first = 0; + frame->packet_last = 0; + + frame->length = length; + memcpy( (guint8 *) (frame->consmac), consmac, sizeof(frame->consmac)); + frame->conscrid = conscrid; + frame->qostype = qostype; + frame->qosvalue = qosvalue; + + frame->offset = 4; + frame->conns = NULL; + + frame->provcrid = 0; + frame->conncrret = -1; + + cons_ldev->consframes = g_list_append(cons_ldev->consframes, frame); + prov_ldev->provframes = g_list_append(prov_ldev->provframes, frame); + + return frame; +} + + +static void +cba_frame_disconnect(packet_info *pinfo, cba_frame_t *frame) +{ + + if (frame->packet_disconnect == 0) { + frame->packet_disconnect = pinfo->num; + } + + if (frame->packet_disconnect != pinfo->num) { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_disconnect, "cba_frame_disconnect#%u: frame already disconnected in #%u", + pinfo->num, frame->packet_disconnect); + } +} + + +static void +cba_frame_disconnectme(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_ldev_t *cons_ldev, cba_ldev_t *prov_ldev) +{ + GList *frames; + cba_frame_t *frame; + + + for(frames = cons_ldev->consframes; frames != NULL; frames = g_list_next(frames)) { + frame = (cba_frame_t *)frames->data; + + if ( frame->provparent == prov_ldev && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + + cba_frame_info(tvb, pinfo, tree, frame); + + if (frame->packet_disconnectme == 0) { + frame->packet_disconnectme = pinfo->num; + } + + if (frame->packet_disconnectme != pinfo->num) { + expert_add_info_format(pinfo, tree, &ei_cba_acco_disconnect, "cba_frame_disconnectme#%u: frame already disconnectme'd in #%u", + pinfo->num, frame->packet_disconnectme); + } + } + } +} + + +static cba_frame_t * +cba_frame_find_by_cons(packet_info *pinfo, const guint8 *consmac, guint16 conscrid) +{ + GList *pdevs; + GList *ldevs; + GList *frames; + cba_pdev_t *pdev; + cba_ldev_t *ldev; + cba_frame_t *frame; + + + /* find pdev */ + for(pdevs = cba_pdevs; pdevs != NULL; pdevs = g_list_next(pdevs)) { + pdev = (cba_pdev_t *)pdevs->data; + + /* find ldev */ + for(ldevs = pdev->ldevs; ldevs != NULL; ldevs = g_list_next(ldevs)) { + ldev = (cba_ldev_t *)ldevs->data; + + /* find frame */ + for(frames = ldev->consframes; frames != NULL; frames = g_list_next(frames)) { + frame = (cba_frame_t *)frames->data; + + if ( frame->conscrid == conscrid && + memcmp(frame->consmac, consmac, 6) == 0 && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + return frame; + } + } + } + } + + return NULL; +} + + +static cba_frame_t * +cba_frame_find_by_provcrid(packet_info *pinfo, cba_ldev_t *prov_ldev, guint32 provcrid) +{ + GList *frames; + cba_frame_t *frame; + + + if (prov_ldev == NULL) { + return NULL; + } + + for(frames = prov_ldev->provframes; frames != NULL; frames = g_list_next(frames)) { + frame = (cba_frame_t *)frames->data; + + if ( frame->provcrid == provcrid && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + return frame; + } + } + + expert_add_info(pinfo, NULL, &ei_cba_acco_prov_crid); + + return NULL; +} + + +static void +cba_frame_incoming_data(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, cba_frame_t *frame) +{ + if (frame->packet_first == 0) { + frame->packet_first = pinfo->num; + } + + if ( pinfo->num > frame->packet_last && + cba_packet_in_range(pinfo, frame->packet_connect, frame->packet_disconnect, frame->packet_disconnectme)) { + frame->packet_last = pinfo->num; + } +} + + +static void +cba_connection_info(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, cba_connection_t *conn) +{ + if (tree) { + proto_item *item; + proto_item *sub_item; + proto_tree *sub_tree; + + if (conn->qostype != 0x30) { + sub_tree = proto_tree_add_subtree_format(tree, tvb, 0, 0, ett_cba_conn_info, &sub_item, + "ProvItem:\"%s\" PID:0x%x CID:0x%x QoS:%s/%ums", + conn->provitem, conn->provid, conn->consid, + val_to_str(conn->qostype, cba_qos_type_short_vals, "%u"), conn->qosvalue); + } else { + sub_tree = proto_tree_add_subtree_format(tree, tvb, 0, 0, ett_cba_conn_info, &sub_item, + "ProvItem:\"%s\" PID:0x%x CID:0x%x Len:%u", + conn->provitem, conn->provid, conn->consid, conn->length); + } + proto_item_set_generated(sub_item); + + item = proto_tree_add_string(sub_tree, hf_cba_acco_conn_provider_item, tvb, 0, 0 /* len */, conn->provitem); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_prov_id, tvb, 0, 0 /* len */, conn->provid); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_cons_id, tvb, 0, 0 /* len */, conn->consid); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_serversrt_record_length, tvb, 0, 0 /* len */, conn->length); + proto_item_set_generated(item); + + if (conn->qostype != 0x30) { + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_qos_type, + tvb, 0, 0, conn->qostype); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_acco_conn_qos_value, + tvb, 0, 0, conn->qosvalue); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_connect_in, + tvb, 0, 0, conn->packet_connect); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_data_first_in, + tvb, 0, 0, conn->packet_first); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_data_last_in, + tvb, 0, 0, conn->packet_last); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_disconnect_in, + tvb, 0, 0, conn->packet_disconnect); + proto_item_set_generated(item); + item = proto_tree_add_uint(sub_tree, hf_cba_disconnectme_in, + tvb, 0, 0, conn->packet_disconnectme); + proto_item_set_generated(item); + } + } +} + + +static cba_connection_t * +cba_connection_connect(packet_info *pinfo, cba_ldev_t *cons_ldev, cba_ldev_t *prov_ldev, cba_frame_t *cons_frame, + guint16 qostype, guint16 qosvalue, const char *provitem, guint32 consid, guint16 length, + guint16 *typedesc, guint16 typedesclen) +{ + GList *cba_iter; + cba_connection_t *conn; + + + /* find connection */ + if (cons_frame != NULL) { + /* SRT: search in frame */ + for(cba_iter = cons_frame->conns; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + conn = (cba_connection_t *)cba_iter->data; + if (conn->consid == consid) { + return conn; + } + } + } else { + /* DCOM: search in ldev */ + for(cba_iter = cons_ldev->consconns; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + conn = (cba_connection_t *)cba_iter->data; + if ( conn->consid == consid && + cba_packet_in_range(pinfo, conn->packet_connect, conn->packet_disconnect, conn->packet_disconnectme)) { + return conn; + } + } + } + + conn = wmem_new(wmem_file_scope(), cba_connection_t); + + conn->consparentacco = cons_ldev; + conn->provparentacco = prov_ldev; + conn->parentframe = cons_frame; + + conn->packet_connect = pinfo->num; + conn->packet_disconnect = 0; + conn->packet_disconnectme = 0; + conn->packet_first = 0; + conn->packet_last = 0; + + conn->consid = consid; + conn->provitem = wmem_strdup(wmem_file_scope(), provitem); + conn->typedesclen = typedesclen; + conn->typedesc = typedesc; + conn->qostype = qostype; + conn->qosvalue = qosvalue; + conn->length = length; + + conn->provid = 0; + conn->connret = -1; + + if (cons_frame != NULL) { + conn->frame_offset = cons_frame->offset; + conn->length = length; + cons_frame->offset += length; + cons_frame->conns = g_list_append(cons_frame->conns, conn); + } else { + conn->frame_offset = 0; + cons_ldev->consconns = g_list_append(cons_ldev->consconns, conn); + prov_ldev->provconns = g_list_append(prov_ldev->provconns, conn); + } + + return conn; +} + + +static void +cba_connection_disconnect(packet_info *pinfo, cba_connection_t *conn) +{ + /* XXX - detect multiple disconnects? */ + if (conn->packet_disconnect == 0) { + conn->packet_disconnect = pinfo->num; + } + + if (conn->packet_disconnect != pinfo->num) { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_disconnect, "connection_disconnect#%u: already disconnected", + conn->packet_disconnect); + } +} + + +static void +cba_connection_disconnectme(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, cba_ldev_t *cons_ldev, cba_ldev_t *prov_ldev) +{ + GList *conns; + cba_connection_t *conn; + + + for(conns = cons_ldev->consconns; conns != NULL; conns = g_list_next(conns)) { + conn = (cba_connection_t *)conns->data; + + if ( conn->provparentacco == prov_ldev && + cba_packet_in_range(pinfo, conn->packet_connect, conn->packet_disconnect, conn->packet_disconnectme)) { + + cba_connection_info(tvb, pinfo, tree, conn); + + if (conn->packet_disconnectme == 0) { + conn->packet_disconnectme = pinfo->num; + } + + if (conn->packet_disconnectme != pinfo->num) { + expert_add_info_format(pinfo, tree, &ei_cba_acco_disconnect, "connection_disconnectme#%u: already disconnectme'd", + conn->packet_disconnectme); + } + } + } +} + + +static cba_connection_t * +cba_connection_find_by_provid(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, cba_ldev_t *prov_ldev, guint32 provid) +{ + GList *cba_iter; + cba_connection_t *conn; + + + for(cba_iter = prov_ldev->provconns; cba_iter != NULL; cba_iter = g_list_next(cba_iter)) { + conn = (cba_connection_t *)cba_iter->data; + if ( conn->provid == provid && + cba_packet_in_range(pinfo, conn->packet_connect, conn->packet_disconnect, conn->packet_disconnectme)) { + return conn; + } + } + return NULL; +} + + +static void +cba_connection_incoming_data(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, cba_connection_t *conn) +{ + if (conn->packet_first == 0) { + conn->packet_first = pinfo->num; + } + + if ( pinfo->num > conn->packet_last && + cba_packet_in_range(pinfo, conn->packet_connect, conn->packet_disconnect, conn->packet_disconnectme)) { + conn->packet_last = pinfo->num; + } +} + + +/* dissect a response containing an array of hresults (e.g: ICBAAccoMgt::RemoveConnections) */ +static int +dissect_HResultArray_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32Idx; + guint32 u32Tmp; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + u32Tmp = u32ArraySize; + while (u32Tmp--) { + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult, u32Idx); + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32ArraySize, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServer_SetActivation_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32Idx; + guint32 u32Tmp; + proto_item *item; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(1)); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + u32Tmp = u32ArraySize; + while (u32Tmp--) { + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult, u32Idx); + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32ArraySize, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_Disconnect_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32Idx; + guint32 u32Tmp; + proto_item *item; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(3)); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + u32Tmp = u32ArraySize; + while (u32Tmp--) { + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult, u32Idx); + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32ArraySize, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_SetActivation_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32Idx; + guint32 u32Tmp; + proto_item *item; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(3)); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + u32Tmp = u32ArraySize; + while (u32Tmp--) { + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult, u32Idx); + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32ArraySize, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServer_Connect_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + + guint32 u32VariableOffset; + guint32 u32SubStart; + guint32 u32Pointer; + guint16 u16VarType; + guint32 u32ConsID; + gchar szItem[1000] = { 0 }; + guint32 u32MaxItemLen = sizeof(szItem); + gchar szCons[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szCons); + guint32 u32Idx; + + proto_item *item; + dcom_interface_t *cons_interf; + cba_ldev_t *cons_ldev; + cba_ldev_t *prov_ldev; + cba_connection_t *conn; + server_connect_call_t *call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(2)); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + + /* find the consumer ldev by its name */ + cons_ldev = cba_acco_add(pinfo, szCons); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, di, drep, 0, &cons_interf); + if (cons_interf == NULL) { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_conn_consumer, + "Server_Connect: consumer interface invalid"); + } + + /* "crosslink" consumer interface and its object */ + if (cons_interf != NULL && cons_ldev != NULL) { + cba_ldev_link_acco(pinfo, cons_ldev, cons_interf); + } + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /* link connections infos to the call */ + if (prov_ldev != NULL && cons_ldev != NULL) { + call = (server_connect_call_t *)wmem_alloc(wmem_file_scope(), sizeof(server_connect_call_t) + u32ArraySize * sizeof(cba_connection_t *)); + call->conn_count = 0; + call->frame = NULL; + call->conns = (cba_connection_t **) (call+1); + di->call_data->private_data = call; + } else{ + call = NULL; + } + + u32VariableOffset = offset + u32ArraySize*16; + + /* array of CONNECTINs */ + u32Idx = 1; + while (u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_connectin, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectin); + u32SubStart = offset; + + /* ProviderItem */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider_item, szItem, u32MaxItemLen); + } + + /* DataType */ + offset = dissect_dcom_VARTYPE(tvb, offset, pinfo, sub_tree, di, drep, + &u16VarType); + + /* Epsilon */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_epsilon); + } + /* ConsumerID */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + /* add to object database */ + if (prov_ldev != NULL && cons_ldev != NULL) { + conn = cba_connection_connect(pinfo, cons_ldev, prov_ldev, /*cons_frame*/ NULL, + u16QoSType, u16QoSValue, szItem, u32ConsID, 0, + /* XXX - VarType must be translated to new type description if it includes an array (0x2000) */ + (guint16 *)wmem_memdup(wmem_file_scope(), &u16VarType, 2), 1); + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } else { + conn = NULL; + } + + /* add to current call */ + if (call != NULL) { + call->conn_count++; + call->conns[u32Idx-1] = conn; + } + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", VarType=%s", + u32Idx, u32ConsID, szItem, + val_to_str(u16VarType, dcom_variant_type_vals, "Unknown (0x%04x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Consumer=\"%s\" Cnt=%u", szCons, u32Count); + + return u32VariableOffset; +} + +static int +dissect_ICBAAccoServer2_Connect2_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + + guint32 u32VariableOffset; + guint32 u32SubStart; + guint32 u32Pointer; + guint16 u16VarType; + guint32 u32ConsID; + gchar szItem[1000] = { 0 }; + guint32 u32MaxItemLen = sizeof(szItem); + gchar szCons[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szCons); + guint32 u32Idx; + guint16 u16TypeDescLen; + guint32 u32ArraySize2; + guint32 u32Idx2; + guint16 u16VarType2 = -1; + + proto_item *item; + dcom_interface_t *cons_interf; + cba_ldev_t *prov_ldev; + cba_ldev_t *cons_ldev; + cba_connection_t *conn; + guint16 typedesclen = 0; + guint16 *typedesc = NULL; + server_connect_call_t *call = NULL; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(2)); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + + /* find the consumer ldev by its name */ + cons_ldev = cba_acco_add(pinfo, szCons); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_MInterfacePointer(tvb, offset, pinfo, tree, di, drep, 0, &cons_interf); + if (cons_interf == NULL) { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_conn_consumer, + "Server2_Connect2: consumer interface invalid"); + } + } else { + /* GetConnectionData do it this way */ + cons_interf = NULL; + } + + /* "crosslink" consumer interface and its object */ + if (cons_interf != NULL && cons_ldev != NULL) { + cba_ldev_link_acco(pinfo, cons_ldev, cons_interf); + } + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /* link connection infos to the call */ + if (prov_ldev != NULL && cons_ldev != NULL) { + call = (server_connect_call_t *)wmem_alloc(wmem_file_scope(), sizeof(server_connect_call_t) + u32ArraySize * sizeof(cba_connection_t *)); + call->conn_count = 0; + call->frame = NULL; + call->conns = (cba_connection_t **) (call+1); + di->call_data->private_data = call; + } else{ + call = NULL; + } + + u32VariableOffset = offset + u32ArraySize*20; + + /* array of CONNECTINs */ + u32Idx = 1; + while (u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_connectin, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectin); + u32SubStart = offset; + + /* ProviderItem */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider_item, szItem, u32MaxItemLen); + } + + /* TypeDescLen */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_type_desc_len, &u16TypeDescLen); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + /* pTypeDesc */ + if (u32Pointer) { + u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + &u32ArraySize2); + + /* limit the allocation to a reasonable size */ + if (u32ArraySize2 < 1000) { + typedesc = (guint16 *)wmem_alloc0(wmem_file_scope(), u32ArraySize2 * 2); + typedesclen = u32ArraySize2; + } else { + typedesc = NULL; + typedesclen = 0; + } + + /* extended type description will build an array here */ + u32Idx2 = 1; + while (u32ArraySize2--) { + /* ToBeDone: some of the type description values are counts */ + u32VariableOffset = dissect_dcom_VARTYPE(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + &u16VarType); + + if (typedesc != NULL && u32Idx2 <= typedesclen) { + typedesc[u32Idx2-1] = u16VarType; + } + + /* remember first VarType only */ + if (u32Idx2 == 1) { + u16VarType2 = u16VarType; + } + u32Idx2++; + } + } + + /* Epsilon */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_epsilon); + } + /* ConsumerID */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + /* add to object database */ + if (prov_ldev != NULL && cons_ldev != NULL) { + conn = cba_connection_connect(pinfo, cons_ldev, prov_ldev, /*cons_frame*/ NULL, + u16QoSType, u16QoSValue, szItem, u32ConsID, 0, + typedesc, typedesclen); + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } else { + conn = NULL; + } + + /* add to current call */ + if (call != NULL) { + call->conn_count++; + call->conns[u32Idx-1] = conn; + } + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", TypeDesc=%s", + u32Idx, u32ConsID, szItem, + val_to_str(u16VarType2, dcom_variant_type_vals, "Unknown (0x%04x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Consumer=\"%s\" Cnt=%u", szCons, u32Count); + + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoServer_Connect_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint8 u8FirstConnect; + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32HResult; + guint32 u32Idx = 1; + guint32 u32ProvID; + guint32 u32SubStart; + + proto_item *item; + cba_connection_t *conn; + server_connect_call_t *call = (server_connect_call_t *)di->call_data->private_data; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + if (call == NULL) { + expert_add_info(pinfo, NULL, &ei_cba_acco_no_request_info); + } + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(1)); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_server_first_connect, &u8FirstConnect); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /* array of CONNECTOUTs */ + while(u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_connectout, tvb, offset, 8, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectout); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_prov_id, &u32ProvID); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + /* put response data into the connection */ + if (call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + conn->provid = u32ProvID; + conn->connret = u32HResult; + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } + + proto_item_append_text(sub_item, "[%u]: ProvID=0x%x %s", + u32Idx, u32ProvID, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + /* this might be a global HRESULT */ + while(call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + conn->provid = 0; + conn->connret = u32HResult; + u32Idx++; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s Cnt=%u -> %s", + (u8FirstConnect) ? "First" : "NotFirst", + u32Idx-1, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServer_Disconnect_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + + proto_item *item; + cba_ldev_t *prov_ldev; + cba_connection_t *conn; + server_connect_call_t *call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(2)); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + prov_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + /* link connection infos to the call */ + if (prov_ldev != NULL) { + call = (server_connect_call_t *)wmem_alloc(wmem_file_scope(), sizeof(server_connect_call_t) + u32ArraySize * sizeof(cba_connection_t *)); + call->conn_count = 0; + call->frame = NULL; + call->conns = (cba_connection_t **) (call+1); + di->call_data->private_data = call; + } else{ + call = NULL; + } + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + + /* add to current call */ + if (call != NULL) { + conn = cba_connection_find_by_provid(tvb, pinfo, tree, prov_ldev, u32ProvID); + call->conn_count++; + call->conns[u32Idx-1] = conn; + } + + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + + return offset; +} + + +static int +dissect_ICBAAccoServer_Disconnect_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32Idx; + guint32 u32Tmp; + + proto_item *item; + cba_connection_t *conn; + server_connect_call_t *call = (server_connect_call_t *)di->call_data->private_data; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + if (call == NULL) { + expert_add_info(pinfo, NULL, &ei_cba_acco_no_request_info); + } + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(1)); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + u32Tmp = u32ArraySize; + while (u32Tmp--) { + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult, u32Idx); + + /* mark this connection as disconnected */ + if (call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + if (conn != NULL) { + cba_connection_disconnect(pinfo, conn); + } + } + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32ArraySize, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_Disconnect_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + proto_item *item; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(4)); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return offset; +} + + +static int +dissect_ICBAAccoServer_DisconnectMe_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + proto_item *item; + cba_ldev_t *prov_ldev; + cba_ldev_t *cons_ldev; + server_disconnectme_call_t *call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(2)); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_consumer, szStr, u32MaxStr); + + /* find the consumer ldev by its name */ + cons_ldev = cba_acco_add(pinfo, szStr); + + if (prov_ldev != NULL && cons_ldev != NULL) { + call = wmem_new(wmem_file_scope(), server_disconnectme_call_t); + call->cons = cons_ldev; + call->prov = prov_ldev; + di->call_data->private_data = call; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Consumer=\"%s\"", szStr); + + return offset; +} + + +static int +dissect_ICBAAccoServer_DisconnectMe_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + proto_item *item; + server_disconnectme_call_t *call; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(1)); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + call = (server_disconnectme_call_t *)di->call_data->private_data; + if (call) { + cba_connection_disconnectme(tvb, pinfo, tree, call->cons, call->prov); + } + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_DisconnectMe_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + proto_item *item; + cba_ldev_t *prov_ldev; + cba_ldev_t *cons_ldev; + server_disconnectme_call_t *call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(4)); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_consumer, szStr, u32MaxStr); + + /* find the consumer ldev by its name */ + cons_ldev = cba_acco_add(pinfo, szStr); + + if (prov_ldev != NULL && cons_ldev != NULL) { + call = wmem_new(wmem_file_scope(), server_disconnectme_call_t); + call->cons = cons_ldev; + call->prov = prov_ldev; + di->call_data->private_data = call; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Consumer=\"%s\"", szStr); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_DisconnectMe_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + proto_item *item; + server_disconnectme_call_t *call; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(3)); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + call = (server_disconnectme_call_t *)di->call_data->private_data; + if (call) { + cba_frame_disconnectme(tvb, pinfo, tree, call->cons, call->prov); + } + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServer_Ping_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + proto_item *item; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(1)); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServer_SetActivation_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + proto_item *item; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(2)); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + u32Idx++; + } + + /* update column info now */ + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_SetActivation_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + proto_item *item; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(4)); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return offset; +} + + +static int +dissect_ICBAAccoServer_Ping_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + proto_item *item; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(2)); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_consumer, szStr, u32MaxStr); + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Consumer=\"%s\"", szStr); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_ConnectCR_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szCons[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szCons); + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8ConsMac[6]; + guint16 u16CRID = 0; + guint16 u16CRLength = 0; + guint32 u32Flags; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + proto_item *item; + proto_tree *flags_tree; + guint32 u32SubStart; + dcom_interface_t *cons_interf; + cba_ldev_t *prov_ldev; + cba_ldev_t *cons_ldev; + cba_frame_t *frame; + server_frame_call_t *call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(4)); + + /* szCons */ + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + + /* find the consumer ldev by its name */ + cons_ldev = cba_acco_add(pinfo, szCons); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, di, drep, 0, &cons_interf); + if (cons_interf == NULL) { + expert_add_info_format(pinfo, NULL, &ei_cba_acco_conn_consumer, + "ServerSRT_ConnectCR: consumer interface invalid"); + } + + /* "crosslink" consumer interface and its object */ + if (cons_interf != NULL && cons_ldev != NULL) { + cba_ldev_link_acco(pinfo, cons_ldev, cons_interf); + } + + /* ConsumerMAC (big-endian, 1byte-aligned) */ + tvb_memcpy(tvb, u8ConsMac, offset, 6); + + proto_tree_add_ether(tree, hf_cba_acco_serversrt_cons_mac, tvb, + offset, 6, u8ConsMac); + offset += 6; + + /* add flags subtree */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, NULL /*tree*/, di, drep, + 0 /* hfindex */, &u32Flags); + offset -= 4; + item = proto_tree_add_uint_format_value(tree, hf_cba_acco_serversrt_cr_flags, + tvb, offset, 4, u32Flags, + "0x%02x (%s, %s)", u32Flags, + (u32Flags & 0x2) ? "Reconfigure" : "not Reconfigure", + (u32Flags & 0x1) ? "Timestamped" : "not Timestamped"); + flags_tree = proto_item_add_subtree(item, ett_cba_acco_serversrt_cr_flags); + proto_tree_add_boolean(flags_tree, hf_cba_acco_serversrt_cr_flags_reconfigure, tvb, offset, 4, u32Flags); + proto_tree_add_boolean(flags_tree, hf_cba_acco_serversrt_cr_flags_timestamped, tvb, offset, 4, u32Flags); + offset += 4; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /* link frame infos to the call */ + if (prov_ldev != NULL && cons_ldev != NULL && u32ArraySize < 100) { + call = (server_frame_call_t *)wmem_alloc(wmem_file_scope(), sizeof(server_frame_call_t) + u32ArraySize * sizeof(cba_frame_t *)); + call->frame_count = 0; + call->frames = (cba_frame_t **) (call+1); + di->call_data->private_data = call; + } else { + call = NULL; + } + + u32Idx = 1; + while (u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + /* array of CONNECTINCRs */ + sub_item = proto_tree_add_item(tree, hf_cba_connectincr, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectincr); + u32SubStart = offset; + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_serversrt_cr_id, &u16CRID); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_serversrt_cr_length, &u16CRLength); + + /* add to object database */ + if (prov_ldev != NULL && cons_ldev != NULL) { + frame = cba_frame_connect(pinfo, cons_ldev, prov_ldev, u16QoSType, u16QoSValue, u8ConsMac, u16CRID, u16CRLength); + + cba_frame_info(tvb, pinfo, sub_tree, frame); + } else { + frame = NULL; + } + + /* add to current call */ + if (call != NULL) { + call->frame_count++; + call->frames[u32Idx-1] = frame; + } + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: CRID=0x%x, CRLength=%u", + u32Idx, u16CRID, u16CRLength); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": %sConsCRID=0x%x Len=%u QoS=%u", + (u32Flags & 0x2) ? "Reco " : "", u16CRID, u16CRLength, u16QoSValue); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_ConnectCR_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint8 u8FirstConnect; + guint8 u8ProvMac[6]; + guint32 u32ProvCRID = 0; + guint32 u32HResult; + guint32 u32ArraySize; + guint32 u32Idx = 1; + guint32 u32Pointer; + guint32 u32SubStart; + proto_item *item; + cba_frame_t *frame; + server_frame_call_t *call = (server_frame_call_t *)di->call_data->private_data; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + if (call == NULL) { + expert_add_info(pinfo, NULL, &ei_cba_acco_no_request_info); + } + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(3)); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_server_first_connect, &u8FirstConnect); + + /* ProviderMAC (big-endian, 1byte-aligned) */ + tvb_memcpy(tvb, u8ProvMac, offset, 6); + + proto_tree_add_ether(tree, hf_cba_acco_serversrt_prov_mac, tvb, + offset, 6, u8ProvMac); + offset += 6; + + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + while (u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + /* array of CONNECTOUTCRs */ + sub_item = proto_tree_add_item(tree, hf_cba_connectoutcr, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectoutcr); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_prov_crid, &u32ProvCRID); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult); + + /* put response data into the frame */ + if (call && u32Idx <= call->frame_count) { + frame = call->frames[u32Idx-1]; + frame->provcrid = u32ProvCRID; + frame->conncrret = u32HResult; + + cba_frame_info(tvb, pinfo, sub_tree, frame); + } + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: ProvCRID=0x%x, %s", + u32Idx, u32ProvCRID, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + /* this might be a global HRESULT */ + while(call && u32Idx <= call->frame_count) { + frame = call->frames[u32Idx-1]; + frame->provcrid = 0; + frame->conncrret = u32HResult; + u32Idx++; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s PCRID=0x%x -> %s", + (u8FirstConnect) ? "FirstCR" : "NotFirstCR", + u32ProvCRID, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_DisconnectCR_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvCRID = 0; + proto_item *item; + cba_ldev_t *prov_ldev; + cba_frame_t *frame; + server_frame_call_t *call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(4)); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /* link frame infos to the call */ + if (prov_ldev != NULL) { + call = (server_frame_call_t *)wmem_alloc(wmem_file_scope(), sizeof(server_frame_call_t) + u32ArraySize * sizeof(cba_frame_t *)); + call->frame_count = 0; + call->frames = (cba_frame_t **) (call+1); + di->call_data->private_data = call; + } else{ + call = NULL; + } + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_prov_crid, &u32ProvCRID, u32Idx); + + /* find frame and add it to current call */ + if (call != NULL) { + frame = cba_frame_find_by_provcrid(pinfo, prov_ldev, u32ProvCRID); + call->frame_count++; + call->frames[u32Idx-1] = frame; + } + + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": PCRID=0x%x", + u32ProvCRID); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_DisconnectCR_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32Idx; + guint32 u32Tmp; + cba_frame_t *frame; + proto_item *item; + server_frame_call_t *call = (server_frame_call_t *)di->call_data->private_data; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(3)); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + u32Tmp = u32ArraySize; + while (u32Tmp--) { + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult, u32Idx); + /* put response data into the frame */ + if (call && u32Idx <= call->frame_count) { + frame = call->frames[u32Idx-1]; + if (frame != NULL) { + cba_frame_disconnect(pinfo, frame); + } + } + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServerSRT_Connect_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32ProvCRID; + guint8 u8State; + guint8 u8LastConnect; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32VariableOffset; + guint32 u32Idx; + guint32 u32SubStart; + guint32 u32Pointer; + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + guint16 u16TypeDescLen; + guint32 u32ArraySize2; + guint32 u32Idx2; + guint16 u16VarType2 = -1; + guint16 u16VarType; + guint32 u32ConsID; + guint16 u16RecordLength; + + proto_item *item; + cba_ldev_t *prov_ldev; + cba_frame_t *frame = NULL; + guint16 typedesclen = 0; + guint16 *typedesc = NULL; + + cba_connection_t *conn; + server_connect_call_t *call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + /* get corresponding provider ldev */ + prov_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(4)); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_prov_crid, &u32ProvCRID); + + frame = cba_frame_find_by_provcrid(pinfo, prov_ldev, u32ProvCRID); + + if (frame != NULL) { + cba_frame_info(tvb, pinfo, tree, frame); + } + + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_BYTE(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_serversrt_last_connect, &u8LastConnect); + + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /* link connections infos to the call */ + if (frame != NULL) { + call = (server_connect_call_t *)wmem_alloc(wmem_file_scope(), sizeof(server_connect_call_t) + u32ArraySize * sizeof(cba_connection_t *)); + call->conn_count = 0; + call->frame = frame; + call->conns = (cba_connection_t **) (call+1); + di->call_data->private_data = call; + } else{ + call = NULL; + } + + u32VariableOffset = offset + u32ArraySize*20; + + u32Idx = 1; + while (u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + /* array of CONNECTINs */ + sub_item = proto_tree_add_item(tree, hf_cba_connectin, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectin); + u32SubStart = offset; + + /* ProviderItem */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + + /* TypeDescLen */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_type_desc_len, &u16TypeDescLen); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + /* pTypeDesc */ + if (u32Pointer) { + u32VariableOffset = dissect_dcom_dcerpc_array_size(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + &u32ArraySize2); + + typedesc = (guint16 *)wmem_alloc0(wmem_file_scope(), u32ArraySize2 * 2); + typedesclen = u32ArraySize2; + + /* extended type description will build an array here */ + u32Idx2 = 1; + while (u32ArraySize2--) { + /* ToBeDone: some of the type description values are counts */ + u32VariableOffset = dissect_dcom_VARTYPE(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + &u16VarType); + + if (u32Idx2 <= typedesclen) { + typedesc[u32Idx2-1] = u16VarType; + } + + /* remember first VarType only */ + if (u32Idx2 == 1) { + u16VarType2 = u16VarType; + } + u32Idx2++; + } + } + + /* ConsumerID */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + /* RecordLength */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_serversrt_record_length, &u16RecordLength); + + /* add to object database */ + if (frame != NULL) { + conn = cba_connection_connect(pinfo, frame->consparent, frame->provparent, frame, + frame->qostype, frame->qosvalue, szProvItem, u32ConsID, u16RecordLength, + typedesc, typedesclen); + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } else { + conn = NULL; + } + + /* add to current call */ + if (call != NULL) { + call->conn_count++; + call->conns[u32Idx-1] = conn; + } + + /* update subtree header */ + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x, ProvItem=\"%s\", TypeDesc=%s", + u32Idx, u32ConsID, szProvItem, + val_to_str(u16VarType2, dcom_variant_type_vals, "Unknown (0x%04x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s Cnt=%u PCRID=0x%x", + (u8LastConnect) ? "LastOfCR" : "", + u32Idx-1, + u32ProvCRID); + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoServerSRT_Connect_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32Idx = 1; + guint32 u32SubStart; + guint32 u32ProvID; + guint32 u32HResult; + + proto_item *item; + + server_connect_call_t *call = (server_connect_call_t *)di->call_data->private_data; + cba_connection_t *conn; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + if (call == NULL) { + expert_add_info(pinfo, NULL, &ei_cba_acco_no_request_info); + } + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(3)); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (call && call->frame != NULL) { + cba_frame_info(tvb, pinfo, tree, call->frame); + } + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /* array of CONNECTOUTs */ + while(u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_connectout, tvb, offset, 8, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_connectout); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_prov_id, &u32ProvID); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + /* put response data into the frame */ + if (call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + conn->provid = u32ProvID; + conn->connret = u32HResult; + + cba_connection_info(tvb, pinfo, sub_tree, conn); + } + + proto_item_append_text(sub_item, "[%u]: ProvID=0x%x %s", + u32Idx, u32ProvID, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + /* this might be a global HRESULT */ + while(call && u32Idx <= call->conn_count) { + conn = call->conns[u32Idx-1]; + conn->provid = 0; + conn->connret = u32HResult; + u32Idx++; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32Idx-1, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_Server_GetProvIDs_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + if (u32Count) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u ProvID=", u32Count); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, + tree, di, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + + if (u32Idx == 1) { + col_append_fstr(pinfo->cinfo, COL_INFO, "0x%x", u32ProvID); + } else if (u32Idx < 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",0x%x", u32ProvID); + } else if (u32Idx == 10) { + col_append_str(pinfo->cinfo, COL_INFO, ",..."); + } + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_Server_GetProvConnections_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ProvID; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_prov_id, &u32ProvID, u32Idx); + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return offset; +} + + +static int +dissect_Server_GetProvConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32TmpCount; + guint32 u32Pointer; + guint32 u32VariableOffset; + guint32 u32Idx; + guint32 u32SubStart; + gchar szCons[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szCons); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + guint32 u32ConsID; + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + u32VariableOffset = offset + u32Count*28; + + /* array fixed part (including pointers to variable part) */ + u32TmpCount = u32Count; + u32Idx = 1; + while (u32TmpCount--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_getprovconnout, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getprovconnout); + u32SubStart = offset; + + /* wszConsumer */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_consumer, szCons, u32MaxConsLen); + } + /* wszProviderItem */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + /* dwConsID */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + /* Epsilon */ + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_epsilon); + } + + /* QoS Type */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + /* QoS Value */ + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + /* State */ + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_state, &u8State); + /* PartialResult */ + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: %s", + u32Idx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return u32VariableOffset; +} + + +#define CBA_MRSH_VERSION_DCOM 0x01 +#define CBA_MRSH_VERSION_SRT_WITH_CONSID 0x10 +#define CBA_MRSH_VERSION_SRT_WITHOUT_CONSID 0x11 + + +static int +dissect_CBA_Connection_Data(tvbuff_t *tvb, + packet_info *pinfo, proto_tree *tree, cba_ldev_t *cons_ldev, cba_frame_t *frame) +{ + guint8 u8Version; + guint8 u8Flags; + guint16 u16CountFix; + guint16 u16Count; + guint32 u32ItemIdx; + guint32 u32HoleIdx; + proto_item *conn_data_item = NULL; + proto_tree *conn_data_tree = NULL; + guint16 u16Len; + guint32 u32ID; + guint8 u8QC; + guint16 u16DataLen; + guint16 u16HdrLen; + int offset = 0; + int offset_hole; + gboolean qc_reported = FALSE; + int qc_good = 0; + int qc_uncertain = 0; + int qc_bad = 0; + GList *conns; + int item_offset; + cba_connection_t *conn; + + + /*** ALL data in this buffer is NOT aligned and always little endian ordered ***/ + + if (tree) { + conn_data_item = proto_tree_add_item(tree, hf_cba_acco_cb_conn_data, tvb, offset, 0, ENC_NA); + conn_data_tree = proto_item_add_subtree(conn_data_item, ett_ICBAAccoCallback_Buffer); + } + + /* add buffer header */ + u8Version = tvb_get_guint8 (tvb, offset); + if (conn_data_tree) { + proto_tree_add_item(conn_data_tree, hf_cba_acco_cb_version, tvb, offset, 1, ENC_LITTLE_ENDIAN); + } + offset += 1; + + u8Flags = tvb_get_guint8 (tvb, offset); + if (conn_data_tree) { + proto_tree_add_item(conn_data_tree, hf_cba_acco_cb_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); + } + offset += 1; + + u16Count = tvb_get_letohs (tvb, offset); + if (conn_data_tree) { + proto_tree_add_item(conn_data_tree, hf_cba_acco_cb_count, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } + offset += 2; + u16CountFix = u16Count; + + /* show meta information */ + if (frame) { + cba_frame_info(tvb, pinfo, conn_data_tree, frame); + } else { + if (cons_ldev && cons_ldev->name) { + proto_item *item; + item = proto_tree_add_string(conn_data_tree, hf_cba_acco_conn_consumer, tvb, offset, 0, cons_ldev->name); + proto_item_set_generated(item); + } + } + + /* update column info now */ +#if 0 + col_append_fstr(pinfo->cinfo, COL_INFO, " Cnt=%u", u16Count); +#endif + + /* is this an OnDataChanged buffer format (version), we know? */ + if ((u8Version != CBA_MRSH_VERSION_DCOM) && + (u8Version != CBA_MRSH_VERSION_SRT_WITH_CONSID) && + (u8Version != CBA_MRSH_VERSION_SRT_WITHOUT_CONSID)) + { + return offset; + } + + /* Timestamps are currently unused -> flags must be zero */ + if (u8Flags != 0) { + return offset; + } + + u32ItemIdx = 1; + u32HoleIdx = 1; + while (u16Count--) { + proto_item *sub_item; + proto_tree *sub_tree; + proto_item *item; + + /* find next record header */ + u16Len = tvb_get_letohs (tvb, offset); + + /* trapped inside an empty hole? -> try to find next record header */ + if (u16Len == 0 && + (u8Version == CBA_MRSH_VERSION_SRT_WITH_CONSID || + u8Version == CBA_MRSH_VERSION_SRT_WITHOUT_CONSID)) + { + u32HoleIdx++; + offset_hole = offset; + /* length smaller or larger than possible -> must be a hole */ + while (u16Len == 0) { + offset++; + u16Len = tvb_get_letohs(tvb, offset); + /* this is a bit tricky here! we know: */ + /* u16Len must be greater than 3 (min. size of header itself) */ + /* u16Len must be a lot smaller than 0x300 (max. size of frame) */ + /* -> if we found a length larger than 0x300, */ + /* this must be actually the high byte, so do one more step */ + if (u16Len > 0x300) { + u16Len = 0; + } + } + proto_tree_add_none_format(conn_data_tree, hf_cba_acco_cb_item_hole, tvb, + offset_hole, offset - offset_hole, + "Hole(--): -------------, offset=%2u, length=%2u", + offset_hole, offset - offset_hole); + } + + /* add callback-item subtree */ + sub_item = proto_tree_add_item(conn_data_tree, hf_cba_acco_cb_item, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_ICBAAccoCallback_Item); + + item_offset = offset; + + /* add item header fields */ + if (sub_tree) { + proto_tree_add_item(sub_tree, hf_cba_acco_cb_item_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); + } + offset += 2; + u16HdrLen = 2; + + if (u8Version == CBA_MRSH_VERSION_DCOM || + u8Version == CBA_MRSH_VERSION_SRT_WITH_CONSID) + { + u32ID = tvb_get_letohl (tvb, offset); + if (sub_tree) { + proto_tree_add_item(sub_tree, hf_cba_acco_conn_cons_id, tvb, offset, 4, ENC_LITTLE_ENDIAN); + } + offset += 4; + u16HdrLen += 4; + } else { + u32ID = 0; + } + + u8QC = tvb_get_guint8 (tvb, offset); + item = NULL; + if (sub_tree) { + item = proto_tree_add_item(sub_tree, hf_cba_acco_qc, tvb, offset, 1, ENC_LITTLE_ENDIAN); + } + offset += 1; + u16HdrLen += 1; + + if ( u8QC != 0x80 && /* GoodNonCascOk */ + u8QC != 0x1C && /* BadOutOfService (usually permanent, so don't report for every frame) */ + qc_reported == 0) { + expert_add_info_format(pinfo, item, &ei_cba_acco_qc, "%s QC: %s", + u8Version == CBA_MRSH_VERSION_DCOM ? "DCOM" : "SRT", + val_to_str(u8QC, cba_acco_qc_vals, "Unknown (0x%02x)")); + qc_reported = 0; + } + + switch(u8QC >> 6) { + case(00): + qc_bad++; + break; + case(01): + qc_uncertain++; + break; + default: + qc_good++; + } + + /* user data length is item length without headers */ + u16DataLen = u16Len - u16HdrLen; + + /* append text to subtree header */ + if (u8Version == CBA_MRSH_VERSION_DCOM || + u8Version == CBA_MRSH_VERSION_SRT_WITH_CONSID) + { + proto_item_append_text(sub_item, + "[%2u]: ConsID=0x%08x, offset=%2u, length=%2u (user-length=%2u), QC=%s (0x%02x)", + u32ItemIdx, u32ID, offset - u16HdrLen, u16Len, u16DataLen, + val_to_str(u8QC, cba_acco_qc_vals, "Unknown (0x%02x)"), u8QC ); + } else { + proto_item_append_text(sub_item, + "[%2u]: ConsID=-, offset=%2u, length=%2u (user-length=%2u), QC=%s (0x%02x)", + u32ItemIdx, offset - u16HdrLen, u16Len, u16DataLen, + val_to_str(u8QC, cba_acco_qc_vals, "Unknown (0x%02x)"), u8QC ); + } + proto_item_set_len(sub_item, u16Len); + + /* hexdump of user data */ + proto_tree_add_item(sub_tree, hf_cba_acco_cb_item_data, tvb, offset, u16DataLen, ENC_NA); + offset += u16DataLen; + + if (frame != NULL ) { + /* find offset in SRT */ + /* XXX - expensive! */ + cba_frame_incoming_data(tvb, pinfo, sub_tree, frame); + for(conns = frame->conns; conns != NULL; conns = g_list_next(conns)) { + conn = (cba_connection_t *)conns->data; + if (conn->frame_offset == item_offset) { + cba_connection_info(tvb, pinfo, sub_tree, conn); + break; + } + } + } else { + /* find consID in ldev */ + /* XXX - expensive! */ + if (cons_ldev != NULL) { + for(conns = cons_ldev->consconns; conns != NULL; conns = g_list_next(conns)) { + conn = (cba_connection_t *)conns->data; + if (conn->consid == u32ID) { + cba_connection_info(tvb, pinfo, sub_tree, conn); + cba_connection_incoming_data(tvb, pinfo, sub_tree, conn); + break; + } + } + } + } + + u32ItemIdx++; + } + + if (u8Version == 1) { + proto_item_append_text(conn_data_item, + ": Version=0x%x (DCOM), Flags=0x%x, Count=%u", + u8Version, u8Flags, u16CountFix); + } else { + proto_item_append_text(conn_data_item, + ": Version=0x%x (SRT), Flags=0x%x, Count=%u, Items=%u, Holes=%u", + u8Version, u8Flags, u16CountFix, u32ItemIdx-1, u32HoleIdx-1); + } + proto_item_set_len(conn_data_item, offset); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", QC (G:%u,U:%u,B:%u)", + qc_good, qc_uncertain, qc_bad); + + return offset; +} + + +static gboolean +dissect_CBA_Connection_Data_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + void *data) +{ + guint8 u8Version; + guint8 u8Flags; + /* the tvb will NOT contain the frame_id here! */ + guint16 u16FrameID = GPOINTER_TO_UINT(data); + cba_frame_t *frame; + + /* frame id must be in valid range (cyclic Real-Time, class=1 or class=2) */ + if (u16FrameID < 0x8000 || u16FrameID >= 0xfb00) { + return FALSE; + } + + u8Version = tvb_get_guint8 (tvb, 0); + u8Flags = tvb_get_guint8 (tvb, 1); + + /* version and flags must be ok */ + if (u8Version != 0x11 || u8Flags != 0x00) { + return FALSE; + } + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-CBA"); + + frame = cba_frame_find_by_cons(pinfo, (const guint8 *)pinfo->dl_dst.data, u16FrameID); + + dissect_CBA_Connection_Data(tvb, pinfo, tree, frame ? frame->consparent : NULL, frame); + + return TRUE; +} + + +static int +dissect_ICBAAccoCallback_OnDataChanged_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Length; + guint32 u32ArraySize; + tvbuff_t *next_tvb; + proto_item *item; + cba_ldev_t *cons_ldev; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + /* get corresponding provider ldev */ + cons_ldev = cba_ldev_find(pinfo, &pinfo->net_dst, &di->call_data->object_uuid); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(1)); + + /* length */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_cb_length, &u32Length); + + /* array size */ + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /*** the data below is NOT ndr encoded (especially NOT aligned)!!! ***/ + /* dissect PROFINET component data (without header) */ + next_tvb = tvb_new_subset_remaining(tvb, offset); + + offset += dissect_CBA_Connection_Data(next_tvb, pinfo, tree, cons_ldev, NULL /* frame */); + + return offset; +} + + +static int +dissect_ICBAAccoCallback_OnDataChanged_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + proto_item *item; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(2)); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoCallback_Gnip_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + proto_item *item; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(3)); + + return offset; +} + + +static int +dissect_ICBAAccoCallback_Gnip_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + proto_item *item; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_srt_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(4)); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoServer2_GetConnectionData_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + proto_item *item; + cba_ldev_t *cons_ldev; + cba_ldev_t **call; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, TRUE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(2)); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_consumer, szStr, u32MaxStr); + + cons_ldev = cba_acco_add(pinfo, szStr); + + /* link ldev to the call */ + if (cons_ldev != NULL) { + call = (cba_ldev_t **)wmem_alloc(wmem_file_scope(), sizeof(cba_ldev_t *)); + *call = cons_ldev; + di->call_data->private_data = call; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, " Consumer=\"%s\"", szStr); + + return offset; +} + + +static int +dissect_ICBAAccoServer2_GetConnectionData_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Length; + guint32 u32ArraySize; + tvbuff_t *next_tvb; + guint32 u32Pointer; + guint32 u32HResult; + proto_item *item; + cba_ldev_t **call = (cba_ldev_t **)di->call_data->private_data; + cba_ldev_t *cons_ldev = (call!=NULL) ? *call : NULL; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + if (cons_ldev == NULL) { + expert_add_info(pinfo, NULL, &ei_cba_acco_no_request_info); + } + + item = proto_tree_add_boolean (tree, hf_cba_acco_dcom_call, tvb, offset, 0, FALSE); + proto_item_set_generated(item); + p_add_proto_data(pinfo->pool, pinfo, proto_ICBAAccoMgt, 0, GUINT_TO_POINTER(1)); + + /* length */ + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_cb_length, &u32Length); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + /* array size */ + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + /*** the data below is NOT ndr encoded (especially NOT aligned)!!! ***/ + /* dissect PROFINET component data (without header) */ + next_tvb = tvb_new_subset_remaining(tvb, offset); + + offset += dissect_CBA_Connection_Data(next_tvb, pinfo, tree, (call != NULL) ? *call : NULL, NULL /* frame */); + + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_AddConnections_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szConsumer[1000] = { 0 }; + guint32 u32MaxConsLen = sizeof(szConsumer); + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Pointer; + guint16 u16Persistence; + gchar szConsItem[1000] = { 0 }; + guint32 u32MaxConsItemLen = sizeof(szConsItem); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + guint32 u32VariableOffset; + guint32 u32SubStart; + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_provider, szConsumer, u32MaxConsLen); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * 20; + + u32Idx = 1; + while (u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_addconnectionin, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_addconnectionin); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_consumer_item, szConsItem, u32MaxConsItemLen); + } + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_persist, &u16Persistence); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_substitute); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_epsilon); + } + proto_item_append_text(sub_item, "[%u]: ConsItem=\"%s\" ProvItem=\"%s\" %s Pers=%u", + u32Idx, szConsItem, szProvItem, + val_to_str(u16Persistence, cba_persist_vals, "Unknown (0x%02x)"), u16Persistence); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": Prov=\"%s\" State=%s Cnt=%u", + szConsumer, + val_to_str(u8State, cba_acco_conn_state_vals, "Unknown (0x%02x)"), + u32Count); + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoMgt_AddConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32ArraySize = 0; + guint32 u32ConsID; + guint16 u16ConnVersion; + guint32 u32HResult = 0; + guint32 u32Count = 0; + guint32 u32Idx; + guint32 u32SubStart; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Count = u32ArraySize; + u32Idx = 1; + while (u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_addconnectionout, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_addconnectionout); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_version, &u16ConnVersion); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x Version=%u %s", + u32Idx, u32ConsID, u16ConnVersion, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_RemoveConnections_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ConsID; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID, u32Idx); + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_SetActivationState_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint8 u8State; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ConsID; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_state, &u8State); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID, u32Idx); + u32Idx++; + } + + /* update column info now */ + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_GetInfo_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Max; + guint32 u32CurCnt; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_info_max, &u32Max); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_info_curr, &u32CurCnt); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u/%u -> %s", + u32CurCnt, u32Max, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_GetIDs_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32ConsID; + guint8 u8State; + guint16 u16Version; + guint32 u32HResult; + guint32 u32Idx; + guint32 u32SubStart; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + if (u32Count) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u ConsID=", u32Count); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_getidout, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getidout); + u32SubStart = offset; + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID); + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_state, &u8State); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_version, &u16Version); + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: ConsID=0x%x State=%s Version=%u %s", + u32Idx, u32ConsID, + val_to_str(u8State, cba_acco_conn_state_vals, "Unknown (0x%02x)"), + u16Version, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + if (u32Idx == 1) { + col_append_fstr(pinfo->cinfo, COL_INFO, "0x%x", u32ConsID); + } else if (u32Idx < 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",0x%x", u32ConsID); + } else if (u32Idx == 10) { + col_append_str(pinfo->cinfo, COL_INFO, ",..."); + } + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt2_GetConsIDs_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32Idx; + guint32 u32ConsID; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + if (u32Count) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u ConsID=", u32Count); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, + tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID, u32Idx); + + if (u32Idx == 1) { + col_append_fstr(pinfo->cinfo, COL_INFO, "0x%x", u32ConsID); + } else if (u32Idx < 10) { + col_append_fstr(pinfo->cinfo, COL_INFO, ",0x%x", u32ConsID); + } else if (u32Idx == 10) { + col_append_str(pinfo->cinfo, COL_INFO, ",..."); + } + + u32Idx++; + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt2_GetConsConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32TmpCount; + guint32 u32Pointer; + guint32 u32HResult; + + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint16 u16Persistence; + guint32 u32SubStart; + guint32 u32Idx; + guint32 u32VariableOffset; + gchar szProv[1000] = { 0 }; + guint32 u32MaxProvLen = sizeof(szProv); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + gchar szConsItem[1000] = { 0 }; + guint32 u32MaxConsItemLen = sizeof(szConsItem); + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + u32VariableOffset = offset + u32Count*32; + + /* array fixed part (including pointers to variable part) */ + u32TmpCount = u32Count; + u32Idx = 1; + while (u32TmpCount--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_getconsconnout, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getconnectionout); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider, szProv, u32MaxProvLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_consumer_item, szConsItem, u32MaxConsItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_substitute); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_epsilon); + } + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_state, &u8State); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_persist, &u16Persistence); + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: %s", + u32Idx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoMgt2_DiagConsConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32TmpCount; + guint32 u32Pointer; + guint32 u32HResult; + guint8 u8State; + guint16 u16Persistence; + guint16 u16ConnVersion; + guint32 u32SubStart; + guint32 u32Idx; + guint32 u32VariableOffset; + guint32 u32ConnErrorState; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + u32VariableOffset = offset + u32Count*16; + + /* array fixed part (including pointers to variable part) */ + u32TmpCount = u32Count; + u32Idx = 1; + while (u32TmpCount--) { + proto_item *sub_item; + proto_tree *sub_tree; + proto_item *state_item; + + sub_item = proto_tree_add_item(tree, hf_cba_diagconsconnout, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getconnectionout); + u32SubStart = offset; + + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_state, &u8State); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_persist, &u16Persistence); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_version, &u16ConnVersion); + /* connection state */ +#if 0 + offset = dissect_dcom_DWORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_error_state, &u32ConnErrorState); +#endif + offset = dissect_dcom_HRESULT_item(tvb, offset, pinfo, sub_tree, di, drep, + &u32ConnErrorState, hf_cba_acco_conn_error_state, &state_item); + proto_item_set_text(state_item, "ConnErrorState: %s (0x%x)", + val_to_str(u32ConnErrorState, dcom_hresult_vals, "Unknown (0x%08x)"), + u32ConnErrorState); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: %s", + u32Idx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoMgt_GetConnections_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32ConsID; + guint32 u32Count; + guint32 u32ArraySize; + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32Idx = 1; + while (u32ArraySize--){ + offset = dissect_dcom_indexed_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_cons_id, &u32ConsID, u32Idx); + u32Idx++; + } + + return offset; +} + + +static int +dissect_ICBAAccoMgt_GetConnections_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32TmpCount; + guint32 u32Pointer; + guint32 u32HResult; + + guint16 u16QoSType; + guint16 u16QoSValue; + guint8 u8State; + guint16 u16Persistence; + guint16 u16ConnVersion; + guint32 u32SubStart; + guint32 u32Idx; + guint32 u32VariableOffset; + gchar szProv[1000] = { 0 }; + guint32 u32MaxProvLen = sizeof(szProv); + gchar szProvItem[1000] = { 0 }; + guint32 u32MaxProvItemLen = sizeof(szProvItem); + gchar szConsItem[1000] = { 0 }; + guint32 u32MaxConsItemLen = sizeof(szConsItem); + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + u32VariableOffset = offset + u32Count*36; + + /* array fixed part (including pointers to variable part) */ + u32TmpCount = u32Count; + u32Idx = 1; + while (u32TmpCount--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_getconnectionout, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_getconnectionout); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider, szProv, u32MaxProvLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_provider_item, szProvItem, u32MaxProvItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_consumer_item, szConsItem, u32MaxConsItemLen); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_substitute); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_epsilon); + } + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + offset = dissect_dcom_BOOLEAN(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_state, &u8State); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_persist, &u16Persistence); + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_conn_version, &u16ConnVersion); + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: %s", + u32Idx, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoMgt_ReviseQoS_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16QoSType; + guint16 u16QoSValue; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_LPWSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_rtauto, szStr, u32MaxStr); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_type, &u16QoSType); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": RTAuto=\"%s\" QoSType=%s QoSValue=%u", + szStr, + val_to_str(u16QoSType, cba_qos_type_vals, "Unknown (0x%04x)"), + u16QoSValue); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_ReviseQoS_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16QoSValue; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_conn_qos_value, &u16QoSValue); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u -> %s", + u16QoSValue, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_get_PingFactor_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16PF; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_ping_factor, &u16PF); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u -> %s", + u16PF, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_put_PingFactor_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16PF; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_ping_factor, &u16PF); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u", u16PF); + + return offset; +} + + + +static int +dissect_ICBAAccoMgt_get_CDBCookie_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Cookie; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_cdb_cookie, &u32Cookie); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": CDBCookie=0x%x -> %s", + u32Cookie, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_GetDiagnosis_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Request; + guint32 u32InLength; + guint32 u32ArraySize; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_diag_req, &u32Request); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_diag_in_length, &u32InLength); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + if (u32ArraySize != 0) { + proto_tree_add_item(tree, hf_cba_acco_diag_data, tvb, offset, u32InLength, ENC_NA); + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %s: %u bytes", + val_to_str(u32Request, cba_acco_diag_req_vals, "Unknown request (0x%08x)"), + u32InLength); + + return offset; +} + + +static int +dissect_ICBAAccoMgt_GetDiagnosis_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32OutLength; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_diag_out_length, &u32OutLength); + + if (u32OutLength != 0) { + proto_tree_add_item(tree, hf_cba_acco_diag_data, tvb, offset, u32OutLength, ENC_NA); + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u bytes", + u32OutLength); + + return offset; +} + + +static int +dissect_ICBAAccoSync_ReadItems_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32ArraySize; + guint32 u32VariableOffset; + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize*4; + + u32Idx = 1; + while (u32ArraySize--) { + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_indexed_LPWSTR(tvb, u32VariableOffset, pinfo, tree, di, drep, + hf_cba_acco_item, szStr, u32MaxStr, u32Idx); + } + + u32Idx++; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return u32VariableOffset; +} + + + + +static int +dissect_ICBAAccoSync_ReadItems_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + guint16 u16QC; + guint32 u32ArraySize = 0; + guint32 u32HResult; + guint32 u32Idx; + guint32 u32SubStart; + guint32 u32VariableOffset; + guint32 u32Tmp; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + u32VariableOffset = offset; + + if (u32Pointer) { + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * 20; + u32Idx = 1; + u32Tmp = u32ArraySize; + while(u32Tmp--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_readitemout, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_readitemout); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, hf_cba_acco_data); + } + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_qc, &u16QC); + offset = dissect_dcom_FILETIME(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_time_stamp, NULL); + + offset = dissect_dcom_indexed_HRESULT(tvb, offset, pinfo, sub_tree, di, drep, + &u32HResult, u32Idx); + + proto_item_append_text(sub_item, "[%u]: QC=%s (0x%02x) %s", + u32Idx, + val_to_str_const(u16QC, cba_acco_qc_vals, "Unknown"), + u16QC, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + } + + u32VariableOffset = dissect_dcom_HRESULT(tvb, u32VariableOffset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u -> %s", + u32ArraySize, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return u32VariableOffset; +} + + +static int +dissect_ICBAAccoSync_WriteItems_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32VariableOffset; + guint32 u32SubStart; + guint32 u32Idx; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * 8; + u32Idx = 1; + while(u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_writeitemin, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_writeitemin); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_item, szStr, u32MaxStr); + } + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_data); + } + + proto_item_append_text(sub_item, "[%u]: Item=\"%s\"", u32Idx, szStr); + proto_item_set_len(sub_item, offset - u32SubStart); + + u32Idx++; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return u32VariableOffset; +} + + + +static int +dissect_ICBAAccoSync_WriteItemsQCD_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32ArraySize; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32VariableOffset; + guint32 u32SubStart; + guint32 u32Idx; + guint16 u16QC; + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_acco_count, &u32Count); + + offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep, + &u32ArraySize); + + u32VariableOffset = offset + u32ArraySize * 20; + u32Idx = 1; + while(u32ArraySize--) { + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_cba_writeitemin, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_cba_writeitemin); + u32SubStart = offset; + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_LPWSTR(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_item, szStr, u32MaxStr); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep, + &u32Pointer); + if (u32Pointer) { + u32VariableOffset = dissect_dcom_VARIANT(tvb, u32VariableOffset, pinfo, sub_tree, di, drep, + hf_cba_acco_data); + } + + offset = dissect_dcom_WORD(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_qc, &u16QC); + + offset = dissect_dcom_FILETIME(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_acco_time_stamp, NULL); + + proto_item_append_text(sub_item, "[%u]: Item=\"%s\" QC=%s (0x%02x)", + u32Idx, szStr, + val_to_str_const(u16QC, cba_acco_qc_vals, "Unknown"), u16QC); + + proto_item_set_len(sub_item, offset - u32SubStart); + u32Idx++; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cnt=%u", u32Count); + + return u32VariableOffset; +} + + +/* sub dissector table of ICBAAccoMgt / ICBAAccoMgt2 interface */ +static dcerpc_sub_dissector ICBAAccoMgt_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "AddConnections", dissect_ICBAAccoMgt_AddConnections_rqst, dissect_ICBAAccoMgt_AddConnections_resp }, + { 4, "RemoveConnections", dissect_ICBAAccoMgt_RemoveConnections_rqst, dissect_HResultArray_resp }, + { 5, "ClearConnections", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + { 6, "SetActivationState", dissect_ICBAAccoMgt_SetActivationState_rqst, dissect_HResultArray_resp }, + { 7, "GetInfo", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt_GetInfo_resp }, + { 8, "GetIDs", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt_GetIDs_resp }, + { 9, "GetConnections", dissect_ICBAAccoMgt_GetConnections_rqst, dissect_ICBAAccoMgt_GetConnections_resp }, + {10, "ReviseQoS", dissect_ICBAAccoMgt_ReviseQoS_rqst, dissect_ICBAAccoMgt_ReviseQoS_resp }, + {11, "get_PingFactor", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt_get_PingFactor_resp }, + {12, "put_PingFactor", dissect_ICBAAccoMgt_put_PingFactor_rqst, dissect_dcom_simple_resp }, + {13, "get_CDBCookie", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt_get_CDBCookie_resp }, + /* stage 2 */ + {14, "GetConsIDs", dissect_dcom_simple_rqst, dissect_ICBAAccoMgt2_GetConsIDs_resp }, + {15, "GetConsConnections", dissect_ICBAAccoMgt_GetConnections_rqst, dissect_ICBAAccoMgt2_GetConsConnections_resp }, + {16, "DiagConsConnections", dissect_ICBAAccoMgt_GetConnections_rqst, dissect_ICBAAccoMgt2_DiagConsConnections_resp }, + {17, "GetProvIDs", dissect_dcom_simple_rqst, dissect_Server_GetProvIDs_resp }, + {18, "GetProvConnections", dissect_Server_GetProvConnections_rqst, dissect_Server_GetProvConnections_resp }, + {19, "GetDiagnosis", dissect_ICBAAccoMgt_GetDiagnosis_rqst, dissect_ICBAAccoMgt_GetDiagnosis_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAAccoCallback interface */ +static dcerpc_sub_dissector ICBAAccoCallback_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "OnDataChanged", dissect_ICBAAccoCallback_OnDataChanged_rqst, dissect_ICBAAccoCallback_OnDataChanged_resp }, + /* stage 2 */ + { 4, "Gnip", dissect_ICBAAccoCallback_Gnip_rqst, dissect_ICBAAccoCallback_Gnip_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAAccoServer interface */ +static dcerpc_sub_dissector ICBAAccoServer_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "Connect", dissect_ICBAAccoServer_Connect_rqst, dissect_ICBAAccoServer_Connect_resp }, + { 4, "Disconnect", dissect_ICBAAccoServer_Disconnect_rqst, dissect_ICBAAccoServer_Disconnect_resp }, + { 5, "DisconnectMe", dissect_ICBAAccoServer_DisconnectMe_rqst, dissect_ICBAAccoServer_DisconnectMe_resp }, + { 6, "SetActivation", dissect_ICBAAccoServer_SetActivation_rqst, dissect_ICBAAccoServer_SetActivation_resp }, + { 7, "Ping", dissect_ICBAAccoServer_Ping_rqst, dissect_ICBAAccoServer_Ping_resp }, + /* stage 2 */ + { 8, "Connect2", dissect_ICBAAccoServer2_Connect2_rqst, dissect_ICBAAccoServer_Connect_resp }, + { 9, "GetConnectionData", dissect_ICBAAccoServer2_GetConnectionData_rqst, dissect_ICBAAccoServer2_GetConnectionData_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAAccoServerSRT interface (stage 2 only) */ +static dcerpc_sub_dissector ICBAAccoServerSRT_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "ConnectCR", dissect_ICBAAccoServerSRT_ConnectCR_rqst, dissect_ICBAAccoServerSRT_ConnectCR_resp }, + { 4, "DisconnectCR", dissect_ICBAAccoServerSRT_DisconnectCR_rqst, dissect_ICBAAccoServerSRT_DisconnectCR_resp }, + { 5, "Connect", dissect_ICBAAccoServerSRT_Connect_rqst, dissect_ICBAAccoServerSRT_Connect_resp }, + { 6, "Disconnect", dissect_ICBAAccoServerSRT_Disconnect_rqst, dissect_ICBAAccoServerSRT_Disconnect_resp }, + { 7, "DisconnectMe", dissect_ICBAAccoServerSRT_DisconnectMe_rqst, dissect_ICBAAccoServerSRT_DisconnectMe_resp }, + { 8, "SetActivation", dissect_ICBAAccoServerSRT_SetActivation_rqst, dissect_ICBAAccoServerSRT_SetActivation_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAAccoSync interface */ +static dcerpc_sub_dissector ICBAAccoSync_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "ReadItems", dissect_ICBAAccoSync_ReadItems_rqst, dissect_ICBAAccoSync_ReadItems_resp }, + { 4, "WriteItems", dissect_ICBAAccoSync_WriteItems_rqst, dissect_HResultArray_resp }, + { 5, "WriteItemsQCD", dissect_ICBAAccoSync_WriteItemsQCD_rqst, dissect_HResultArray_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* register protocol */ +void +proto_register_dcom_cba_acco (void) +{ + static gint *ett3[3]; + static gint *ett4[4]; + static gint *ett5[5]; + + + static hf_register_info hf_cba_acco_array[] = { + { &hf_cba_acco_opnum, + { "Operation", "cba.acco.opnum", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_ping_factor, + { "PingFactor", "cba.acco.ping_factor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_count, + { "Count", "cba.acco.count", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_info_max, + { "Max", "cba.acco.info_max", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_info_curr, + { "Current", "cba.acco.info_curr", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_rtauto, + { "RTAuto", "cba.acco.rtauto", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_item, + { "Item", "cba.acco.item", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_data, + { "Data", "cba.acco.data", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_qc, + { "QualityCode", "cba.acco.qc", + FT_UINT8, BASE_HEX, VALS(cba_acco_qc_vals), 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_time_stamp, + { "TimeStamp", "cba.acco.time_stamp", + FT_UINT64, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_readitemout, + { "ReadItemOut", "cba.acco.readitemout", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_writeitemin, + { "WriteItemIn", "cba.acco.writeitemin", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cdb_cookie, + { "CDBCookie", "cba.acco.cdb_cookie", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + /* dcom_hresult_vals from packet-dcom.h doesn't work here, as length is unknown! */ + { &hf_cba_acco_conn_error_state, + { "ConnErrorState", "cba.acco.conn_error_state", + FT_UINT32, BASE_HEX, NULL /*VALS(dcom_hresult_vals)*/, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_diag_req, + { "Request", "cba.acco.diag_req", + FT_UINT32, BASE_HEX, VALS(cba_acco_diag_req_vals), 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_diag_in_length, + { "InLength", "cba.acco.diag_in_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_diag_out_length, + { "OutLength", "cba.acco.diag_out_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_diag_data, + { "Data", "cba.acco.diag_data", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_dcom_call, + { "DcomRuntime", "cba.acco.dcom", + FT_BOOLEAN, BASE_NONE, TFS(&cba_acco_call_flags), 0x0, + "This is a DCOM runtime context", HFILL } + }, + { &hf_cba_acco_srt_call, + { "SrtRuntime", "cba.acco.srt", + FT_BOOLEAN, BASE_NONE, TFS(&cba_acco_call_flags), 0x0, + "This is an SRT runtime context", HFILL } + } + + }; + + static hf_register_info hf_cba_acco_server[] = { +#if 0 + { &hf_cba_acco_server_pICBAAccoCallback, + { "pICBAAccoCallback", "cba.acco.server_pICBAAccoCallback", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, +#endif + { &hf_cba_acco_server_first_connect, + { "FirstConnect", "cba.acco.server_first_connect", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_getprovconnout, + { "GETPROVCONNOUT", "cba.acco.getprovconnout", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_serversrt_prov_mac, + { "ProviderMAC", "cba.acco.serversrt_prov_mac", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_serversrt_cons_mac, + { "ConsumerMAC", "cba.acco.serversrt_cons_mac", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_serversrt_cr_id, + { "ConsumerCRID", "cba.acco.serversrt_cr_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_serversrt_cr_length, + { "CRLength", "cba.acco.serversrt_cr_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_serversrt_cr_flags, + { "Flags", "cba.acco.serversrt_cr_flags", + FT_UINT32, BASE_HEX, 0, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_serversrt_cr_flags_timestamped, + { "Timestamped", "cba.acco.serversrt_cr_flags_timestamped", + FT_BOOLEAN, 32, TFS (&acco_flags_set_truth), 0x1, + NULL, HFILL } + }, + { &hf_cba_acco_serversrt_cr_flags_reconfigure, + { "Reconfigure", "cba.acco.serversrt_cr_flags_reconfigure", + FT_BOOLEAN, 32, TFS (&acco_flags_set_truth), 0x2, + NULL, HFILL } + }, + { &hf_cba_type_desc_len, + { "TypeDescLen", "cba.acco.type_desc_len", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_serversrt_record_length, + { "RecordLength", "cba.acco.serversrt_record_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, +#if 0 + { &hf_cba_acco_serversrt_action, + { "Action", "cba.acco.serversrt_action", + FT_UINT32, BASE_DEC, VALS(cba_acco_serversrt_action_vals), 0x0, + NULL, HFILL } + }, +#endif + { &hf_cba_acco_serversrt_last_connect, + { "LastConnect", "cba.acco.serversrt_last_connect", + FT_UINT8, BASE_DEC, VALS(cba_acco_serversrt_last_connect_vals), 0x0, + NULL, HFILL } + }, + }; + + static hf_register_info hf_cba_connectcr_array[] = { + { &hf_cba_acco_prov_crid, + { "ProviderCRID", "cba.acco.prov_crid", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + }; + + static hf_register_info hf_cba_connect_array[] = { + { &hf_cba_addconnectionin, + { "ADDCONNECTIONIN", "cba.acco.addconnectionin", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_addconnectionout, + { "ADDCONNECTIONOUT", "cba.acco.addconnectionout", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_getidout, + { "GETIDOUT", "cba.acco.getidout", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_getconnectionout, + { "GETCONNECTIONOUT", "cba.acco.getconnectionout", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_getconsconnout, + { "GETCONSCONNOUT", "cba.acco.getconsconnout", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_diagconsconnout, + { "DIAGCONSCONNOUT", "cba.acco.diagconsconnout", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_connectincr, + { "CONNECTINCR", "cba.acco.connectincr", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_connectoutcr, + { "CONNECTOUTCR", "cba.acco.connectoutcr", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_connectin, + { "CONNECTIN", "cba.acco.connectin", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_connectout, + { "CONNECTOUT", "cba.acco.connectout", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_prov_id, + { "ProviderID", "cba.acco.conn_prov_id", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_cons_id, + { "ConsumerID", "cba.acco.conn_cons_id", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_version, + { "ConnVersion", "cba.acco.conn_version", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_consumer, + { "Consumer", "cba.acco.conn_consumer", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_qos_type, + { "QoSType", "cba.acco.conn_qos_type", + FT_UINT16, BASE_HEX, VALS(cba_qos_type_vals), 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_qos_value, + { "QoSValue", "cba.acco.conn_qos_value", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_state, + { "State", "cba.acco.conn_state", + FT_UINT8, BASE_HEX, VALS(cba_acco_conn_state_vals), 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_provider, + { "Provider", "cba.acco.conn_provider", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_provider_item, + { "ProviderItem", "cba.acco.conn_provider_item", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_consumer_item, + { "ConsumerItem", "cba.acco.conn_consumer_item", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_persist, + { "Persistence", "cba.acco.conn_persist", + FT_UINT16, BASE_HEX, VALS(cba_persist_vals), 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_epsilon, + { "Epsilon", "cba.acco.conn_epsilon", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_conn_substitute, + { "Substitute", "cba.acco.conn_substitute", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + }; + + static hf_register_info hf_cba_acco_cb[] = { + { &hf_cba_acco_cb_length, + { "Length", "cba.acco.cb_length", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cb_version, + { "Version", "cba.acco.cb_version", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cb_flags, + { "Flags", "cba.acco.cb_flags", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cb_count, + { "Count", "cba.acco.cb_count", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cb_conn_data, + { "CBA Connection data", "cba.acco.cb_conn_data", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cb_item, + { "Item", "cba.acco.cb_item", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cb_item_hole, + { "Hole", "cba.acco.cb_item_hole", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cb_item_length, + { "Length", "cba.acco.cb_item_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_acco_cb_item_data, + { "Data(Hex)", "cba.acco.cb_item_data", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_cba_connect_in, + { "Connect in frame", "cba.connect_in", + FT_FRAMENUM, BASE_NONE, NULL, 0, + "This connection Connect was in the packet with this number", HFILL } + }, + { &hf_cba_disconnect_in, + { "Disconnect in frame", "cba.disconnect_in", + FT_FRAMENUM, BASE_NONE, NULL, 0, + "This connection Disconnect was in the packet with this number", HFILL } + }, + { &hf_cba_connectcr_in, + { "ConnectCR in frame", "cba.connect_in", + FT_FRAMENUM, BASE_NONE, NULL, 0, + "This frame ConnectCR was in the packet with this number", HFILL } + }, + { &hf_cba_disconnectcr_in, + { "DisconnectCR in frame", "cba.disconnect_in", + FT_FRAMENUM, BASE_NONE, NULL, 0, + "This frame DisconnectCR was in the packet with this number", HFILL } + }, + { &hf_cba_disconnectme_in, + { "DisconnectMe in frame", "cba.disconnectme_in", + FT_FRAMENUM, BASE_NONE, NULL, 0, + "This connection/frame DisconnectMe was in the packet with this number", HFILL } + }, + { &hf_cba_data_first_in, + { "First data in frame", "cba.data_first_in", + FT_FRAMENUM, BASE_NONE, NULL, 0, + "The first data of this connection/frame in the packet with this number", HFILL } + }, + { &hf_cba_data_last_in, + { "Last data in frame", "cba.data_last_in", + FT_FRAMENUM, BASE_NONE, NULL, 0, + "The last data of this connection/frame in the packet with this number", HFILL } + }, + }; + + static ei_register_info ei[] = { + { &ei_cba_acco_pdev_find, { "cba.acco.pdev_find.fail", PI_UNDECODED, PI_NOTE, "pdev_find: no pdev for IP", EXPFILL }}, + { &ei_cba_acco_pdev_find_unknown_interface, { "cba.acco.pdev_find.unknown_interface", PI_UNDECODED, PI_NOTE, "pdev_find: unknown interface", EXPFILL }}, + { &ei_cba_acco_ldev_unknown, { "cba.acco.ldev.unknown", PI_UNDECODED, PI_NOTE, "Unknown LDev", EXPFILL }}, + { &ei_cba_acco_ipid_unknown, { "cba.acco.ipid.unknown", PI_UNDECODED, PI_NOTE, "Unknown IPID", EXPFILL }}, + { &ei_cba_acco_prov_crid, { "cba.acco.prov_crid.unknown", PI_UNDECODED, PI_NOTE, "Unknown provider frame ProvCRID", EXPFILL }}, + { &ei_cba_acco_conn_consumer, { "cba.acco.conn_consumer.invalid", PI_UNDECODED, PI_NOTE, "Consumer interface invalid", EXPFILL }}, + { &ei_cba_acco_no_request_info, { "cba.acco.no_request_info", PI_UNDECODED, PI_NOTE, "No request info, response data ignored", EXPFILL }}, + { &ei_cba_acco_qc, { "cba.acco.qc.expert", PI_RESPONSE_CODE, PI_CHAT, "expert QC", EXPFILL }}, + { &ei_cba_acco_disconnect, { "cba.acco.disconnect", PI_SEQUENCE, PI_NOTE, "Disconnection sequence issue", EXPFILL }}, + { &ei_cba_acco_connect, { "cba.acco.connect_not_set", PI_SEQUENCE, PI_NOTE, "packet_connect not set", EXPFILL }}, + }; + + expert_module_t* expert_cba_acco; + + ett5[0] = &ett_ICBAAccoMgt; + ett5[1] = &ett_cba_addconnectionin; + ett5[2] = &ett_cba_addconnectionout; + ett5[3] = &ett_cba_getidout; + ett5[4] = &ett_cba_getconnectionout; + proto_ICBAAccoMgt = proto_register_protocol ("ICBAAccoMgt", "ICBAAccoMgt", "cba_acco_mgt"); + proto_register_field_array(proto_ICBAAccoMgt, hf_cba_acco_array, array_length(hf_cba_acco_array)); + proto_register_field_array(proto_ICBAAccoMgt, hf_cba_connect_array, array_length(hf_cba_connect_array)); + proto_register_field_array(proto_ICBAAccoMgt, hf_cba_connectcr_array, array_length(hf_cba_connectcr_array)); + proto_register_subtree_array (ett5, array_length (ett5)); + + /* XXX - just pick a protocol to register the expert info in */ + /* XXX - also, just pick a protocol to use proto_data for */ + expert_cba_acco = expert_register_protocol(proto_ICBAAccoMgt); + expert_register_field_array(expert_cba_acco, ei, array_length(ei)); + + proto_ICBAAccoMgt2 = proto_register_protocol ("ICBAAccoMgt2", "ICBAAccoMgt2", "cba_acco_mgt2"); + + ett3[0] = &ett_ICBAAccoCallback; + ett3[1] = &ett_ICBAAccoCallback_Item; + ett3[2] = &ett_ICBAAccoCallback_Buffer; + proto_ICBAAccoCallback = proto_register_protocol ("ICBAAccoCallback", "ICBAAccoCB", "cba_acco_cb"); + proto_register_field_array(proto_ICBAAccoCallback, hf_cba_acco_cb, array_length(hf_cba_acco_cb)); + proto_register_subtree_array (ett3, array_length (ett3)); + + proto_ICBAAccoCallback2 = proto_register_protocol ("ICBAAccoCallback2", "ICBAAccoCB2", "cba_acco_cb2"); + + ett4[0] = &ett_ICBAAccoServer; + ett4[1] = &ett_cba_connectin; + ett4[2] = &ett_cba_connectout; + ett4[3] = &ett_cba_getprovconnout; + proto_ICBAAccoServer = proto_register_protocol ("ICBAAccoServer", "ICBAAccoServ", "cba_acco_server"); + proto_register_field_array(proto_ICBAAccoServer, hf_cba_acco_server, array_length(hf_cba_acco_server)); + proto_register_subtree_array (ett4, array_length (ett4)); + + proto_ICBAAccoServer2 = proto_register_protocol ("ICBAAccoServer2", "ICBAAccoServ2", "cba_acco_server2"); + + ett4[0] = &ett_ICBAAccoServerSRT; + ett4[1] = &ett_cba_acco_serversrt_cr_flags; + ett4[2] = &ett_cba_connectincr; + ett4[3] = &ett_cba_connectoutcr; + proto_ICBAAccoServerSRT = proto_register_protocol ("ICBAAccoServerSRT", "ICBAAccoServSRT", "cba_acco_server_srt"); + proto_register_subtree_array (ett4, array_length (ett4)); + + ett5[0] = &ett_ICBAAccoSync; + ett5[1] = &ett_cba_readitemout; + ett5[2] = &ett_cba_writeitemin; + ett5[3] = &ett_cba_frame_info; + ett5[4] = &ett_cba_conn_info; + proto_ICBAAccoSync = proto_register_protocol ("ICBAAccoSync", "ICBAAccoSync", "cba_acco_sync"); + proto_register_subtree_array (ett5, array_length (ett5)); + + register_conversation_filter("cba", "PN-CBA", cba_filter_valid, cba_build_filter, NULL); +} + + +/* handoff protocol */ +void +proto_reg_handoff_dcom_cba_acco (void) +{ + /* Register the interfaces */ + dcerpc_init_uuid(proto_ICBAAccoMgt, ett_ICBAAccoMgt, + &uuid_ICBAAccoMgt, ver_ICBAAccoMgt, ICBAAccoMgt_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoMgt2, ett_ICBAAccoMgt, + &uuid_ICBAAccoMgt2, ver_ICBAAccoMgt2, ICBAAccoMgt_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoCallback, ett_ICBAAccoCallback, + &uuid_ICBAAccoCallback, ver_ICBAAccoCallback, ICBAAccoCallback_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoCallback2, ett_ICBAAccoCallback, + &uuid_ICBAAccoCallback2, ver_ICBAAccoCallback2, ICBAAccoCallback_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoServer, ett_ICBAAccoServer, + &uuid_ICBAAccoServer, ver_ICBAAccoServer, ICBAAccoServer_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoServer2, ett_ICBAAccoServer, + &uuid_ICBAAccoServer2, ver_ICBAAccoServer2, ICBAAccoServer_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoServerSRT, ett_ICBAAccoServerSRT, + &uuid_ICBAAccoServerSRT, ver_ICBAAccoServerSRT, ICBAAccoServerSRT_dissectors, hf_cba_acco_opnum); + + dcerpc_init_uuid(proto_ICBAAccoSync, ett_ICBAAccoSync, + &uuid_ICBAAccoSync, ver_ICBAAccoSync, ICBAAccoSync_dissectors, hf_cba_acco_opnum); + + + heur_dissector_add("pn_rt", dissect_CBA_Connection_Data_heur, "PROFINET CBA IO", "pn_cba_pn_rt", proto_ICBAAccoServer, HEURISTIC_ENABLE); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-dcom-cba-acco.h b/plugins/epan/profinet/packet-dcom-cba-acco.h new file mode 100644 index 00000000..31711244 --- /dev/null +++ b/plugins/epan/profinet/packet-dcom-cba-acco.h @@ -0,0 +1,59 @@ +/* packet-dcom-cba-acco.h + * Routines for DCOM CBA + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __PACKET_DCERPC_DCOM_CBA_ACCO_H +#define __PACKET_DCERPC_DCOM_CBA_ACCO_H + +typedef struct cba_pdev_s { + GList *ldevs; + dcom_object_t *object; + gint first_packet; + + guint8 ip[4]; +} cba_pdev_t; + +typedef struct cba_ldev_s { + GList *provframes; + GList *consframes; + GList *provconns; + GList *consconns; + dcom_object_t *ldev_object; + dcom_object_t *acco_object; + cba_pdev_t *parent; + gint first_packet; + + const char *name; +} cba_ldev_t; + + +extern GList *cba_pdevs; + +extern cba_pdev_t * +cba_pdev_find(packet_info *pinfo, const address *addr, e_guid_t *ipid); + +extern void +cba_pdev_link(packet_info *pinfo, cba_pdev_t *pdev, dcom_interface_t *pdev_interf); + +extern cba_pdev_t * +cba_pdev_add(packet_info *pinfo, const address *addr); + +extern void +cba_ldev_link(packet_info *pinfo, cba_ldev_t *ldev, dcom_interface_t *ldev_interf); + +extern void +cba_ldev_link_acco(packet_info *pinfo, cba_ldev_t *ldev, dcom_interface_t *acco_interf); + +extern cba_ldev_t * +cba_ldev_find(packet_info *pinfo, const address *addr, e_guid_t *ipid); + +extern cba_ldev_t * +cba_ldev_add(packet_info *pinfo, cba_pdev_t *pdev, const char *name); + +#endif /* packet-dcerpc-dcom-cba-acco.h */ diff --git a/plugins/epan/profinet/packet-dcom-cba.c b/plugins/epan/profinet/packet-dcom-cba.c new file mode 100644 index 00000000..52c5017e --- /dev/null +++ b/plugins/epan/profinet/packet-dcom-cba.c @@ -0,0 +1,1730 @@ +/* packet-dcom-cba.c + * Routines for DCOM CBA + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include "packet-dcom-cba-acco.h" + +void proto_register_dcom_cba(void); +void proto_reg_handoff_dcom_cba(void); + +static int hf_cba_opnum = -1; + +static int hf_cba_revision_major = -1; +static int hf_cba_revision_minor = -1; +static int hf_cba_revision_service_pack = -1; +static int hf_cba_revision_build = -1; + +static int hf_cba_time = -1; + +static int hf_cba_name = -1; +static int hf_cba_producer = -1; +static int hf_cba_product = -1; +static int hf_cba_production_date = -1; +static int hf_cba_serial_no = -1; +static int hf_cba_multi_app = -1; +static int hf_cba_profinet_dcom_stack = -1; +static int hf_cba_pdev_stamp = -1; + +static int hf_cba_browse_count = -1; +static int hf_cba_browse_offset = -1; +static int hf_cba_browse_max_return = -1; +static int hf_cba_browse_item = -1; +static int hf_cba_browse_data_type = -1; +static int hf_cba_browse_access_right = -1; +static int hf_cba_browse_selector = -1; +static int hf_cba_browse_info1 = -1; +static int hf_cba_browse_info2 = -1; + +static int hf_cba_cookie = -1; +static int hf_cba_state = -1; +static int hf_cba_new_state = -1; +static int hf_cba_old_state = -1; +static int hf_cba_grouperror = -1; +static int hf_cba_new_grouperror = -1; +static int hf_cba_old_grouperror = -1; + +static int hf_cba_component_id = -1; +static int hf_cba_component_version = -1; +static int hf_cba_pbaddress = -1; +static int hf_cba_pbaddress_system_id = -1; +static int hf_cba_pbaddress_address = -1; + +static int hf_cba_save_ldev_name = -1; +static int hf_cba_save_result = -1; + +static expert_field ei_cba_acco_interface_pointer_unresolved = EI_INIT; + +static e_guid_t uuid_coclass_CBAPhysicalDevice = { 0xcba00000, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; + + +/* CBA interfaces */ +static int proto_ICBAPhysicalDevice = -1; +static gint ett_ICBAPhysicalDevice = -1; +static e_guid_t uuid_ICBAPhysicalDevice = { 0xcba00001, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPhysicalDevice = 0; + +static int proto_ICBAPhysicalDevice2 = -1; +static e_guid_t uuid_ICBAPhysicalDevice2 = { 0xcba00006, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPhysicalDevice2 = 0; + +static int proto_ICBABrowse = -1; +static gint ett_ICBABrowse = -1; +static e_guid_t uuid_ICBABrowse = { 0xcba00002, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBABrowse = 0; + +static int proto_ICBABrowse2 = -1; +static e_guid_t uuid_ICBABrowse2 = { 0xcba00007, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBABrowse2 = 0; + +static int proto_ICBAPhysicalDevicePC = -1; +static gint ett_ICBAPhysicalDevicePC = -1; +static e_guid_t uuid_ICBAPhysicalDevicePC = { 0xcba00003, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPhysicalDevicePC = 0; + +static int proto_ICBAPhysicalDevicePCEvent = -1; +static gint ett_ICBAPhysicalDevicePCEvent = -1; +static e_guid_t uuid_ICBAPhysicalDevicePCEvent = { 0xcba00004, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPhysicalDevicePCEvent = 0; + +static int proto_ICBAPersist = -1; +static gint ett_ICBAPersist = -1; +static e_guid_t uuid_ICBAPersist = { 0xcba00005, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPersist = 0; + +static int proto_ICBAPersist2 = -1; +static e_guid_t uuid_ICBAPersist2 = { 0xcba00008, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAPersist2 = 0; + +static int proto_ICBALogicalDevice = -1; +static gint ett_ICBALogicalDevice = -1; +static e_guid_t uuid_ICBALogicalDevice = { 0xcba00011, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBALogicalDevice = 0; + +static int proto_ICBALogicalDevice2 = -1; +static e_guid_t uuid_ICBALogicalDevice2 = { 0xcba00017, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBALogicalDevice2 = 0; + +static int proto_ICBAState = -1; +static gint ett_ICBAState = -1; +static e_guid_t uuid_ICBAState = { 0xcba00012, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAState = 0; + +static int proto_ICBAStateEvent = -1; +static gint ett_ICBAStateEvent = -1; +static e_guid_t uuid_ICBAStateEvent = { 0xcba00013, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAStateEvent = 0; + +static int proto_ICBATime = -1; +static gint ett_ICBATime = -1; +static e_guid_t uuid_ICBATime = { 0xcba00014, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBATime = 0; + +static int proto_ICBAGroupError = -1; +static gint ett_ICBAGroupError = -1; +static e_guid_t uuid_ICBAGroupError = { 0xcba00015, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAGroupError = 0; + +static int proto_ICBAGroupErrorEvent = -1; +static gint ett_ICBAGroupErrorEvent = -1; +static e_guid_t uuid_ICBAGroupErrorEvent = { 0xcba00016, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBAGroupErrorEvent = 0; + +static int proto_ICBARTAuto = -1; +static gint ett_ICBARTAuto = -1; +static e_guid_t uuid_ICBARTAuto = { 0xcba00051, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBARTAuto = 0; + +static int proto_ICBARTAuto2 = -1; +static e_guid_t uuid_ICBARTAuto2 = { 0xcba00052, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBARTAuto2 = 0; + +static int proto_ICBASystemProperties = -1; +static gint ett_ICBASystemProperties = -1; +static e_guid_t uuid_ICBASystemProperties = { 0xcba00062, 0x6c97, 0x11d1, { 0x82, 0x71, 0x00, 0xa0, 0x24, 0x42, 0xdf, 0x7d } }; +static guint16 ver_ICBASystemProperties = 0; + + +static gint ett_PBAddress = -1; + + +static const value_string cba_state_vals[] = { + { 0x00, "NonExistent" }, + { 0x01, "Initializing" }, + { 0x02, "Ready" }, + { 0x03, "Operating" }, + { 0x04, "Defect" }, + { 0, NULL } +}; + + +static const value_string cba_grouperror_vals[] = { + { 0x00, "NonAccessible" }, + { 0x01, "Okay" }, + { 0x02, "Problem" }, + { 0x03, "Unknown" }, + { 0x04, "MaintenanceRequired" }, + { 0x05, "MaintenanceDemanded" }, + { 0x06, "MaintenanceRequiredAndDemanded" }, + { 0x07, "ProblemAndMaintenanceRequired" }, + { 0x08, "ProblemAndMaintenanceDemanded" }, + { 0x09, "ProblemAndMaintenanceRequiredAndDemanded" }, + { 0, NULL } +}; + +static const value_string dcom_boolean_vals[] = { + { 0x00, "FALSE" }, + { 0x01, "TRUE" }, + { 0xffff, "TRUE" }, + { 0, NULL } +}; + + + + +static int +dissect_ICBABrowse_get_Count_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Count; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_browse_count, &u32Count); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + if (u32HResult) { /* !S_OK */ + col_append_fstr(pinfo->cinfo, COL_INFO, "-> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + } else { + col_append_fstr(pinfo->cinfo, COL_INFO, " Cnt=%u -> S_OK", u32Count); + } + + + return offset; +} + + +static int +dissect_ICBABrowse_BrowseItems_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Offset; + guint32 u32MaxReturn; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_browse_offset, &u32Offset); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_browse_max_return, &u32MaxReturn); + + col_append_fstr(pinfo->cinfo, COL_INFO, " Offset=%u MaxReturn=%u", + u32Offset, u32MaxReturn); + + return offset; +} + + +static int +dissect_ICBABrowse_BrowseItems_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_cba_browse_item); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_cba_browse_data_type); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_cba_browse_access_right); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBABrowse2_get_Count2_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Selector; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_browse_selector, &u32Selector); + + col_append_fstr(pinfo->cinfo, COL_INFO, " Selector=%u", + u32Selector); + + return offset; +} + + + +static int +dissect_ICBABrowse2_BrowseItems2_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Selector; + guint32 u32Offset; + guint32 u32MaxReturn; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_browse_selector, &u32Selector); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_browse_offset, &u32Offset); + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_browse_max_return, &u32MaxReturn); + + col_append_fstr(pinfo->cinfo, COL_INFO, " Sel=%u Offset=%u MaxReturn=%u", + u32Selector, u32Offset, u32MaxReturn); + + return offset; +} + + +static int +dissect_ICBABrowse2_BrowseItems2_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_cba_browse_item); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_cba_browse_info1); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_cba_browse_info2); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAPersist2_Save2_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_cba_save_ldev_name); + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, hf_cba_save_result); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + + +static int +dissect_get_BSTR_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep, int hfindex) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, di, drep, + hfindex, szStr, u32MaxStr); + } else { + szStr[0] = '\0'; + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\" -> %s", szStr, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_get_ProductionDate_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + gdouble r8Date; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DATE(tvb, offset, pinfo, tree, di, drep, + hf_cba_production_date, &r8Date); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Date: %g -> %s", + r8Date, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_get_SerialNo_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + guint32 u32Pointer; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_VARIANT(tvb, offset, pinfo, tree, di, drep, + hf_cba_serial_no); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBATime_get_Time_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + gdouble r8Date; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DATE(tvb, offset, pinfo, tree, di, drep, + hf_cba_time, &r8Date); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Time: %g -> %s", + r8Date, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBATime_put_Time_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gdouble r8Date; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DATE(tvb, offset, pinfo, tree, di, drep, + hf_cba_time, &r8Date); + + return offset; +} + + +static int +dissect_get_Producer_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + + return dissect_get_BSTR_resp(tvb, offset, pinfo, tree, di, drep, hf_cba_producer); +} + + +static int +dissect_get_Product_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + + return dissect_get_BSTR_resp(tvb, offset, pinfo, tree, di, drep, hf_cba_product); +} + + +static int +dissect_ICBAPhysicalDevice_get_LogicalDevice_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Pointer; + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + gchar *call; + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_name, szStr, u32MaxStr); + } else { + szStr[0] = '\0'; + } + + if (strlen(szStr) > 0) { + call = wmem_strdup(wmem_file_scope(), szStr); + di->call_data->private_data = call; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"", szStr); + + return offset; +} + + +static int +dissect_ICBAPhysicalDevice_get_LogicalDevice_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + gchar *ldev_name = (gchar *)di->call_data->private_data; + dcom_interface_t *pdev_interf; + dcom_interface_t *ldev_interf; + cba_pdev_t *pdev; + cba_ldev_t *ldev; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, di, drep, 0, &ldev_interf); + + /* try to read the ldev name from the request */ + if (ldev_name != NULL && ldev_interf != NULL) { + /* XXX - this is a hack to create a pdev interface */ + /* as I currently don't understand the objref process for a root interface! */ + pdev_interf = dcom_interface_new(pinfo, &pinfo->net_dst, &uuid_ICBAPhysicalDevice, 0, 0, &di->call_data->object_uuid); + if (pdev_interf != NULL) { + pdev = cba_pdev_add(pinfo, &pinfo->net_dst); + cba_pdev_link(pinfo, pdev, pdev_interf); + + ldev = cba_ldev_add(pinfo, pdev, ldev_name); + cba_ldev_link(pinfo, ldev, ldev_interf); + } + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAPhysicalDevice2_Type_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16MultiApp; + guint16 u16PROFInetDCOMStack; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, tree, di, drep, + hf_cba_multi_app, &u16MultiApp); + + offset = dissect_dcom_VARIANT_BOOL(tvb, offset, pinfo, tree, di, drep, + hf_cba_profinet_dcom_stack, &u16PROFInetDCOMStack); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " App=%s Stack=%s -> %s", + (u16MultiApp) ? "Multi" : "Single", + (u16PROFInetDCOMStack) ? "PN-DCOM" : "MS-DCOM", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_PROFInetRevision_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16Major; + guint16 u16Minor; + guint16 u16ServicePack; + guint16 u16Build; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_revision_major, &u16Major); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_revision_minor, &u16Minor); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_revision_service_pack, &u16ServicePack); + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_revision_build, &u16Build); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " Revision=%u.%u.%u.%u -> %s", + u16Major, u16Minor, u16ServicePack, u16Build, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAPhysicalDevice2_get_PDevStamp_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32PDevStamp; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_pdev_stamp, &u32PDevStamp); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " PDevStamp=0x%x -> %s", + u32PDevStamp, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_Revision_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16Major; + guint16 u16Minor; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_revision_major, &u16Major); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_revision_minor, &u16Minor); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": %u.%u -> %s", + u16Major, u16Minor, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBALogicalDevice_get_Name_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_name, szStr, u32MaxStr); + } else { + szStr[0] = '\0'; + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\" -> %s", szStr, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_RTAuto_get_Name_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + + return dissect_get_BSTR_resp(tvb, offset, pinfo, tree, di, drep, hf_cba_name); +} + + +static int +dissect_ICBALogicalDevice_get_ACCO_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + dcom_interface_t *acco_interf; + cba_ldev_t *ldev; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, di, drep, 0, &acco_interf); + if (acco_interf == NULL) { + expert_add_info(pinfo, NULL, &ei_cba_acco_interface_pointer_unresolved); + } + + ldev = cba_ldev_find(pinfo, &pinfo->net_src, &di->call_data->object_uuid); + + /* "crosslink" interface and its object */ + if (ldev != NULL && acco_interf != NULL) { + cba_ldev_link_acco(pinfo, ldev, acco_interf); + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBALogicalDevice_get_RTAuto_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, di, drep, 0, NULL); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBALogicalDevice_Get_RTAuto_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + guint32 u32Pointer; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_name, szStr, u32MaxStr); + } else { + szStr[0] = '\0'; + } + + col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"", szStr); + + return offset; +} + + + +static int +dissect_ComponentInfo_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + gchar szStr[1000]; + guint32 u32MaxStr = sizeof(szStr); + gchar szStr2[1000]; + guint32 u32MaxStr2 = sizeof(szStr2); + guint32 u32HResult; + guint32 u32Pointer; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_component_id, szStr, u32MaxStr); + } else { + szStr[0] = '\0'; + } + + offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep, + &u32Pointer); + if (u32Pointer) { + offset = dissect_dcom_BSTR(tvb, offset, pinfo, tree, di, drep, + hf_cba_component_version, szStr2, u32MaxStr2); + } else { + szStr2[0] = '\0'; + } + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": ID=\"%s\" Version=\"%s\" -> %s", + szStr, szStr2, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static void +dissect_PBAddressInfo(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, dcerpc_info *di, guint8 *drep, + guint32 u32VarType _U_, guint32 u32ArraySize) +{ + guint8 u8ID; + guint8 u8Addr; + proto_item *sub_item; + proto_tree *sub_tree; + + + while (u32ArraySize != 0) { + sub_item = proto_tree_add_item(tree, hf_cba_pbaddress, tvb, offset, 2, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_PBAddress); + + offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_pbaddress_system_id, &u8ID); + offset = dissect_dcom_BYTE(tvb, offset, pinfo, sub_tree, di, drep, + hf_cba_pbaddress_address, &u8Addr); + u32ArraySize-=2; + + proto_item_append_text(sub_item, ": ID=0x%x Addr=%u", u8ID, u8Addr); + col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=0x%x Addr=%u", + u8ID, u8Addr); + } +} + + +static int +dissect_PBAddressInfo_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32HResult; + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_SAFEARRAY(tvb, offset, pinfo, tree, di, drep, 0 /*hfindex _U_ */, dissect_PBAddressInfo); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s", + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_Advise_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, di, drep, 0, NULL); + + return offset; +} + + +static int +dissect_Advise_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Cookie; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_cookie, &u32Cookie); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cookie=0x%x -> %s", + u32Cookie, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_Unadvise_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Cookie; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_cookie, &u32Cookie); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cookie=0x%x", + u32Cookie); + + return offset; +} + + +static int +dissect_ICBAState_get_State_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16State; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_state, &u16State); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": State=%s -> %s", + val_to_str(u16State, cba_state_vals, "Unknown (0x%08x)"), + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAStateEvent_OnStateChanged_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16NewState; + guint16 u16OldState; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_new_state, &u16NewState); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_old_state, &u16OldState); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": NewState=%s OldState=%s", + val_to_str(u16NewState, cba_state_vals, "Unknown (0x%04x)"), + val_to_str(u16OldState, cba_state_vals, "Unknown (0x%04x)") ); + + return offset; +} + + +static int +dissect_ICBAGroupError_OnGroupErrorChanged_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16NewGroupError; + guint16 u16OldGroupError; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_new_grouperror, &u16NewGroupError); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_old_grouperror, &u16OldGroupError); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": NewGE=%s OldGE=%s", + val_to_str(u16NewGroupError, cba_grouperror_vals, "Unknown (0x%04x)"), + val_to_str(u16OldGroupError, cba_grouperror_vals, "Unknown (0x%04x)") ); + + return offset; +} + + +static int +dissect_ICBAPhysicalDevicePCEvent_OnLogicalDeviceAdded_rqst(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint32 u32Cookie; + guint32 u32HResult; + + + offset = dissect_dcom_this(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_cookie, &u32Cookie); + + offset = dissect_dcom_PMInterfacePointer(tvb, offset, pinfo, tree, di, drep, 0, NULL); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": Cookie=0x%x %s", + u32Cookie, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +static int +dissect_ICBAGroupError_GroupError_resp(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep) +{ + guint16 u16GroupError; + guint32 u32Cookie; + guint32 u32HResult; + + + offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep); + + offset = dissect_dcom_WORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_grouperror, &u16GroupError); + + offset = dissect_dcom_DWORD(tvb, offset, pinfo, tree, di, drep, + hf_cba_cookie, &u32Cookie); + + offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep, + &u32HResult); + + col_append_fstr(pinfo->cinfo, COL_INFO, ": GroupError=%s Cookie=0x%x -> %s", + val_to_str(u16GroupError, cba_grouperror_vals, "Unknown (0x%08x)"), + u32Cookie, + val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") ); + + return offset; +} + + +/* sub dissector table of ICBAPhysicalDevice / ICBAPhysicalDevice2 interface */ +static dcerpc_sub_dissector ICBAPhysicalDevice_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "get_Producer", dissect_dcom_simple_rqst, dissect_get_Producer_resp }, + { 8, "get_Product", dissect_dcom_simple_rqst, dissect_get_Product_resp }, + { 9, "get_SerialNo", dissect_dcom_simple_rqst, dissect_get_SerialNo_resp }, + {10, "get_ProductionDate", dissect_dcom_simple_rqst, dissect_get_ProductionDate_resp }, + {11, "Revision", dissect_dcom_simple_rqst, dissect_Revision_resp }, + {12, "get_LogicalDevice", dissect_ICBAPhysicalDevice_get_LogicalDevice_rqst, dissect_ICBAPhysicalDevice_get_LogicalDevice_resp }, + /* stage 2 */ + {13, "Type", dissect_dcom_simple_rqst, dissect_ICBAPhysicalDevice2_Type_resp }, + {14, "PROFInetRevision", dissect_dcom_simple_rqst, dissect_PROFInetRevision_resp }, + {15, "PDevStamp", dissect_dcom_simple_rqst, dissect_ICBAPhysicalDevice2_get_PDevStamp_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBABrowse / ICBABrowse2 interface */ +static dcerpc_sub_dissector ICBABrowse_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "get_Count", dissect_dcom_simple_rqst, dissect_ICBABrowse_get_Count_resp }, + { 8, "BrowseItems", dissect_ICBABrowse_BrowseItems_rqst, dissect_ICBABrowse_BrowseItems_resp }, + /* stage 2 */ + { 9, "get_Count2", dissect_ICBABrowse2_get_Count2_rqst, dissect_ICBABrowse_get_Count_resp }, + {10, "BrowseItems2", dissect_ICBABrowse2_BrowseItems2_rqst, dissect_ICBABrowse2_BrowseItems2_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAPersist / ICBAPersist2 interface */ +static dcerpc_sub_dissector ICBAPersist_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "Save", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + /* stage 2 */ + { 8, "Save2", dissect_dcom_simple_rqst, dissect_ICBAPersist2_Save2_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAPhysicalDevicePC interface */ +/* (local COM interface, not to be called over network) */ +static dcerpc_sub_dissector ICBAPhysicalDevicePC_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "AddLogicalDevice", dissect_Advise_rqst, dissect_Advise_resp }, + { 4, "RemoveLogicalDevice", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + { 5, "AdvisePDevPC", dissect_Advise_rqst, dissect_Advise_resp }, + { 6, "UnadvisePDevPC", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + /* stage 2 */ + { 7, "RegisterApplication", NULL, NULL }, + { 8, "UnRegisterApplication", NULL, NULL }, + { 9, "AddLogicalDevice2", NULL, NULL }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAPhysicalDevicePCEvent interface */ +static dcerpc_sub_dissector ICBAPhysicalDevicePCEvent_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "OnLogicalDeviceAdded", dissect_ICBAPhysicalDevicePCEvent_OnLogicalDeviceAdded_rqst, dissect_dcom_simple_resp }, + { 4, "OnLogicalDeviceRemoved", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBALogicalDevice / ICBALogicalDevice2 interface */ +static dcerpc_sub_dissector ICBALogicalDevice_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "get_Name", dissect_dcom_simple_rqst, dissect_ICBALogicalDevice_get_Name_resp }, + { 8, "get_Producer", dissect_dcom_simple_rqst, dissect_get_Producer_resp }, + { 9, "get_Product", dissect_dcom_simple_rqst, dissect_get_Product_resp }, + {10, "get_SerialNo", dissect_dcom_simple_rqst, dissect_get_SerialNo_resp }, + {11, "get_ProductionDate", dissect_dcom_simple_rqst, dissect_get_ProductionDate_resp }, + {12, "Revision", dissect_dcom_simple_rqst, dissect_Revision_resp }, + {13, "get_ACCO", dissect_dcom_simple_rqst, dissect_ICBALogicalDevice_get_ACCO_resp }, + {14, "get_RTAuto", dissect_ICBALogicalDevice_Get_RTAuto_rqst, dissect_ICBALogicalDevice_get_RTAuto_resp }, + /* stage 2 */ + {15, "PROFInetRevision", dissect_dcom_simple_rqst, dissect_PROFInetRevision_resp }, + {16, "ComponentInfo", dissect_dcom_simple_rqst, dissect_ComponentInfo_resp }, + {17, "PBAddressInfo", dissect_dcom_simple_rqst, dissect_PBAddressInfo_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAState interface */ +static dcerpc_sub_dissector ICBAState_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "get_State", dissect_dcom_simple_rqst, dissect_ICBAState_get_State_resp }, + { 8, "Activate", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + { 9, "Deactivate", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + {10, "Reset", dissect_dcom_simple_rqst, dissect_dcom_simple_resp }, + {11, "AdviseState", dissect_Advise_rqst, dissect_Advise_resp }, + {12, "UnadviseState", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAStateEvent interface */ +static dcerpc_sub_dissector ICBAStateEvent_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "OnStateChanged", dissect_ICBAStateEvent_OnStateChanged_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBATime interface */ +static dcerpc_sub_dissector ICBATime_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "get_Time", dissect_dcom_simple_rqst, dissect_ICBATime_get_Time_resp }, + { 8, "put_Time", dissect_ICBATime_put_Time_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAGroupError interface */ +static dcerpc_sub_dissector ICBAGroupError_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "GroupError", dissect_dcom_simple_rqst, dissect_ICBAGroupError_GroupError_resp }, + { 8, "AdviseGroupError", dissect_Advise_rqst, dissect_Advise_resp }, + { 9, "UnadviseGroupError", dissect_Unadvise_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBAGroupErrorEvent interface */ +static dcerpc_sub_dissector ICBAGroupErrorEvent_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "OnGroupErrorChanged", dissect_ICBAGroupError_OnGroupErrorChanged_rqst, dissect_dcom_simple_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* sub dissector table of ICBARTAuto interface */ +static dcerpc_sub_dissector ICBARTAuto_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "get_Name", dissect_dcom_simple_rqst, dissect_RTAuto_get_Name_resp }, + { 8, "Revision", dissect_dcom_simple_rqst, dissect_Revision_resp }, + + /* stage 2 */ + { 9, "ComponentInfo", dissect_dcom_simple_rqst, dissect_ComponentInfo_resp }, + { 0, NULL, NULL, NULL }, +}; + + +/* the interface ICBASystemProperties will NOT be seen on the ethernet */ +/* sub dissector table of ICBASystemProperties interface (stage 2 only) */ +/* (usually not called over network, no dissecting needed) */ +static dcerpc_sub_dissector ICBASystemProperties_dissectors[] = { + { 0, "QueryInterface", NULL, NULL }, + { 1, "AddRef", NULL, NULL }, + { 2, "Release", NULL, NULL }, + + { 3, "GetTypeInfoCount", dissect_dcom_simple_rqst, dissect_IDispatch_GetTypeInfoCount_resp }, + { 4, "GetTypeInfo", dissect_IDispatch_GetTypeInfo_rqst, dissect_IDispatch_GetTypeInfo_resp }, + { 5, "GetIDsOfNames", dissect_IDispatch_GetIDsOfNames_rqst, dissect_IDispatch_GetIDsOfNames_resp }, + { 6, "Invoke", dissect_IDispatch_Invoke_rqst, dissect_IDispatch_Invoke_resp }, + + { 7, "StateCollection", dissect_dcom_simple_rqst, NULL }, + { 8, "StampCollection", dissect_dcom_simple_rqst, NULL }, + { 0, NULL, NULL, NULL }, +}; + + +static void cba_cleanup(void) { + g_list_free(cba_pdevs); + cba_pdevs = NULL; +} + + +/* register protocol */ +void +proto_register_dcom_cba (void) +{ + static hf_register_info hf_cba_browse_array[] = { + { &hf_cba_browse_count, + { "Count", "cba.browse.count", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_browse_offset, + { "Offset", "cba.browse.offset", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_browse_max_return, + { "MaxReturn", "cba.browse.max_return", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_browse_item, + { "ItemNames", "cba.browse.item", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_browse_data_type, + { "DataTypes", "cba.browse.data_type", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_browse_access_right, + { "AccessRights", "cba.browse.access_right", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_browse_selector, + { "Selector", "cba.browse.selector", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_browse_info1, + { "Info1", "cba.browse.info1", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_browse_info2, + { "Info2", "cba.browse.info2", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + }; + + + static hf_register_info hf_cba_pdev_array[] = { + { &hf_cba_revision_major, + { "Major", "cba.revision_major", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_revision_minor, + { "Minor", "cba.revision_minor", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_revision_service_pack, + { "ServicePack", "cba.revision_service_pack", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_revision_build, + { "Build", "cba_revision_build", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_producer, + { "Producer", "cba.producer", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_product, + { "Product", "cba.product", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_multi_app, + { "MultiApp", "cba.multi_app", + FT_UINT16, BASE_HEX, VALS(dcom_boolean_vals), 0x0, + NULL, HFILL }}, + + { &hf_cba_profinet_dcom_stack, + { "PROFInetDCOMStack", "cba.profinet_dcom_stack", + FT_UINT16, BASE_HEX, VALS(dcom_boolean_vals), 0x0, + NULL, HFILL }}, + + { &hf_cba_pdev_stamp, + { "PDevStamp", "cba.pdev_stamp", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_save_ldev_name, + { "LDevName", "cba.save_ldev_name", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_save_result, + { "PartialResult", "cba.save_result", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + }; + + static hf_register_info hf_cba_ldev_array[] = { + { &hf_cba_name, + { "Name", "cba.name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_component_id, + { "ComponentID", "cba.component_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_component_version, + { "Version", "cba.component_version", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_pbaddress, + { "PROFIBUS Address", "cba.pbaddress", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_pbaddress_system_id, + { "SystemID", "cba.pbaddress.system_id", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_pbaddress_address, + { "Address", "cba.pbaddress.address", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + }; + + static hf_register_info hf_cba_array[] = { + { &hf_cba_opnum, + { "Operation", "cba.opnum", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_production_date, + { "ProductionDate", "cba.production_date", + FT_DOUBLE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_time, + { "Time", "cba.time", + FT_DOUBLE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_serial_no, + { "SerialNo", "cba.serial_no", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_state, + { "State", "cba.state", + FT_UINT16, BASE_HEX, VALS(cba_state_vals), 0x0, + NULL, HFILL }}, + + { &hf_cba_new_state, + { "NewState", "cba.state_new", + FT_UINT16, BASE_HEX, VALS(cba_state_vals), 0x0, + NULL, HFILL }}, + + { &hf_cba_old_state, + { "OldState", "cba.state_old", + FT_UINT16, BASE_HEX, VALS(cba_state_vals), 0x0, + NULL, HFILL }}, + + { &hf_cba_cookie, + { "Cookie", "cba.cookie", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_cba_grouperror, + { "GroupError", "cba.grouperror", + FT_UINT16, BASE_HEX, VALS(cba_grouperror_vals), 0x0, + NULL, HFILL }}, + + { &hf_cba_new_grouperror, + { "NewGroupError", "cba.grouperror_new", + FT_UINT16, BASE_HEX, VALS(cba_grouperror_vals), 0x0, + NULL, HFILL }}, + + { &hf_cba_old_grouperror, + { "OldGroupError", "cba.grouperror_old", + FT_UINT16, BASE_HEX, VALS(cba_grouperror_vals), 0x0, + NULL, HFILL }}, + + }; + + static gint *ett_cba[] = { + &ett_ICBAPhysicalDevice, + &ett_ICBABrowse, + &ett_ICBAPhysicalDevicePC, + &ett_ICBAPhysicalDevicePCEvent, + &ett_ICBAPersist, + &ett_ICBALogicalDevice, + &ett_ICBAState, + &ett_ICBAStateEvent, + &ett_ICBATime, + &ett_ICBAGroupError, + &ett_ICBAGroupErrorEvent, + &ett_ICBARTAuto, + &ett_ICBASystemProperties, + &ett_PBAddress + }; + + static ei_register_info ei[] = { + { &ei_cba_acco_interface_pointer_unresolved, { "cba.acco.interface_pointer_unresolved", PI_UNDECODED, PI_WARN, "LDev_get_ACCO: can't resolve ACCO interface pointer", EXPFILL }}, + }; + + expert_module_t* expert_cba_acco; + + proto_register_subtree_array (ett_cba, array_length (ett_cba)); + + proto_ICBAPhysicalDevice = proto_register_protocol ("ICBAPhysicalDevice", "ICBAPDev", "cba_pdev"); + proto_register_field_array(proto_ICBAPhysicalDevice, hf_cba_pdev_array, array_length(hf_cba_pdev_array)); + + /* XXX - just pick a protocol to register the expert info in */ + expert_cba_acco = expert_register_protocol(proto_ICBAPhysicalDevice); + expert_register_field_array(expert_cba_acco, ei, array_length(ei)); + + proto_ICBAPhysicalDevice2 = proto_register_protocol ("ICBAPhysicalDevice2", "ICBAPDev2", "cba_pdev2"); + + proto_ICBABrowse = proto_register_protocol ("ICBABrowse", "ICBABrowse", "cba_browse"); + proto_register_field_array(proto_ICBABrowse, hf_cba_array, array_length(hf_cba_array)); + proto_register_field_array(proto_ICBABrowse, hf_cba_browse_array, array_length(hf_cba_browse_array)); + + proto_ICBABrowse2 = proto_register_protocol ("ICBABrowse2", "ICBABrowse2", "cba_browse2"); + + proto_ICBAPhysicalDevicePC = proto_register_protocol ("ICBAPhysicalDevicePC", "ICBAPDevPC", "cba_pdev_pc"); + + proto_ICBAPhysicalDevicePCEvent = proto_register_protocol ("ICBAPhysicalDevicePCEvent", "ICBAPDevPCEvent", "cba_pdev_pc_event"); + + proto_ICBAPersist = proto_register_protocol ("ICBAPersist", "ICBAPersist", "cba_persist"); + + proto_ICBAPersist2 = proto_register_protocol ("ICBAPersist2", "ICBAPersist2", "cba_persist2"); + + proto_ICBALogicalDevice = proto_register_protocol ("ICBALogicalDevice", "ICBALDev", "cba_ldev"); + proto_register_field_array(proto_ICBAPhysicalDevice, hf_cba_ldev_array, array_length(hf_cba_ldev_array)); + + proto_ICBALogicalDevice2 = proto_register_protocol ("ICBALogicalDevice2", "ICBALDev2", "cba_ldev2"); + + proto_ICBAState = proto_register_protocol ("ICBAState", "ICBAState", "cba_state"); + + proto_ICBAStateEvent = proto_register_protocol ("ICBAStateEvent", "ICBAStateEvent", "cba_state_event"); + + proto_ICBATime = proto_register_protocol ("ICBATime", "ICBATime", "cba_time"); + + proto_ICBAGroupError = proto_register_protocol ("ICBAGroupError", "ICBAGErr", "cba_grouperror"); + + proto_ICBAGroupErrorEvent = proto_register_protocol ("ICBAGroupErrorEvent", "ICBAGErrEvent", "cba_grouperror_event"); + + proto_ICBARTAuto = proto_register_protocol ("ICBARTAuto", "ICBARTAuto", "cba_rtauto"); + + proto_ICBARTAuto2 = proto_register_protocol ("ICBARTAuto2", "ICBARTAuto2", "cba_rtauto2"); + + proto_ICBASystemProperties = proto_register_protocol ("ICBASystemProperties", "ICBASysProp", "cba_sysprop"); + + register_cleanup_routine(cba_cleanup); +} + + +/* handoff protocol */ +void +proto_reg_handoff_dcom_cba (void) +{ + /* Register the CBA class ID */ + guids_add_uuid(&uuid_coclass_CBAPhysicalDevice, "CBA"); + + /* Register the interfaces */ + dcerpc_init_uuid(proto_ICBAPhysicalDevice, ett_ICBAPhysicalDevice, + &uuid_ICBAPhysicalDevice, ver_ICBAPhysicalDevice, + ICBAPhysicalDevice_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPhysicalDevice2, ett_ICBAPhysicalDevice, + &uuid_ICBAPhysicalDevice2, ver_ICBAPhysicalDevice2, + ICBAPhysicalDevice_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBABrowse, ett_ICBABrowse, + &uuid_ICBABrowse, ver_ICBABrowse, + ICBABrowse_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBABrowse2, ett_ICBABrowse, + &uuid_ICBABrowse2, ver_ICBABrowse2, + ICBABrowse_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPhysicalDevicePC, ett_ICBAPhysicalDevicePC, + &uuid_ICBAPhysicalDevicePC, ver_ICBAPhysicalDevicePC, + ICBAPhysicalDevicePC_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPhysicalDevicePCEvent, ett_ICBAPhysicalDevicePCEvent, + &uuid_ICBAPhysicalDevicePCEvent, ver_ICBAPhysicalDevicePCEvent, + ICBAPhysicalDevicePCEvent_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPersist, ett_ICBAPersist, + &uuid_ICBAPersist, ver_ICBAPersist, + ICBAPersist_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAPersist2, ett_ICBAPersist, + &uuid_ICBAPersist2, ver_ICBAPersist2, + ICBAPersist_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBALogicalDevice, ett_ICBALogicalDevice, + &uuid_ICBALogicalDevice, ver_ICBALogicalDevice, + ICBALogicalDevice_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBALogicalDevice2, ett_ICBALogicalDevice, + &uuid_ICBALogicalDevice2, ver_ICBALogicalDevice2, + ICBALogicalDevice_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAState, ett_ICBAState, + &uuid_ICBAState, ver_ICBAState, + ICBAState_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAStateEvent, ett_ICBAStateEvent, + &uuid_ICBAStateEvent, ver_ICBAStateEvent, + ICBAStateEvent_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBATime, ett_ICBATime, + &uuid_ICBATime, ver_ICBATime, + ICBATime_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAGroupError, ett_ICBAGroupError, + &uuid_ICBAGroupError, ver_ICBAGroupError, + ICBAGroupError_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBAGroupErrorEvent, ett_ICBAGroupErrorEvent, + &uuid_ICBAGroupErrorEvent, ver_ICBAGroupErrorEvent, + ICBAGroupErrorEvent_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBARTAuto, ett_ICBARTAuto, + &uuid_ICBARTAuto, ver_ICBARTAuto, + ICBARTAuto_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBARTAuto2, ett_ICBARTAuto, + &uuid_ICBARTAuto2, ver_ICBARTAuto2, + ICBARTAuto_dissectors, hf_cba_opnum); + + dcerpc_init_uuid(proto_ICBASystemProperties, ett_ICBASystemProperties, + &uuid_ICBASystemProperties, ver_ICBASystemProperties, + ICBASystemProperties_dissectors, hf_cba_opnum); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-pn-dcp.c b/plugins/epan/profinet/packet-pn-dcp.c new file mode 100644 index 00000000..456c79c9 --- /dev/null +++ b/plugins/epan/profinet/packet-pn-dcp.c @@ -0,0 +1,2096 @@ +/* packet-pn-dcp.c + * Routines for PN-DCP (PROFINET Discovery and basic Configuration Protocol) + * packet dissection. + * + * IEC 61158-6-10 section 4.3 + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * Cyclic PNIO RTC1 Data Dissection: + * + * Added new functions to packet-pn-dcp.c. The profinet plug-in will now save + * the information (Stationname, -type, -id) of "Ident OK" frames. Those + * informations will later be used for detailled dissection of cyclic PNIO RTC1 + * dataframes. + * + * The declaration of the new added structures are within packet-pn.h to + * use the information within packet-pn-rtc-one.c + * + * Overview for cyclic PNIO RTC1 data dissection functions: + * -> dissect_PNDCP_Suboption_Device (Save Stationname, -type, -id) + */ + + +#include "config.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "packet-pn.h" + + +void proto_register_pn_dcp(void); +void proto_reg_handoff_pn_dcp(void); + +int proto_pn_dcp = -1; + +static int hf_pn_dcp_service_id = -1; +static int hf_pn_dcp_service_type = -1; +static int hf_pn_dcp_xid = -1; +static int hf_pn_dcp_reserved8 = -1; +static int hf_pn_dcp_reserved16 = -1; +static int hf_pn_dcp_response_delay = -1; +static int hf_pn_dcp_data_length = -1; +static int hf_pn_dcp_block_length = -1; + +static int hf_pn_dcp_block = -1; + +static int hf_pn_dcp_block_error = -1; + +static int hf_pn_dcp_option = -1; +static int hf_pn_dcp_block_info = -1; +static int hf_pn_dcp_block_qualifier = -1; +static int hf_pn_dcp_blockqualifier = -1; +static int hf_pn_dcp_blockqualifier_r2f = -1; + +static int hf_pn_dcp_suboption_ip = -1; +static int hf_pn_dcp_suboption_ip_block_info = -1; +static int hf_pn_dcp_suboption_ip_ip = -1; +static int hf_pn_dcp_suboption_ip_subnetmask = -1; +static int hf_pn_dcp_suboption_ip_standard_gateway = -1; +static int hf_pn_dcp_suboption_ip_mac_address = -1; + +static int hf_pn_dcp_suboption_device = -1; +static int hf_pn_dcp_suboption_device_typeofstation = -1; +static int hf_pn_dcp_suboption_device_nameofstation = -1; +static int hf_pn_dcp_suboption_vendor_id = -1; +static int hf_pn_dcp_suboption_device_id = -1; +static int hf_pn_dcp_suboption_device_role = -1; +static int hf_pn_dcp_suboption_device_aliasname = -1; +static int hf_pn_dcp_suboption_device_instance_high = -1; +static int hf_pn_dcp_suboption_device_instance_low = -1; +static int hf_pn_dcp_suboption_device_oem_ven_id = -1; +static int hf_pn_dcp_suboption_device_oem_dev_id = -1; + +static int hf_pn_dcp_rsi_properties_value = -1; +static int hf_pn_dcp_rsi_properties_value_bit0 = -1; +static int hf_pn_dcp_rsi_properties_value_bit1 = -1; +static int hf_pn_dcp_rsi_properties_value_bit2 = -1; +static int hf_pn_dcp_rsi_properties_value_bit3 = -1; +static int hf_pn_dcp_rsi_properties_value_bit4 = -1; +static int hf_pn_dcp_rsi_properties_value_bit5 = -1; +static int hf_pn_dcp_rsi_properties_value_otherbits = -1; + +static int hf_pn_dcp_suboption_tsn = -1; +static int hf_pn_dcp_suboption_tsn_domain_name = -1; +static int hf_pn_dcp_suboption_tsn_domain_uuid = -1; +static int hf_pn_dcp_suboption_tsn_nme_prio = -1; +static int hf_pn_dcp_suboption_tsn_nme_parameter_uuid = -1; +static int hf_pn_dcp_suboption_tsn_nme_agent = -1; + +static int hf_pn_dcp_suboption_dhcp = -1; +static int hf_pn_dcp_suboption_dhcp_option_code = -1; +static int hf_pn_dcp_suboption_dhcp_parameter_length = -1; +static int hf_pn_dcp_suboption_dhcp_parameter_data = -1; +static int hf_pn_dcp_suboption_dhcp_arbitrary_client_id = -1; +static int hf_pn_dcp_suboption_dhcp_control_parameter_data = -1; + +static int hf_pn_dcp_suboption_control = -1; +static int hf_pn_dcp_suboption_control_option = -1; +static int hf_pn_dcp_suboption_control_signal_value = -1; + +static int hf_pn_dcp_suboption_deviceinitiative = -1; +static int hf_pn_dcp_deviceinitiative_value = -1; + +static int hf_pn_dcp_suboption_all = -1; + +static int hf_pn_dcp_suboption_manuf = -1; + +static int hf_pn_dcp_vendor_id_high = -1; +static int hf_pn_dcp_vendor_id_low = -1; +static int hf_pn_dcp_device_id_high = -1; +static int hf_pn_dcp_device_id_low = -1; +static int hf_pn_dcp_instance_id_high = -1; +static int hf_pn_dcp_instance_id_low = -1; +static gint ett_pn_dcp = -1; +static gint ett_pn_dcp_block = -1; + +static gint ett_pn_dcp_rsi_properties_value = -1; + +static expert_field ei_pn_dcp_block_parse_error = EI_INIT; +static expert_field ei_pn_dcp_block_error_unknown = EI_INIT; +static expert_field ei_pn_dcp_ip_conflict = EI_INIT; + +#define PNDCP_SERVICE_ID_GET 0x03 +#define PNDCP_SERVICE_ID_SET 0x04 +#define PNDCP_SERVICE_ID_IDENTIFY 0x05 +#define PNDCP_SERVICE_ID_HELLO 0x06 + +static const value_string pn_dcp_service_id[] = { + { 0x00, "reserved" }, + { 0x01, "Manufacturer specific" }, + { 0x02, "Manufacturer specific" }, + { PNDCP_SERVICE_ID_GET, "Get" }, + { PNDCP_SERVICE_ID_SET, "Set" }, + { PNDCP_SERVICE_ID_IDENTIFY,"Identify" }, + { PNDCP_SERVICE_ID_HELLO, "Hello" }, + /* 0x07 - 0xff reserved */ + { 0, NULL } +}; + +#define PNDCP_SERVICE_TYPE_REQUEST 0 +#define PNDCP_SERVICE_TYPE_RESPONSE_SUCCESS 1 +#define PNDCP_SERVICE_TYPE_RESPONSE_UNSUPPORTED 5 + +static const value_string pn_dcp_service_type[] = { + { PNDCP_SERVICE_TYPE_REQUEST, "Request" }, + { PNDCP_SERVICE_TYPE_RESPONSE_SUCCESS, "Response Success" }, + { PNDCP_SERVICE_TYPE_RESPONSE_UNSUPPORTED, "Response - Request not supported" }, + /* all others reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_block_error[] = { + { 0x00, "Ok" }, + { 0x01, "Option unsupp." }, + { 0x02, "Suboption unsupp. or no DataSet avail." }, + { 0x03, "Suboption not set" }, + { 0x04, "Resource Error" }, + { 0x05, "SET not possible by local reasons" }, + { 0x06, "In operation, SET not possible" }, + /* all others reserved */ + { 0, NULL } +}; + +static const range_string pn_dcp_block_info[] = { + { 0x0000, 0xFFFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const value_string pn_dcp_block_qualifier[] = { + { 0x0000, "Use the value temporary" }, + { 0x0001, "Save the value permanent" }, + /*0x0002 - 0xffff reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_BlockQualifier[] = { + { 0x0002, "Reset application data" }, + { 0x0003, "Reset application data" }, + { 0x0004, "Reset communication parameter" }, + { 0x0005, "Reset communication parameter" }, + { 0x0006, "Reset engineering parameter" }, + { 0x0007, "Reset engineering parameter" }, + { 0x0008, "Resets all stored data" }, + { 0x0009, "Resets all stored data" }, + { 0x000A, "Reset engineering parameter" }, + { 0x000B, "Reset engineering parameter" }, + { 0x000C, "Reserved" }, + { 0x000D, "Reserved" }, + { 0x000E, "Reserved" }, + { 0x0010, "Resets all stored data in the IOD or IOC to its factory values" }, + { 0x0011, "Resets all stored data in the IOD or IOC to its factory values" }, + { 0x0012, "Reset and restore data" }, + { 0x0013, "Reset and restore data" }, + { 0x0014, "Reserved" }, + { 0x0015, "Reserved" }, + { 0x0016, "Reserved" }, + { 0, NULL } +}; + +#define PNDCP_OPTION_IP 0x01 +#define PNDCP_OPTION_DEVICE 0x02 +#define PNDCP_OPTION_DHCP 0x03 +#define PNDCP_OPTION_RESERVED 0x04 +#define PNDCP_OPTION_CONTROL 0x05 +#define PNDCP_OPTION_DEVICEINITIATIVE 0x06 +#define PNDCP_OPTION_TSN 0x07 +#define PNDCP_OPTION_MANUF_X80 0x80 +#define PNDCP_OPTION_MANUF_XFE 0xFE +#define PNDCP_OPTION_ALLSELECTOR 0xFF + +static const range_string pn_dcp_option[] = { + { 0x00, 0x00, "Reserved" }, + { PNDCP_OPTION_IP , PNDCP_OPTION_IP , "IP" }, + { PNDCP_OPTION_DEVICE , PNDCP_OPTION_DEVICE , "Device properties" }, + { PNDCP_OPTION_DHCP , PNDCP_OPTION_DHCP , "DHCP" }, + { PNDCP_OPTION_RESERVED , PNDCP_OPTION_RESERVED , "Reserved" }, + { PNDCP_OPTION_CONTROL , PNDCP_OPTION_CONTROL , "Control" }, + { PNDCP_OPTION_DEVICEINITIATIVE, PNDCP_OPTION_DEVICEINITIATIVE, "Device Initiative" }, + { PNDCP_OPTION_TSN , PNDCP_OPTION_TSN , "TSN Domain"}, + /*0x07 - 0x7F reserved */ + /*0x80 - 0xFE manufacturer specific */ + { PNDCP_OPTION_MANUF_X80 , PNDCP_OPTION_MANUF_XFE , "Manufacturer specific" }, + { PNDCP_OPTION_ALLSELECTOR, PNDCP_OPTION_ALLSELECTOR, "All Selector" }, + { 0, 0, NULL } +}; + +#define PNDCP_SUBOPTION_IP_MAC 0x01 +#define PNDCP_SUBOPTION_IP_IP 0x02 +#define PNDCP_SUBOPTION_IP_FULL_IP_SUITE 0x03 + +static const value_string pn_dcp_suboption_ip[] = { + { 0x00, "Reserved" }, + { PNDCP_SUBOPTION_IP_MAC, "MAC address" }, + { PNDCP_SUBOPTION_IP_IP, "IP parameter" }, + { PNDCP_SUBOPTION_IP_FULL_IP_SUITE, "Full IP suite" }, + /*0x03 - 0xff reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_suboption_ip_block_info[] = { + { 0x0000, "IP not set" }, + { 0x0001, "IP set" }, + { 0x0002, "IP set by DHCP" }, + { 0x0080, "IP not set (address conflict detected)" }, + { 0x0081, "IP set (address conflict detected)" }, + { 0x0082, "IP set by DHCP (address conflict detected)" }, + /*0x0003 - 0xffff reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_suboption_control_signal_value[] = { + {0x0100, "Flash Once"}, + {0, NULL} +}; + +#define PNDCP_SUBOPTION_DEVICE_MANUF 0x01 +#define PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION 0x02 +#define PNDCP_SUBOPTION_DEVICE_DEV_ID 0x03 +#define PNDCP_SUBOPTION_DEVICE_DEV_ROLE 0x04 +#define PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS 0x05 +#define PNDCP_SUBOPTION_DEVICE_ALIAS_NAME 0x06 +#define PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE 0x07 +#define PNDCP_SUBOPTION_DEVICE_OEM_DEV_ID 0x08 +#define PNDCP_SUBOPTION_DEVICE_RSI_PROPERTIES 0x0A + +static const value_string pn_dcp_suboption_device[] = { + { 0x00, "Reserved" }, + { PNDCP_SUBOPTION_DEVICE_MANUF, "Manufacturer specific (Type of Station)" }, + { PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION, "Name of Station" }, + { PNDCP_SUBOPTION_DEVICE_DEV_ID, "Device ID" }, + { PNDCP_SUBOPTION_DEVICE_DEV_ROLE, "Device Role" }, + { PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS, "Device Options" }, + { PNDCP_SUBOPTION_DEVICE_ALIAS_NAME, "Alias Name" }, + { PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE, "Device Instance" }, + { PNDCP_SUBOPTION_DEVICE_OEM_DEV_ID, "OEM Device ID"}, + { PNDCP_SUBOPTION_DEVICE_RSI_PROPERTIES,"RSI Properties" }, + /*0x09 - 0xff reserved */ + { 0, NULL } +}; + +static const true_false_string pn_dcp_rsi_properties_value_bit = + { "Available", "Not available" } ; + +#define PNDCP_SUBOPTION_TSN_DOMAIN_NAME 0x01 +#define PNDCP_SUBOPTION_TSN_NME_MANAGER 0x02 +#define PNDCP_SUBOPTION_TSN_NME_PARAMETER_UUID 0x03 +#define PNDCP_SUBOPTION_TSN_NME_AGENT 0x04 +#define PNDCP_SUBOPTION_TSN_CIM_INTERFACE 0x05 + +static const value_string pn_dcp_suboption_tsn[] = { + { 0x00, "Reserved" }, + { PNDCP_SUBOPTION_TSN_DOMAIN_NAME, "TSN Domain Name" }, + { PNDCP_SUBOPTION_TSN_NME_MANAGER, "NME Manager" }, + { PNDCP_SUBOPTION_TSN_NME_PARAMETER_UUID, "NME Paramater UUID" }, + { PNDCP_SUBOPTION_TSN_NME_AGENT, "NME Agent" }, + { PNDCP_SUBOPTION_TSN_CIM_INTERFACE, "CIM Interface" }, + { 0, NULL } +}; + +static const range_string pn_dcp_suboption_tsn_nme_prio[] = +{ + { 0x0000, 0x0000, "Highest priority NME manager" }, + { 0x0001, 0x3000, "High priorities for NME manager" }, + { 0x3001, 0x9FFF, "Low priorities for NME manager" }, + { 0xA000, 0xA000, "Lowest priority for NME manager / Default priority for NME manager" }, + { 0xA001, 0xFFFF, "Reserved" }, + { 0, 0, NULL } +}; + +#define PNDCP_SUBOPTION_DHCP_CLIENT_ID 61 +#define PNDCP_SUBOPTION_DHCP_CONTROL_FOR_ADDRESS_RES 255 + +static const value_string pn_dcp_suboption_dhcp[] = { + { 12, "Host name" }, + { 43, "Vendor specific" }, + { 54, "Server identifier" }, + { 55, "Parameter request list" }, + { 60, "Class identifier" }, + { PNDCP_SUBOPTION_DHCP_CLIENT_ID, "DHCP client identifier" }, + { 81, "FQDN, Fully Qualified Domain Name" }, + { 97, "UUID/GUID-based Client" }, + { PNDCP_SUBOPTION_DHCP_CONTROL_FOR_ADDRESS_RES, "Control DHCP for address resolution" }, + /*all others reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_suboption_dhcp_control_parameter_data[] = { + { 0x00, "Don't use DHCP (Default)" }, + { 0x01, "Don't use DHCP, all DHCPOptions set to Reset to Factory value" }, + { 0x02, "Use DHCP with the given set of DHCPOptions" }, + { 0, NULL } +}; + +#define PNDCP_SUBOPTION_CONTROL_START_TRANS 0x01 +#define PNDCP_SUBOPTION_CONTROL_END_TRANS 0x02 +#define PNDCP_SUBOPTION_CONTROL_SIGNAL 0x03 +#define PNDCP_SUBOPTION_CONTROL_RESPONSE 0x04 +#define PNDCP_SUBOPTION_CONTROL_FACT_RESET 0x05 +#define PNDCP_SUBOPTION_CONTROL_RESET_TO_FACT 0x06 + +static const value_string pn_dcp_suboption_control[] = { + { 0x00, "Reserved" }, + { PNDCP_SUBOPTION_CONTROL_START_TRANS, "Start Transaction" }, + { PNDCP_SUBOPTION_CONTROL_END_TRANS, "End Transaction" }, + { PNDCP_SUBOPTION_CONTROL_SIGNAL, "Signal" }, + { PNDCP_SUBOPTION_CONTROL_RESPONSE, "Response" }, + { PNDCP_SUBOPTION_CONTROL_FACT_RESET, "Reset Factory Settings" }, + { PNDCP_SUBOPTION_CONTROL_RESET_TO_FACT,"Reset to Factory" }, + /*0x07 - 0xff reserved */ + { 0, NULL } +}; + +#define PNDCP_SUBOPTION_DEVICEINITIATIVE 0x01 + +static const value_string pn_dcp_suboption_deviceinitiative[] = { + { 0x00, "Reserved" }, + { PNDCP_SUBOPTION_DEVICEINITIATIVE, "Device Initiative" }, + /*0x00 - 0xff reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_deviceinitiative_value[] = { + { 0x00, "Device does not issue a DCP-Hello-ReqPDU after power on" }, + { 0x01, "Device does issue a DCP-Hello-ReqPDU after power on" }, + /*0x02 - 0xff reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_suboption_all[] = { + { 0xff, "ALL Selector" }, + /* all other reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_suboption_other[] = { + { 0x00, "Default" }, + /* all other reserved */ + { 0, NULL } +}; + +static const value_string pn_dcp_suboption_manuf[] = { + /* none known */ + { 0, NULL } +}; + + + + + +/* dissect the option field */ +static int +dissect_PNDCP_Option(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *block_item, int hfindex, gboolean append_col) +{ + guint8 option; + guint8 suboption; + const value_string *val_str; + + offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hfindex, &option); + switch (option) { + case PNDCP_OPTION_IP: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip, &suboption); + val_str = pn_dcp_suboption_ip; + break; + case PNDCP_OPTION_DEVICE: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device, &suboption); + val_str = pn_dcp_suboption_device; + break; + case PNDCP_OPTION_DHCP: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp, &suboption); + val_str = pn_dcp_suboption_dhcp; + break; + case PNDCP_OPTION_CONTROL: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_control, &suboption); + val_str = pn_dcp_suboption_control; + break; + case PNDCP_OPTION_DEVICEINITIATIVE: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_deviceinitiative, &suboption); + val_str = pn_dcp_suboption_deviceinitiative; + break; + case PNDCP_OPTION_TSN: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_tsn, &suboption); + val_str = pn_dcp_suboption_tsn; + break; + case PNDCP_OPTION_ALLSELECTOR: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_all, &suboption); + val_str = pn_dcp_suboption_all; + break; + default: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_manuf, &suboption); + val_str = pn_dcp_suboption_manuf; + } + + proto_item_append_text(block_item, ", Status from %s - %s", + rval_to_str_const(option, pn_dcp_option, "Unknown"), + val_to_str_const(suboption, val_str, "Unknown")); + + if (append_col) { + col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(suboption, val_str, "Unknown")); + } + + return offset; +} + + +/* dissect the "IP" suboption */ +static int +dissect_PNDCP_Suboption_IP(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *block_item, proto_item *dcp_item, + guint8 service_id, gboolean is_response) +{ + guint8 suboption; + guint16 block_length; + guint16 block_info; + guint16 block_qualifier; + gboolean have_block_info = FALSE; + gboolean have_block_qualifier = FALSE; + guint8 mac[6]; + guint32 ip; + proto_item *item = NULL; + address addr; + + + /* SuboptionIPParameter */ + offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip, &suboption); + /* DCPBlockLength */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); + + switch (suboption) { + case PNDCP_SUBOPTION_IP_MAC: + /* MACAddressValue? */ + pn_append_info(pinfo, dcp_item, ", MAC"); + proto_item_append_text(block_item, "IP/MAC"); + + /* BlockInfo? */ + if (((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || + ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || + ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); + have_block_info = TRUE; + block_length -= 2; + } + + /* BlockQualifier? */ + if ((service_id == PNDCP_SERVICE_ID_SET) && !is_response) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + have_block_qualifier = TRUE; + block_length -= 2; + } + + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_mac_address, mac); + set_address(&addr, AT_ETHER, 6, mac); + proto_item_append_text(block_item, ", MACAddress: %s", address_to_str(pinfo->pool, &addr)); + break; + case PNDCP_SUBOPTION_IP_IP: + pn_append_info(pinfo, dcp_item, ", IP"); + proto_item_append_text(block_item, "IP/IP"); + + /* BlockInfo? */ + if (((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || + ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || + ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { + block_info = tvb_get_ntohs(tvb, offset); + if (tree) { + item = proto_tree_add_uint(tree, hf_pn_dcp_suboption_ip_block_info, tvb, offset, 2, block_info); + } + offset += 2; + proto_item_append_text(block_item, ", BlockInfo: %s", + val_to_str_const(block_info, pn_dcp_suboption_ip_block_info, "Undecoded")); + block_length -= 2; + if (block_info & 0x80) { + expert_add_info(pinfo, item, &ei_pn_dcp_ip_conflict); + } + } + + /* BlockQualifier? */ + if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + block_length -= 2; + } + + /* IPParameterValue ... */ + + /* IPAddress */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_ip, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", IP: %s", address_to_str(pinfo->pool, &addr)); + + /* Subnetmask */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_subnetmask, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", Subnet: %s", address_to_str(pinfo->pool, &addr)); + + /* StandardGateway */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_standard_gateway, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", Gateway: %s", address_to_str(pinfo->pool, &addr)); + break; + case PNDCP_SUBOPTION_IP_FULL_IP_SUITE: + pn_append_info(pinfo, dcp_item, ", MAC"); + proto_item_append_text(block_item, "IP/MAC"); + + /* BlockInfo? */ + if (((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || + ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || + ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); + have_block_info = TRUE; + block_length -= 2; + } + + /* BlockQualifier? */ + if ((service_id == PNDCP_SERVICE_ID_SET) && !is_response) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + have_block_qualifier = TRUE; + block_length -= 2; + } + + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + + /* IPAddress */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_ip, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", IP: %s", address_to_str(pinfo->pool, &addr)); + + /* Subnetmask */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_subnetmask, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", Subnet: %s", address_to_str(pinfo->pool, &addr)); + + /* StandardGateway */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_standard_gateway, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", Gateway: %s", address_to_str(pinfo->pool, &addr)); + + /* IPAddress_1 */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_ip, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", DNSServerIP1: %s", address_to_str(pinfo->pool, &addr)); + + /* IPAddress_2 */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_subnetmask, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", DNSServerIP2: %s", address_to_str(pinfo->pool, &addr)); + + /* IPAddress_3 */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_standard_gateway, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", DNSServerIP3: %s", address_to_str(pinfo->pool, &addr)); + + /* IPAddress_4 */ + offset = dissect_pn_ipv4(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_ip_standard_gateway, &ip); + set_address(&addr, AT_IPv4, 4, &ip); + proto_item_append_text(block_item, ", DNSServerIP4: %s", address_to_str(pinfo->pool, &addr)); + + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); + } + + return offset; +} + + +/* dissect the "device" suboption */ +static int +dissect_PNDCP_Suboption_Device(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *block_item, proto_item *dcp_item, + guint8 service_id, gboolean is_response) +{ + guint8 suboption; + guint16 block_length; + gchar *info_str; + guint8 device_role; + guint16 vendor_id; + guint16 device_id; + char *typeofstation; + char *nameofstation; + char *aliasname; + guint16 block_info = 0; + guint16 block_qualifier = 0; + gboolean have_block_info = FALSE; + gboolean have_block_qualifier = FALSE; + guint8 device_instance_high; + guint8 device_instance_low; + guint16 oem_vendor_id; + guint16 oem_device_id; + proto_item *sub_item; + proto_tree *sub_tree; + conversation_t *conversation; + stationInfo *station_info; + + /* SuboptionDevice... */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device, &suboption); + /* DCPBlockLength */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); + + /* BlockInfo? */ + if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || + ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || + ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); + have_block_info = TRUE; + block_length -= 2; + } + + /* BlockQualifier? */ + if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + have_block_qualifier = TRUE; + block_length -= 2; + } + + switch (suboption) { + case PNDCP_SUBOPTION_DEVICE_MANUF: + /* + * XXX - IEC 61158-6-10 Edition 4.0, section 4.3, says this field + * "shall be coded as data type VisibleString", and that VisibleString + * is "ISO/IEC 646 - International Reference Version without the "del" + * (coding 0x7F) character", i.e. ASCII. + * + * However, at least one capture has a packet where 0xAE is used in + * a place where a registered trademark symbol would be appropriate, + * so the host sending it apparently extended ASCII to ISO 8859-n + * for some value of n. That may have just been an error on their + * part, not realizing that they should have done "(R)" or something + * such as that. + */ + proto_tree_add_item_ret_display_string (tree, hf_pn_dcp_suboption_device_typeofstation, tvb, offset, block_length, ENC_ASCII, pinfo->pool, &typeofstation); + pn_append_info(pinfo, dcp_item, ", DeviceVendorValue"); + proto_item_append_text(block_item, "Device/Manufacturer specific"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info){ + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + proto_item_append_text(block_item, ", DeviceVendorValue: \"%s\"", typeofstation); + + + if (PINFO_FD_VISITED(pinfo) == FALSE) { + /* Create a conversation between the MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, need to switch dl_src & dl_dst if not a response + * All conversations are based on Device MAC as addr1 */ + if (is_response) { + conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + } + else { + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_NONE, 0, 0, 0); + } + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, proto_pn_dcp); + if (station_info == NULL) { + station_info = wmem_new0(wmem_file_scope(), stationInfo); + init_pnio_rtc1_station(station_info); + conversation_add_proto_data(conversation, proto_pn_dcp, station_info); + } + + station_info->typeofstation = wmem_strdup(wmem_file_scope(), typeofstation); + } + + offset += block_length; + break; + + case PNDCP_SUBOPTION_DEVICE_NAMEOFSTATION: + /* + * XXX - IEC 61158-6-10 Edition 4.0 says, in section 4.3.1.4.15 + * "Coding of the field NameOfStationValue", that "This field shall + * be coded as data type OctetString with 1 to 240 octets. The + * definition of IETF RFC 5890 and the following syntax applies: ..." + * + * RFC 5890 means Punycode; should we translate the domain name to + * UTF-8 and show both the untranslated and translated domain name? + * + * They don't mention anything about the RFC 1035 encoding of + * domain names as mentioned in section 3.1 "Name space definitions", + * with the labels being counted strings; does that mean that this + * is just an ASCII string to be interpreted as a Punycode Unicode + * domain name? + */ + proto_tree_add_item_ret_display_string (tree, hf_pn_dcp_suboption_device_nameofstation, tvb, offset, block_length, ENC_ASCII, pinfo->pool, &nameofstation); + pn_append_info(pinfo, dcp_item, wmem_strdup_printf(pinfo->pool, ", NameOfStation:\"%s\"", nameofstation)); + proto_item_append_text(block_item, "Device/NameOfStation"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + proto_item_append_text(block_item, ", \"%s\"", nameofstation); + + + if (PINFO_FD_VISITED(pinfo) == FALSE) { + /* Create a conversation between the MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, need to switch dl_src & dl_dst if not a response + * All conversations are based on Device MAC as addr1 */ + if (is_response) { + conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + } + else { + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_NONE, 0, 0, 0); + } + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, proto_pn_dcp); + if (station_info == NULL) { + station_info = wmem_new0(wmem_file_scope(), stationInfo); + init_pnio_rtc1_station(station_info); + conversation_add_proto_data(conversation, proto_pn_dcp, station_info); + } + + station_info->nameofstation = wmem_strdup(wmem_file_scope(), nameofstation); + } + + offset += block_length; + break; + + case PNDCP_SUBOPTION_DEVICE_DEV_ID: + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_vendor_id, &vendor_id); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_id, &device_id); + + if (PINFO_FD_VISITED(pinfo) == FALSE) { + /* Create a conversation between the MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + /* Create new conversation, need to switch dl_src & dl_dst if not a response + * All conversations are based on Device MAC as addr1 */ + if (is_response) { + conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + } + else { + conversation = conversation_new(pinfo->num, &pinfo->dl_dst, &pinfo->dl_src, CONVERSATION_NONE, 0, 0, 0); + } + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, proto_pn_dcp); + if (station_info == NULL) { + station_info = wmem_new0(wmem_file_scope(), stationInfo); + init_pnio_rtc1_station(station_info); + conversation_add_proto_data(conversation, proto_pn_dcp, station_info); + } + + station_info->u16Vendor_id = vendor_id; + station_info->u16Device_id = device_id; + } + + + pn_append_info(pinfo, dcp_item, ", Dev-ID"); + proto_item_append_text(block_item, "Device/Device ID"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + proto_item_append_text(block_item, ", VendorID: 0x%04x / DeviceID: 0x%04x", vendor_id, device_id); + break; + case PNDCP_SUBOPTION_DEVICE_DEV_ROLE: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_role, &device_role); + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_reserved8, NULL); + pn_append_info(pinfo, dcp_item, ", Dev-Role"); + proto_item_append_text(block_item, "Device/Device Role"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) + proto_item_append_text(block_item, ", BlockInfo: %s", rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + if (device_role & 0x01) + proto_item_append_text(block_item, ", IO-Device"); + if (device_role & 0x02) + proto_item_append_text(block_item, ", IO-Controller"); + if (device_role & 0x04) + proto_item_append_text(block_item, ", IO-Multidevice"); + if (device_role & 0x08) + proto_item_append_text(block_item, ", PN-Supervisor"); + break; + case PNDCP_SUBOPTION_DEVICE_DEV_OPTIONS: + info_str = wmem_strdup_printf(pinfo->pool, ", Dev-Options(%u)", block_length/2); + pn_append_info(pinfo, dcp_item, info_str); + proto_item_append_text(block_item, "Device/Device Options"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + proto_item_append_text(block_item, ", %u options", block_length/2); + for( ; block_length != 0; block_length -= 2) { + offset = dissect_PNDCP_Option(tvb, offset, pinfo, tree, NULL /*block_item*/, hf_pn_dcp_option, + FALSE /* append_col */); + } + break; + case PNDCP_SUBOPTION_DEVICE_ALIAS_NAME: + /* + * XXX - IEC 61158-6-10 Edition 4.0, section 4.3.1.4.17 "Coding of + * the field AliasNameValue", says this field "shall be coded as + * OctetString. The content shall be the concatenation of the content + * of the fields NameOfPort and NameOfStation. + * + * AliasNameValue = NameOfPort + "." + NameOfStation + * + * " and: + * + * It says in section 4.3.1.4.16 "Coding of the field NameOfPort" + * that "This field shall be coded as OctetString[8] or + * OctetString[14] as "port-xyz" or "port-xyz-rstuv" where x, y, + * z is in the range "0"-"9" from 001 up to 255 and r, s, t, u, v + * is in the range "0"-"9" from 00000 up to 65535. ... + * Furthermore, the definition of IETF RFC 5890 shall be applied." + * + * That suggests that the Octets are probably just ASCII characters; + * IETF RFC 5890 means Punycode, but there isn't anything in those + * string formats that requires non-ASCII characters - they're + * just literally "port-" followed by numbers and hyphens. + * + * It says in section 4.3.1.4.15 "Coding of the field + * NameOfStationValue" that it's a domain name, complete with + * RFC 5890 Punycode. + */ + proto_tree_add_item_ret_display_string (tree, hf_pn_dcp_suboption_device_aliasname, tvb, offset, block_length, ENC_ASCII, pinfo->pool, &aliasname); + pn_append_info(pinfo, dcp_item, wmem_strdup_printf(pinfo->pool, ", AliasName:\"%s\"", aliasname)); + proto_item_append_text(block_item, "Device/AliasName"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + proto_item_append_text(block_item, ", \"%s\"", aliasname); + offset += block_length; + break; + case PNDCP_SUBOPTION_DEVICE_DEV_INSTANCE: + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_instance_high, &device_instance_high); + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_instance_low, &device_instance_low); + pn_append_info(pinfo, dcp_item, ", Dev-Instance"); + proto_item_append_text(block_item, "Device/Device Instance"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + proto_item_append_text(block_item, ", InstanceHigh: %d, Instance Low: %d", + device_instance_high, device_instance_low); + break; + case PNDCP_SUBOPTION_DEVICE_OEM_DEV_ID: + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_oem_ven_id, &oem_vendor_id); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_device_oem_dev_id, &oem_device_id); + pn_append_info(pinfo, dcp_item, ", OEM-Dev-ID"); + proto_item_append_text(block_item, "Device/OEM Device ID"); + if(have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if(have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + proto_item_append_text(block_item, ", OEMVendorID: 0x%04x / OEMDeviceID: 0x%04x", oem_vendor_id, oem_device_id); + break; + case PNDCP_SUBOPTION_DEVICE_RSI_PROPERTIES: + sub_item = proto_tree_add_item(tree, hf_pn_dcp_rsi_properties_value, tvb, offset, 2, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_dcp_rsi_properties_value); + + static int* const flags[] = { + &hf_pn_dcp_rsi_properties_value_bit0, + &hf_pn_dcp_rsi_properties_value_bit1, + &hf_pn_dcp_rsi_properties_value_bit2, + &hf_pn_dcp_rsi_properties_value_bit3, + &hf_pn_dcp_rsi_properties_value_bit4, + &hf_pn_dcp_rsi_properties_value_bit5, + &hf_pn_dcp_rsi_properties_value_otherbits, + NULL + }; + + proto_tree_add_bitmask(sub_tree, tvb, offset, hf_pn_dcp_rsi_properties_value, ett_pn_dcp_rsi_properties_value, flags, ENC_BIG_ENDIAN); + + offset = offset + 2; + + if (pinfo->fd->visited == FALSE) { + /* Create a conversation between the MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, proto_pn_dcp); + if (station_info == NULL) { + station_info = wmem_new0(wmem_file_scope(), stationInfo); + init_pnio_rtc1_station(station_info); + conversation_add_proto_data(conversation, proto_pn_dcp, station_info); + } + } + + pn_append_info(pinfo, dcp_item, ", RSI-Properties"); + proto_item_append_text(block_item, "Device/RSI Properties"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); + } + + return offset; +} + +/* dissect the "tsn" suboption */ +static int +dissect_PNDCP_Suboption_TSN(tvbuff_t* tvb, int offset, packet_info* pinfo, + proto_tree* tree, proto_item* block_item, proto_item* dcp_item, + guint8 service_id, gboolean is_response) +{ + guint8 suboption; + guint16 block_length; + char *domain_name; + guint16 nme_prio; + e_guid_t tsn_domain_uuid; + e_guid_t nme_parameter_uuid; + e_guid_t nme_name_uuid; + guint16 vendor_id; + guint16 device_id; + guint16 block_info = 0; + guint16 block_qualifier = 0; + gboolean have_block_info = FALSE; + gboolean have_block_qualifier = FALSE; + guint8 instance_id_high; + guint8 instance_id_low; + conversation_t* conversation; + stationInfo* station_info; + gboolean is_zeros = TRUE; + + /* SuboptionTSN... */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_tsn, &suboption); + + /* DCPBlockLength */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); + + /* BlockInfo? */ + if (((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || + ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || + ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); + have_block_info = TRUE; + block_length -= 2; + } + + /* BlockQualifier? */ + if ((service_id == PNDCP_SERVICE_ID_SET) && !is_response) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + have_block_qualifier = TRUE; + block_length -= 2; + } + + switch (suboption) { + case PNDCP_SUBOPTION_TSN_DOMAIN_NAME: + + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_tsn_domain_uuid, &tsn_domain_uuid); + proto_tree_add_item_ret_display_string(tree, hf_pn_dcp_suboption_tsn_domain_name, tvb, offset, (block_length-16), ENC_ASCII | ENC_NA, pinfo->pool, &domain_name); + + pn_append_info(pinfo, dcp_item, ", TSN-Domain Name"); + proto_item_append_text(block_item, "TSN/TSN-Domain Name"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) + proto_item_append_text(block_item, ", BlockInfo: %s", rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + + pn_append_info(pinfo, dcp_item, wmem_strdup_printf(pinfo->pool, ", DomainName:\"%s\"", domain_name)); + proto_item_append_text(block_item, ", \"%s\"", domain_name); + offset += (block_length-16); + is_zeros = TRUE; + + for (int i = 0; i < 8; i++) + { + if (tsn_domain_uuid.data4[i] != 0) + { + is_zeros = FALSE; + break; + } + } + + if ((tsn_domain_uuid.data1 == 0) && (tsn_domain_uuid.data2 == 0) && (tsn_domain_uuid.data3 == 0) && (is_zeros)) + proto_item_append_text(block_item, ", No TSN domain assigned"); + else + proto_item_append_text(block_item, ", UUID identifying a TSN domain using SNMP/ LLDP/ DCP"); + + break; + + case PNDCP_SUBOPTION_TSN_NME_MANAGER: + + pn_append_info(pinfo, dcp_item, ", NME-Manager"); + proto_item_append_text(block_item, "TSN/NME-Manager"); + + if (have_block_qualifier) + { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + + if (have_block_info) + { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_tsn_nme_prio, &nme_prio); + proto_item_append_text(block_item, ", BlockInfo: %s", rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + + if (nme_prio == 0x0000) + proto_item_append_text(block_item, ", Highest priority NME manager"); + else if ((0x0001 <= nme_prio) && (nme_prio <= 0x3000)) + proto_item_append_text(block_item, ", High priorities for NME manager"); + else if ((0x3001 <= nme_prio) && (nme_prio <= 0x9FFF)) + proto_item_append_text(block_item, ", Low priorities for NME manager"); + else if (0xA000 == nme_prio) + proto_item_append_text(block_item, ", Lowest priority for NME manager / Default priority for NME manager"); + else + proto_item_append_text(block_item, ", Reserved"); + } + + break; + + case PNDCP_SUBOPTION_TSN_NME_PARAMETER_UUID: + + pn_append_info(pinfo, dcp_item, ", NME-Parameter UUID"); + proto_item_append_text(block_item, "TSN/NME-Parameter UUID"); + + if (block_length > 0) + { + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_tsn_nme_parameter_uuid, &nme_parameter_uuid); + + if (have_block_qualifier) + { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) + proto_item_append_text(block_item, ", BlockInfo: %s", rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + + is_zeros = TRUE; + + for (int i = 0; i < 8; i++) + { + if (nme_parameter_uuid.data4[i] != 0) + { + is_zeros = FALSE; + break; + } + } + if ((nme_parameter_uuid.data1 == 0) && (nme_parameter_uuid.data2 == 0) && (nme_parameter_uuid.data3 == 0) && (is_zeros)) + proto_item_append_text(block_item, ", Unconfigured"); + else + proto_item_append_text(block_item, ", UUID identifying an NME parameter set within the TSN domain."); + } + break; + + case PNDCP_SUBOPTION_TSN_NME_AGENT: + + pn_append_info(pinfo, dcp_item, ", NME-Agent"); + proto_item_append_text(block_item, "TSN/NME-Agent"); + + if (have_block_qualifier) + { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + + if (have_block_info) + { + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_tsn_nme_agent, &nme_name_uuid); + proto_item_append_text(block_item, ", BlockInfo: %s", rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + + is_zeros = TRUE; + for (int i = 0; i < 8; i++) + { + if (nme_name_uuid.data4[i] != 0) + { + is_zeros = FALSE; + break; + } + } + + if ((nme_name_uuid.data1 == 0) && (nme_name_uuid.data2 == 0) && (nme_name_uuid.data3 == 0) && (is_zeros)) + proto_item_append_text(block_item, ", No NME assigned"); + else + proto_item_append_text(block_item, ", UUID identifying an NME using SNMP / LLDP / DCP"); + } + break; + + case PNDCP_SUBOPTION_TSN_CIM_INTERFACE: + + pn_append_info(pinfo, dcp_item, ", CIM-Interface"); + proto_item_append_text(block_item, "TSN/CIM-Interface"); + + if (have_block_qualifier) + { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) + { + // CIMVDIValue + dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_vendor_id_high, &vendor_id); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_vendor_id_low, &vendor_id); + + dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_device_id_high, &device_id); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_device_id_low, &device_id); + + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_instance_id_high, &instance_id_high); + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_instance_id_low, &instance_id_low); + + if (pinfo->fd->visited == FALSE) { + /* Create a conversation between the MAC addresses */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + if (conversation == NULL) { + conversation = conversation_new(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, proto_pn_dcp); + if (station_info == NULL) { + station_info = wmem_new0(wmem_file_scope(), stationInfo); + init_pnio_rtc1_station(station_info); + conversation_add_proto_data(conversation, proto_pn_dcp, station_info); + } + + station_info->u16Vendor_id = vendor_id; + station_info->u16Device_id = device_id; + } + + proto_item_append_text(block_item, ", BlockInfo: %s", rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + + proto_item_append_text(block_item, ", VendorID: 0x%04x / DeviceID: 0x%04x / InstanceIDHigh: 0x%04x / InstanceIDLow: 0x%04x", vendor_id, device_id, instance_id_high, instance_id_low); + } + break; + + default: + pn_append_info(pinfo, dcp_item, ", TSN/Reserved"); + proto_item_append_text(block_item, "TSN/Reserved"); + } + + return offset; +} + +/* dissect the "DHCP" suboption */ +static int +dissect_PNDCP_Suboption_DHCP(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *block_item, proto_item *dcp_item, + guint8 service_id _U_, gboolean is_response _U_) +{ + guint8 suboption; + guint8 option_code = 0; + guint16 block_length; + guint16 block_info = 0; + guint16 block_qualifier = 0; + guint8 dhcpparameterlength = 0; + guint8 dhcpparameterdata = 0; + guint8 dhcpcontrolparameterdata = 0; + gboolean have_block_info = FALSE; + gboolean have_block_qualifier = FALSE; + int expected_offset; + + + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp, &suboption); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); + + expected_offset = offset + block_length; + + /* BlockInfo? */ + if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || + ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || + ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); + have_block_info=TRUE; + block_length -= 2; + } + /* BlockQualifier? */ + if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + have_block_qualifier=TRUE; + block_length -= 2; + } + + switch (suboption) { + case PNDCP_SUBOPTION_DHCP_CLIENT_ID: + pn_append_info(pinfo, dcp_item, ", DHCP client identifier"); + proto_item_append_text(block_item, "DHCP/Client-ID"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp_option_code, &option_code); + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp_parameter_length, &dhcpparameterlength); + if (dhcpparameterlength > 0) { + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp_parameter_data, &dhcpparameterdata); + if (dhcpparameterlength == 1) { + if (dhcpparameterdata == 1) { + proto_item_append_text(block_item, ", Client-ID: MAC Address"); + } + else { + proto_item_append_text(block_item, ", Client-ID: Name of Station"); + } + } + else { + proto_item_append_text(block_item, ", Client-ID: Arbitrary"); + /* + * XXX - IEC 61158-6-10 Edition 4.0, section 4.3.1.4.21.5 + * "Use of arbitrary client identifier", that this is an + * OctetString to be used as a client identifier with DHCP. + * + * Does that mean it should be FT_BYTES, possibly with + * the BASE_SHOW_ASCII_PRINTABLE flag to show it as ASCII + * iff it's printable? Or should packet-dhcp.c export + * dissect_dhcpopt_client_identifier(), so that we can + * use its heuristics? + */ + proto_tree_add_item(tree, hf_pn_dcp_suboption_dhcp_arbitrary_client_id, tvb, offset, dhcpparameterlength - 1, ENC_ASCII); + offset += (dhcpparameterlength-1); + } + } + break; + case PNDCP_SUBOPTION_DHCP_CONTROL_FOR_ADDRESS_RES: + pn_append_info(pinfo, dcp_item, ", Control DHCP for address resolution"); + proto_item_append_text(block_item, "DHCP/Control DHCP for address resolution"); + if (have_block_qualifier) { + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + } + if (have_block_info) { + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + } + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp_option_code, &option_code); + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp_parameter_length, &dhcpparameterlength); + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_dhcp_control_parameter_data, &dhcpcontrolparameterdata); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); + } + + if (expected_offset > offset) { + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, expected_offset - offset, "Undefined"); + } + + return offset; +} + + +/* dissect the "control" suboption */ +static int +dissect_PNDCP_Suboption_Control(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *block_item, proto_item *dcp_item, + guint8 service_id _U_, gboolean is_response _U_) +{ + guint8 suboption; + guint16 block_length; + guint16 block_qualifier; + guint16 BlockQualifier; + guint16 u16SignalValue; + gchar *info_str; + guint8 block_error; + proto_item *item = NULL; + + + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_control, &suboption); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); + + if (service_id == PNDCP_SERVICE_ID_SET && block_length == 0) { + pn_append_info(pinfo, dcp_item, ", Erroneous DCPSet block"); + proto_item_append_text(block_item, "Control/Erroneous DCPSet block"); + } + else { + switch (suboption) { + case PNDCP_SUBOPTION_CONTROL_START_TRANS: + pn_append_info(pinfo, dcp_item, ", Start-Trans"); + proto_item_append_text(block_item, "Control/Start-Transaction"); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + break; + case PNDCP_SUBOPTION_CONTROL_END_TRANS: + pn_append_info(pinfo, dcp_item, ", End-Trans"); + proto_item_append_text(block_item, "Control/End-Transaction"); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + break; + case PNDCP_SUBOPTION_CONTROL_SIGNAL: + pn_append_info(pinfo, dcp_item, ", Signal"); + proto_item_append_text(block_item, "Control/Signal"); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + block_length -= 2; + + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_control_signal_value, &u16SignalValue); + break; + case PNDCP_SUBOPTION_CONTROL_RESPONSE: + proto_item_append_text(block_item, "Control/Response"); + offset = dissect_PNDCP_Option(tvb, offset, pinfo, tree, block_item, hf_pn_dcp_suboption_control_option, + FALSE /* append_col */); + block_error = tvb_get_guint8(tvb, offset); + if (tree) { + item = proto_tree_add_uint(tree, hf_pn_dcp_block_error, tvb, offset, 1, block_error); + } + offset += 1; + if (block_error != 0) { + expert_add_info_format(pinfo, item, &ei_pn_dcp_block_error_unknown, "%s", + val_to_str_const(block_error, pn_dcp_block_error, "Unknown")); + } + info_str = wmem_strdup_printf(pinfo->pool, ", Response(%s)", + val_to_str_const(block_error, pn_dcp_block_error, "Unknown")); + pn_append_info(pinfo, dcp_item, info_str); + proto_item_append_text(block_item, ", BlockError: %s", + val_to_str_const(block_error, pn_dcp_block_error, "Unknown")); + + break; + case PNDCP_SUBOPTION_CONTROL_FACT_RESET: + pn_append_info(pinfo, dcp_item, ", Reset FactorySettings"); + proto_item_append_text(block_item, "Control/Reset FactorySettings"); + block_length -= 2; + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_blockqualifier, &BlockQualifier); + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(BlockQualifier, pn_dcp_suboption_other, "reserved")); + block_length -= 2; + break; + + case PNDCP_SUBOPTION_CONTROL_RESET_TO_FACT: + pn_append_info(pinfo, dcp_item, ", Reset to Factory"); + proto_item_append_text(block_item, "Reset to FactorySettings"); + + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_blockqualifier_r2f, &BlockQualifier); + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(BlockQualifier, pn_dcp_BlockQualifier, "reserved")); + block_length -= 2; + + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); + } + } + + return offset; +} + + +/* dissect the "deviceinitaitve" suboption */ +static int +dissect_PNDCP_Suboption_DeviceInitiative(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *block_item, proto_item *dcp_item, + guint8 service_id, gboolean is_response) +{ + guint8 suboption; + guint16 block_length; + guint16 block_info; + guint16 block_qualifier; + guint16 value; + + + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_deviceinitiative, &suboption); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); + + pn_append_info(pinfo, dcp_item, ", DeviceInitiative"); + proto_item_append_text(block_item, "DeviceInitiative/DeviceInitiative"); + + /* BlockInfo? */ + if ( ((service_id == PNDCP_SERVICE_ID_IDENTIFY) && is_response) || + ((service_id == PNDCP_SERVICE_ID_HELLO) && !is_response) || + ((service_id == PNDCP_SERVICE_ID_GET) && is_response)) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_info, &block_info); + proto_item_append_text(block_item, ", BlockInfo: %s", + rval_to_str_const(block_info, pn_dcp_block_info, "Unknown")); + block_length -= 2; + } + + /* BlockQualifier? */ + if ( (service_id == PNDCP_SERVICE_ID_SET) && !is_response) { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_qualifier, &block_qualifier); + proto_item_append_text(block_item, ", BlockQualifier: %s", + val_to_str_const(block_qualifier, pn_dcp_block_qualifier, "Unknown")); + block_length -= 2; + } + + /* DeviceInitiativeValue */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_deviceinitiative_value, &value); + + return offset; +} + + +/* dissect the "all" suboption */ +static int +dissect_PNDCP_Suboption_All(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *block_item, proto_item *dcp_item, + guint8 service_id _U_, gboolean is_response _U_) +{ + guint8 suboption; + guint16 block_length; + + + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_dcp_suboption_all, &suboption); + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); + + switch (suboption) { + case 255: /* All */ + pn_append_info(pinfo, dcp_item, ", All"); + proto_item_append_text(block_item, "All/All"); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); + } + + return offset; +} + + +/* dissect the "manufacturer" suboption */ +static int +dissect_PNDCP_Suboption_Manuf(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *block_item, proto_item *dcp_item, + guint8 service_id _U_, gboolean is_response _U_) +{ + guint16 block_length; + + offset = dissect_pn_uint8( tvb, offset, pinfo, tree, hf_pn_dcp_suboption_manuf, NULL); + + pn_append_info(pinfo, dcp_item, ", Manufacturer Specific"); + proto_item_append_text(block_item, "Manufacturer Specific"); + + if (tvb_reported_length_remaining(tvb, offset)>0) + { + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_block_length, &block_length); + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, block_length); + } + return offset; +} + + +/* dissect one DCP block */ +static int +dissect_PNDCP_Block(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, proto_item *dcp_item, + guint8 service_id, gboolean is_response) +{ + guint8 option; + proto_item *block_item; + proto_tree *block_tree; + int ori_offset = offset; + + /* subtree for block */ + block_item = proto_tree_add_none_format(tree, hf_pn_dcp_block, + tvb, offset, 0, "Block: "); + block_tree = proto_item_add_subtree(block_item, ett_pn_dcp_block); + + + offset = dissect_pn_uint8(tvb, offset, pinfo, block_tree, hf_pn_dcp_option, &option); + + if (option == PNDCP_OPTION_IP) + { + offset = dissect_PNDCP_Suboption_IP(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); + } + else if (option == PNDCP_OPTION_DEVICE) + { + offset = dissect_PNDCP_Suboption_Device(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); + } + else if (option == PNDCP_OPTION_DHCP) + { + offset = dissect_PNDCP_Suboption_DHCP(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); + } + else if (option == PNDCP_OPTION_CONTROL) + { + offset = dissect_PNDCP_Suboption_Control(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); + } + else if (option == PNDCP_OPTION_DEVICEINITIATIVE) + { + offset = dissect_PNDCP_Suboption_DeviceInitiative(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); + } + else if (option == PNDCP_OPTION_TSN) + { + offset = dissect_PNDCP_Suboption_TSN(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); + } + else if (option == PNDCP_OPTION_ALLSELECTOR) + { + offset = dissect_PNDCP_Suboption_All(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); + } + else if (PNDCP_OPTION_MANUF_X80 <= option && option <= PNDCP_OPTION_MANUF_XFE) + { + offset = dissect_PNDCP_Suboption_Manuf(tvb, offset, pinfo, block_tree, block_item, dcp_item, service_id, is_response); + } + else + { + pn_append_info(pinfo, dcp_item, ", Reserved"); + proto_item_append_text(block_item, "Reserved"); + /* there isn't a predefined suboption type for reserved option, rest of the block will be seen as padding */ + } + + proto_item_set_len(block_item, offset-ori_offset); + + if (((offset-ori_offset) & 1) && (tvb_reported_length_remaining(tvb, offset) > 0)) { + /* we have an odd number of bytes in this block, add a padding byte */ + offset = dissect_pn_padding(tvb, offset, pinfo, tree, 1); + } + + return offset; +} + + +/* dissect a whole DCP PDU */ +static void +dissect_PNDCP_PDU(tvbuff_t *tvb, + packet_info *pinfo, proto_tree *tree, proto_item *dcp_item) +{ + guint8 service_id; + guint8 service_type; + guint32 xid; + guint16 response_delay; + guint16 data_length; + int offset = 0; + gchar *xid_str; + gboolean is_response = FALSE; + + + offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hf_pn_dcp_service_id, &service_id); + offset = dissect_pn_uint8 (tvb, offset, pinfo, tree, hf_pn_dcp_service_type, &service_type); + proto_tree_add_item_ret_uint(tree, hf_pn_dcp_xid, tvb, offset, 4, ENC_BIG_ENDIAN, &xid); + offset += 4; + if (service_id == PNDCP_SERVICE_ID_IDENTIFY && service_type == PNDCP_SERVICE_TYPE_REQUEST) { + /* multicast header */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_response_delay, &response_delay); + } else { + /* unicast header */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_reserved16, NULL); + } + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_dcp_data_length, &data_length); + + switch (service_id) { + case PNDCP_SERVICE_ID_GET: + pn_append_info(pinfo, dcp_item, "Get"); + break; + case PNDCP_SERVICE_ID_SET: + pn_append_info(pinfo, dcp_item, "Set"); + break; + case PNDCP_SERVICE_ID_IDENTIFY: + pn_append_info(pinfo, dcp_item, "Ident"); + break; + case PNDCP_SERVICE_ID_HELLO: + pn_append_info(pinfo, dcp_item, "Hello"); + break; + default: + dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset)); + return; + } + + switch (service_type) { + case PNDCP_SERVICE_TYPE_REQUEST: + pn_append_info(pinfo, dcp_item, " Req"); + break; + case PNDCP_SERVICE_TYPE_RESPONSE_SUCCESS: + pn_append_info(pinfo, dcp_item, " Ok "); + is_response = TRUE; + break; + case PNDCP_SERVICE_TYPE_RESPONSE_UNSUPPORTED: + pn_append_info(pinfo, dcp_item, " unsupported"); + is_response = TRUE; + break; + default: + dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset)); + return; + } + + xid_str = wmem_strdup_printf(pinfo->pool, ", Xid:0x%x", xid); + pn_append_info(pinfo, dcp_item, xid_str); + + /* dissect a number of blocks (depending on the remaining length) */ + while(data_length) { + int ori_offset = offset; + + if (service_id == PNDCP_SERVICE_ID_GET && service_type == PNDCP_SERVICE_TYPE_REQUEST) { + /* Selectors */ + offset = dissect_PNDCP_Option(tvb, offset, pinfo, + tree, dcp_item, hf_pn_dcp_option, TRUE /* append_col */); + } else { + offset = dissect_PNDCP_Block(tvb, offset, pinfo, tree, dcp_item, service_id, is_response); + } + /* prevent an infinite loop */ + if (offset <= ori_offset || data_length < (offset - ori_offset)) { + proto_tree_add_expert(tree, pinfo, &ei_pn_dcp_block_parse_error, + tvb, ori_offset, tvb_captured_length_remaining(tvb, ori_offset)); + break; + } + data_length -= (offset - ori_offset); + } +} + + +/* possibly dissect a PN-RT packet (frame ID must be in the appropriate range) */ +static gboolean +dissect_PNDCP_Data_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + void *data) +{ + /* the tvb will NOT contain the frame_id here, so get it from dissection data! */ + guint16 u16FrameID = GPOINTER_TO_UINT(data); + proto_item *item; + proto_tree *dcp_tree; + + + /* frame id must be in valid range (acyclic Real-Time, DCP) */ + if (u16FrameID < FRAME_ID_DCP_HELLO || u16FrameID > FRAME_ID_DCP_IDENT_RES) { + /* we are not interested in this packet */ + return FALSE; + } + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-DCP"); + col_clear(pinfo->cinfo, COL_INFO); + + /* subtree for DCP */ + item = proto_tree_add_protocol_format(tree, proto_pn_dcp, tvb, 0, tvb_get_ntohs(tvb, 8) + 10, + "PROFINET DCP, "); + dcp_tree = proto_item_add_subtree(item, ett_pn_dcp); + + /* dissect this PDU */ + dissect_PNDCP_PDU(tvb, pinfo, dcp_tree, item); + + return TRUE; +} + + +void +proto_register_pn_dcp (void) +{ + static hf_register_info hf[] = { + { &hf_pn_dcp_service_id, + { "ServiceID", "pn_dcp.service_id", + FT_UINT8, BASE_DEC, VALS(pn_dcp_service_id), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_service_type, + { "ServiceType", "pn_dcp.service_type", + FT_UINT8, BASE_DEC, VALS(pn_dcp_service_type), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_xid, + { "Xid", "pn_dcp.xid", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_reserved8, + { "Reserved", "pn_dcp.reserved8", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_reserved16, + { "Reserved", "pn_dcp.reserved16", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_response_delay, + { "ResponseDelay", "pn_dcp.response_delay", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_data_length, + { "DCPDataLength", "pn_dcp.data_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_block_length, + { "DCPBlockLength", "pn_dcp.block_length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_option, + { "Option", "pn_dcp.option", + FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(pn_dcp_option), 0x0, + NULL, HFILL }}, + +#if 0 + { &hf_pn_dcp_suboption, + { "Suboption", "pn_dcp.suboption", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, +#endif + + { &hf_pn_dcp_block_error, + { "BlockError", "pn_dcp.block_error", + FT_UINT8, BASE_DEC, VALS(pn_dcp_block_error), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_block, + { "Block", "pn_dcp.block", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_block_info, + { "BlockInfo", "pn_dcp.block_info", + FT_UINT16, BASE_DEC|BASE_RANGE_STRING, RVALS(pn_dcp_block_info), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_block_qualifier, + { "BlockQualifier", "pn_dcp.block_qualifier", + FT_UINT16, BASE_DEC, VALS(pn_dcp_block_qualifier), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_blockqualifier_r2f, + { "BlockQualifier: ResettoFactory", "pn_dcp.block_qualifier_reset", + FT_UINT16, BASE_DEC, VALS(pn_dcp_BlockQualifier), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_blockqualifier, + { "BlockQualifier: ResetFactorySettings", "pn_dcp.block_qualifier_reset", + FT_UINT16, BASE_DEC, VALS(pn_dcp_suboption_other), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_ip, + { "Suboption", "pn_dcp.suboption_ip", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_ip), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_ip_block_info, + { "BlockInfo", "pn_dcp.suboption_ip_block_info", + FT_UINT16, BASE_DEC, VALS(pn_dcp_suboption_ip_block_info), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_ip_mac_address, + { "MAC Address", "pn_dcp.suboption_ip_mac_address", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_ip_ip, + { "IPaddress", "pn_dcp.suboption_ip_ip", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_ip_subnetmask, + { "Subnetmask", "pn_dcp.suboption_ip_subnetmask", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_ip_standard_gateway, + { "StandardGateway", "pn_dcp.suboption_ip_standard_gateway", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device, + { "Suboption", "pn_dcp.suboption_device", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_device), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_typeofstation, + { "DeviceVendorValue", "pn_dcp.suboption_device_devicevendorvalue", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_nameofstation, + { "NameOfStation", "pn_dcp.suboption_device_nameofstation", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_vendor_id, + { "VendorID", "pn_dcp.suboption_vendor_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_id, + { "DeviceID", "pn_dcp.suboption_device_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_role, + { "DeviceRoleDetails", "pn_dcp.suboption_device_role", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_aliasname, + { "AliasName", "pn_dcp.suboption_device_aliasname", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_instance_high, + { "DeviceInstanceHigh", "pn_dcp.suboption_device_instance", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_instance_low, + { "DeviceInstanceLow", "pn_dcp.suboption_device_instance", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_oem_ven_id, + { "OEMVendorID", "pn_dcp.suboption_device_oem_ven_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_device_oem_dev_id, + { "OEMDeviceID", "pn_dcp.suboption_device_oem_dev_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_rsi_properties_value, + { "RsiPropertiesValue", "pn_dcp.suboption_device_rsi_properties_value", + FT_UINT16, BASE_HEX, 0, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_rsi_properties_value_bit0, + { "IP Stack", "pn_dcp.suboption_device_rsi_properties_value.bit0", + FT_BOOLEAN, 16, TFS(&pn_dcp_rsi_properties_value_bit), 0x0001, + NULL, HFILL } }, + + { &hf_pn_dcp_rsi_properties_value_bit1, + { "CLRPC Interface", "pn_dcp.suboption_device_rsi_properties_value.bit1", + FT_BOOLEAN, 16, TFS(&pn_dcp_rsi_properties_value_bit), 0x0002, + NULL, HFILL } }, + + { &hf_pn_dcp_rsi_properties_value_bit2, + { "RSI AR Interface", "pn_dcp.suboption_device_rsi_properties_value.bit2", + FT_BOOLEAN, 16, TFS(&pn_dcp_rsi_properties_value_bit), 0x0004, + NULL, HFILL } }, + + { &hf_pn_dcp_rsi_properties_value_bit3, + { "RSI AR Read Implicit Interface", "pn_dcp.suboption_device_rsi_properties_value.bit3", + FT_BOOLEAN, 16, TFS(&pn_dcp_rsi_properties_value_bit), 0x0008, + NULL, HFILL } }, + + { &hf_pn_dcp_rsi_properties_value_bit4, + { "RSI CIM Interface", "pn_dcp.suboption_device_rsi_properties_value.bit4", + FT_BOOLEAN, 16, TFS(&pn_dcp_rsi_properties_value_bit), 0x0010, + NULL, HFILL } }, + + { &hf_pn_dcp_rsi_properties_value_bit5, + { "RSI CIM Read Implicit Interface", "pn_dcp.suboption_device_rsi_properties_value.bit5", + FT_BOOLEAN, 16, TFS(&pn_dcp_rsi_properties_value_bit), 0x0020, + NULL, HFILL } }, + + { &hf_pn_dcp_rsi_properties_value_otherbits, + { "RsiPropertiesValue.Bit6-15", "pn_dcp.suboption_device_rsi_properties_value.otherbits", + FT_UINT16, BASE_HEX, NULL, 0xFFC0, + NULL, HFILL } }, + + { &hf_pn_dcp_vendor_id_high, + { "VendorIDHigh", "pn_dcp.vendor_id_high", + FT_UINT16, BASE_HEX, NULL, 0xFF00, + NULL, HFILL } }, + + { &hf_pn_dcp_vendor_id_low, + { "VendorIDLow", "pn_dcp.vendor_id_low", + FT_UINT16, BASE_HEX, NULL, 0x00FF, + NULL, HFILL } }, + + { &hf_pn_dcp_device_id_high, + { "DeviceIDHigh", "pn_dcp.device_id_high", + FT_UINT16, BASE_HEX, NULL, 0xFF00, + NULL, HFILL } }, + + { &hf_pn_dcp_device_id_low, + { "DeviceIDLow", "pn_dcp.device_id_low", + FT_UINT16, BASE_HEX, NULL, 0x00FF, + NULL, HFILL } }, + + { &hf_pn_dcp_instance_id_high, + { "InstanceHigh", "pn_dcp.instance_id_high", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_instance_id_low, + { "InstanceLow", "pn_dcp.instance_id_low", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_dhcp, + { "Suboption", "pn_dcp.suboption_dhcp", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_dhcp), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_dhcp_option_code, + { "Option-Code", "pn_dcp.suboption_dhcp_option_code", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_dhcp), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_dhcp_arbitrary_client_id, + { "Client ID", "pn_dcp.suboption_dhcp_client_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_dhcp_parameter_length, + { "DHCP Parameter Length", "pn_dcp.suboption_dhcp_parameter_length", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_dhcp_parameter_data, + { "DHCP Parameter Data", "pn_dcp.suboption_dhcp_parameter_data", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_dhcp_control_parameter_data, + { "DHCP Parameter Data", "pn_dcp.suboption_dhcp_parameter_data", + FT_UINT8, BASE_HEX, VALS(pn_dcp_suboption_dhcp_control_parameter_data), 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_control, + { "Suboption", "pn_dcp.suboption_control", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_control), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_control_option, + { "Option", "pn_dcp.suboption_control_option", + FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(pn_dcp_option), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_control_signal_value, + { "SignalValue", "pn_dcp.suboption_control_signal_value", + FT_UINT16, BASE_HEX, VALS(pn_dcp_suboption_control_signal_value), 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_deviceinitiative, + { "Suboption", "pn_dcp.suboption_deviceinitiative", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_deviceinitiative), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_deviceinitiative_value, + { "DeviceInitiativeValue", "pn_dcp.deviceinitiative_value", + FT_UINT16, BASE_DEC, VALS(pn_dcp_deviceinitiative_value), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_tsn, + { "Suboption", "pn_dcp.suboption_tsn", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_tsn), 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_tsn_domain_name, + { "TSNDomainName", "pn_dcp.suboption_tsn_domain_name", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_tsn_domain_uuid, + { "TSNDomainUUID", "pn_dcp.tsn_domain_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_tsn_nme_prio, + { "NMEPrio", "pn_dcp.suboption_tsn_nme_prio", + FT_UINT16, BASE_DEC | BASE_RANGE_STRING, RVALS(pn_dcp_suboption_tsn_nme_prio), 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_tsn_nme_parameter_uuid, + { "NMEParameterUUID", "pn_dcp.suboption_tsn_nme_parameter_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_tsn_nme_agent, + { "NMEAgent", "pn_dcp.suboption_tsn_nme_agent", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_dcp_suboption_all, + { "Suboption", "pn_dcp.suboption_all", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_all), 0x0, + NULL, HFILL }}, + + { &hf_pn_dcp_suboption_manuf, + { "Suboption", "pn_dcp.suboption_manuf", + FT_UINT8, BASE_DEC, VALS(pn_dcp_suboption_manuf), 0x0, + NULL, HFILL }}, + + }; + + static gint *ett[] = { + &ett_pn_dcp, + &ett_pn_dcp_block, + &ett_pn_dcp_rsi_properties_value + }; + + static ei_register_info ei[] = { + { &ei_pn_dcp_block_parse_error, { "pn_dcp.block_error.parse", PI_PROTOCOL, PI_ERROR, "parse error", EXPFILL }}, + { &ei_pn_dcp_block_error_unknown, { "pn_dcp.block_error.unknown", PI_RESPONSE_CODE, PI_CHAT, "Unknown", EXPFILL }}, + { &ei_pn_dcp_ip_conflict, { "pn_dcp.ip_conflict", PI_RESPONSE_CODE, PI_NOTE, "IP address conflict detected!", EXPFILL }}, + }; + + expert_module_t* expert_pn_dcp; + + proto_pn_dcp = proto_register_protocol ("PROFINET DCP", "PN-DCP", "pn_dcp"); + proto_register_field_array (proto_pn_dcp, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); + expert_pn_dcp = expert_register_protocol(proto_pn_dcp); + expert_register_field_array(expert_pn_dcp, ei, array_length(ei)); +} + +void +proto_reg_handoff_pn_dcp (void) +{ + /* register ourself as an heuristic pn-rt payload dissector */ + heur_dissector_add("pn_rt", dissect_PNDCP_Data_heur, "PROFINET DCP IO", "pn_dcp_pn_rt", proto_pn_dcp, HEURISTIC_ENABLE); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-pn-mrp.c b/plugins/epan/profinet/packet-pn-mrp.c new file mode 100644 index 00000000..9efafe72 --- /dev/null +++ b/plugins/epan/profinet/packet-pn-mrp.c @@ -0,0 +1,675 @@ +/* packet-pn-mrp.c + * Routines for PN-MRP (PROFINET Media Redundancy Protocol) + * packet dissection. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "packet-pn.h" + +void proto_register_pn_mrp(void); +void proto_reg_handoff_pn_mrp(void); + +static dissector_handle_t mrp_handle; + +static int proto_pn_mrp = -1; + +static int hf_pn_mrp_type = -1; +static int hf_pn_mrp_length = -1; +static int hf_pn_mrp_version = -1; +static int hf_pn_mrp_sequence_id = -1; +static int hf_pn_mrp_sa = -1; +static int hf_pn_mrp_prio = -1; +static int hf_pn_mrp_port_role = -1; +static int hf_pn_mrp_ring_state = -1; +static int hf_pn_mrp_interval = -1; +static int hf_pn_mrp_transition = -1; +static int hf_pn_mrp_time_stamp = -1; +static int hf_pn_mrp_blocked = -1; +static int hf_pn_mrp_domain_uuid = -1; +static int hf_pn_mrp_oui = -1; +static int hf_pn_mrp_ed1type = -1; +static int hf_pn_mrp_ed1_manufacturer_data = -1; +static int hf_pn_mrp_sub_tlv_header_type = -1; +static int hf_pn_mrp_sub_tlv_header_length = -1; +static int hf_pn_mrp_sub_option2 = -1; +static int hf_pn_mrp_other_mrm_prio = -1; +static int hf_pn_mrp_other_mrm_sa = -1; +static int hf_pn_mrp_manufacturer_data = -1; + +static gint ett_pn_mrp = -1; +static gint ett_pn_mrp_type = -1; +static gint ett_pn_sub_tlv = -1; + +static const value_string pn_mrp_block_type_vals[] = { + { 0x00, "MRP_End" }, + { 0x01, "MRP_Common" }, + { 0x02, "MRP_Test" }, + { 0x03, "MRP_TopologyChange" }, + { 0x04, "MRP_LinkDown" }, + { 0x05, "MRP_LinkUp" }, + { 0x06, "MRP_InTest" }, + { 0x07, "MRP_InTopologyChange" }, + { 0x08, "MRP_InLinkDown" }, + { 0x09, "MRP_InLinkUp" }, + { 0x0A, "MRP_InLinkStatusPoll" }, + /*0x0B - 0x7E Reserved */ + { 0x7F, "MRP_Option (Organizationally Specific)"}, + { 0, NULL }, +}; + +static const value_string pn_mrp_oui_vals[] = { + { OUI_PROFINET, "PROFINET" }, + { OUI_SIEMENS, "SIEMENS" }, + + { 0, NULL } +}; + + + +static const value_string pn_mrp_port_role_vals[] = { + { 0x0000, "Primary ring port" }, + { 0x0001, "Secondary ring port"}, + /*0x0002 - 0xFFFF Reserved */ + + { 0, NULL } +}; + +#if 0 +static const value_string pn_mrp_role_vals[] = { + { 0x0000, "Media redundancy disabled" }, + { 0x0001, "Media redundancy client" }, + { 0x0002, "Media redundancy manager" }, + { 0x0003, "Media redundancy manager (auto)" }, + /*0x0004 - 0xFFFF Reserved */ + + { 0, NULL } +}; +#endif + +static const value_string pn_mrp_ring_state_vals[] = { + { 0x0000, "Ring open" }, + { 0x0001, "Ring closed"}, + /*0x0002 - 0xFFFF Reserved */ + + { 0, NULL } +}; + + +#if 0 +static const value_string pn_mrp_prio_vals[] = { + { 0x8000, "Default priority for redundancy manager" }, + + { 0, NULL } +}; +#endif + +static const value_string pn_mrp_sub_tlv_header_type_vals[] = { + /* 0x00 Reserved */ + { 0x01, "MRP_TestMgrNAck" }, + { 0x02, "MRP_TestPropagate" }, + { 0x03, "MRP_AutoMgr" }, + /* 0x04 - 0xF0 Reserved for IEC specific functions */ + { 0xF1, "Manufacturer specific functions" }, + { 0xF2, "Manufacturer specific functions" }, + { 0xF3, "Manufacturer specific functions" }, + { 0xF4, "Manufacturer specific functions" }, + { 0xF5, "Manufacturer specific functions" }, + { 0xF6, "Manufacturer specific functions" }, + { 0xF7, "Manufacturer specific functions" }, + { 0xF8, "Manufacturer specific functions" }, + { 0xF9, "Manufacturer specific functions" }, + { 0xFA, "Manufacturer specific functions" }, + { 0xFB, "Manufacturer specific functions" }, + { 0xFC, "Manufacturer specific functions" }, + { 0xFD, "Manufacturer specific functions" }, + { 0xFE, "Manufacturer specific functions" }, + { 0xFF, "Manufacturer specific functions" }, + { 0, NULL }, +}; + +static int +dissect_PNMRP_Common(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_) +{ + guint16 sequence_id; + e_guid_t uuid; + + + /* MRP_SequenceID */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_sequence_id, &sequence_id); + + /* MRP_DomainUUID */ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_mrp_domain_uuid, &uuid); + + return offset; +} + + +static int +dissect_PNMRP_Link(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_) +{ + guint8 mac[6]; + guint16 port_role; + guint16 interval; + guint16 blocked; + proto_item *sub_item; + + /* MRP_SA */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_mrp_sa, mac); + + /* MRP_PortRole */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_port_role, &port_role); + + /* MRP_Interval */ + offset = dissect_pn_uint16_ret_item(tvb, offset, pinfo, tree, hf_pn_mrp_interval, &interval, &sub_item); + if (tree) + { + proto_item_append_text(sub_item," Interval for next topology change event (in ms)"); + if (interval <0x07D1) + proto_item_append_text(sub_item," Mandatory"); + else + proto_item_append_text(sub_item," Optional"); + } + + /* MRP_Blocked */ + offset = dissect_pn_uint16_ret_item(tvb, offset, pinfo, tree, hf_pn_mrp_blocked, &blocked, &sub_item); + if (tree) + { + if (blocked == 0) + proto_item_append_text(sub_item," The MRC is not able to receive and forward frames to port in state blocked"); + else + if (blocked == 1) + proto_item_append_text(sub_item," The MRC is able to receive and forward frames to port in state blocked"); + else + proto_item_append_text(sub_item," Reserved"); + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + return offset; +} + +static const char * mrp_Prio2msg(guint16 prio) +{ + + if (prio == 0x0000) + return(" Highest priority redundancy manager"); + if ((prio >= 0x1000) && (prio <= 0x7000)) + return(" High priorities"); + if (prio == 0x8000) + return(" Default priority for redundancy manager"); + if ((prio >= 0x8001) && (prio <= 0x8FFF)) + return(" Low priorities for redundancy manager"); + if ((prio >= 0x9000) && (prio <= 0x9FFF)) + return(" High priorities for redundancy manager (auto)"); + if (prio == 0xA000) + return(" Default priority for redundancy manager (auto)"); + if ((prio >= 0xA001) && (prio <= 0xF000)) + return(" Low priorities for redundancy manager (auto)"); + if (prio ==0xFFFF) + return(" Lowest priority for redundancy manager (auto)"); + + return(" Reserved"); +} + +static int +dissect_PNMRP_Test(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_) +{ + guint16 prio; + guint8 mac[6]; + guint16 port_role; + guint16 ring_state; + guint16 transition; + guint32 time_stamp; + proto_item *sub_item; + + + /* MRP_Prio */ + offset = dissect_pn_uint16_ret_item(tvb, offset, pinfo, tree, hf_pn_mrp_prio, &prio, &sub_item); + if (tree) + proto_item_append_text(sub_item, "%s", mrp_Prio2msg(prio)); + + /* MRP_SA */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_mrp_sa, mac); + + /* MRP_PortRole */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_port_role, &port_role); + + /* MRP_RingState */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_ring_state, &ring_state); + + /* MRP_Transition */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_transition, &transition); + + /* MRP_TimeStamp */ + proto_tree_add_item_ret_uint(tree, hf_pn_mrp_time_stamp, tvb, offset, 4, ENC_BIG_ENDIAN, &time_stamp); + offset += 4; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + return offset; +} + + +static int +dissect_PNMRP_TopologyChange(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_) +{ + guint16 prio; + guint8 mac[6]; + guint16 interval; + proto_item *sub_item; + + + /* MRP_Prio */ + offset = dissect_pn_uint16_ret_item(tvb, offset, pinfo, tree, hf_pn_mrp_prio, &prio, &sub_item); + if (tree) + proto_item_append_text(sub_item, "%s", mrp_Prio2msg(prio)); + + /* MRP_SA */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_mrp_sa, mac); + + /* MRP_Interval */ + offset = dissect_pn_uint16_ret_item(tvb, offset, pinfo, tree, hf_pn_mrp_interval, &interval, &sub_item); + if (tree) + { + proto_item_append_text(sub_item," Interval for next topology change event (in ms) "); + if (interval <0x07D1) + proto_item_append_text(sub_item,"Mandatory"); + else + proto_item_append_text(sub_item,"Optional"); + } + /* Padding */ + /*offset = dissect_pn_align4(tvb, offset, pinfo, tree);*/ + + return offset; +} + +static int +dissect_PNMRP_Ed1ManufacturerData(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree, guint8 *pLength) +{ + guint16 u16MrpEd1ManufacturerData; + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_ed1_manufacturer_data, + &u16MrpEd1ManufacturerData); + *pLength -= 2; + return offset; +} + +static int +dissect_PNMRP_SubOption2(tvbuff_t *tvb, int offset, +packet_info *pinfo, proto_tree *tree) +{ + guint8 u8SubType; + guint8 u8Sublength; + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16Prio; + guint16 u16OtherPrio; + guint8 mac[6]; + guint8 otherMac[6]; + + sub_item = proto_tree_add_item(tree, hf_pn_mrp_sub_option2, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_sub_tlv); + + /* + MRP_SubTLVHeader (Type=0x01 or Type=0x02, Length = 0x12), + MRP_Prio, + MRP_SA, + MRP_OtherMRMPrio, + MRP_OtherMRMSA, + Padding (=0x00,0x00) + */ + /* MRP_SubTLVHeader.Type */ + offset = dissect_pn_uint8(tvb, offset, pinfo, sub_tree, hf_pn_mrp_sub_tlv_header_type, &u8SubType); + + /* MRP_SubTLVHeader.Length */ + offset = dissect_pn_uint8(tvb, offset, pinfo, sub_tree, hf_pn_mrp_sub_tlv_header_length, &u8Sublength); + + if (u8SubType == 0x00) + { + // IEC area: 0x00: Reserved; + return offset; + } + else if ( u8SubType == 0x01 || u8SubType == 0x02 ) + { + // IEC area: 0x01: MRP_TestMgrNAck; + // IEC area: 0x02: MRP_AutoMgr; + + /* MRP_Prio */ + offset = dissect_pn_uint16_ret_item(tvb, offset, pinfo, sub_tree, hf_pn_mrp_prio, &u16Prio, &sub_item); + proto_item_append_text(sub_item, "%s", mrp_Prio2msg(u16Prio)); + + /* MRP_SA */ + offset = dissect_pn_mac(tvb, offset, pinfo, sub_tree, hf_pn_mrp_sa, mac); + + /* MRP_OtherMRMPrio */ + offset = dissect_pn_uint16_ret_item(tvb, offset, pinfo, sub_tree, hf_pn_mrp_other_mrm_prio, + &u16OtherPrio, &sub_item); + proto_item_append_text(sub_item, "%s", mrp_Prio2msg(u16OtherPrio)); + + /* MRP_OtherMRMSA */ + offset = dissect_pn_mac(tvb, offset, pinfo, sub_tree, hf_pn_mrp_other_mrm_sa, otherMac); + + offset = dissect_pn_align4(tvb, offset, pinfo, sub_tree); + } + else if ( 0xF1 <= u8SubType ) + { + proto_tree_add_string_format(sub_tree, hf_pn_mrp_manufacturer_data, tvb, offset, u8Sublength, "data", + "Reserved for vendor specific data: %u byte", u8Sublength); + offset += u8Sublength; + } + return offset; +} + +static int +dissect_PNMRP_Option(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length) +{ + guint32 oui; + guint8 u8MrpEd1Type; + + /* OUI (organizational unique id) */ + offset = dissect_pn_oid(tvb, offset, pinfo,tree, hf_pn_mrp_oui, &oui); + + switch (oui) + { + case OUI_SIEMENS: + proto_item_append_text(item, "(SIEMENS)"); + length -= 3; + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_mrp_ed1type, &u8MrpEd1Type); + length -= 1; + switch (u8MrpEd1Type) + { + case 0x00: + offset = dissect_PNMRP_Ed1ManufacturerData(tvb, offset, pinfo, tree, &length); + break; + case 0x01: + case 0x02: + case 0x03: + break; + case 0x04: + offset = dissect_PNMRP_Ed1ManufacturerData(tvb, offset, pinfo, tree, &length); + break; + /* 0x05 to 0xFF*/ + default: + break; + } + //offset = dissect_PNMRP_Ed1ManufacturerData(tvb, offset, pinfo, tree, &length); + + if (length != 0) + { + offset = dissect_PNMRP_SubOption2(tvb, offset, pinfo, tree); + } + col_append_str(pinfo->cinfo, COL_INFO, "(Siemens)"); + break; + default: + proto_item_append_text(item, " (Unknown-OUI)"); + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length); + + } + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + return offset; +} + + +static int +dissect_PNMRP_PDU(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item) +{ + guint16 version; + guint8 type; + guint8 length; + gint i; + tvbuff_t *new_tvb; + proto_item *sub_item; + proto_tree *sub_tree; + + /* MRP_Version */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_version, &version); + + /* the rest of the packet has 4byte alignment regarding to the beginning of the next TLV block! */ + /* XXX - do we have to free this new tvb below? */ + new_tvb = tvb_new_subset_remaining(tvb, offset); + offset = 0; + + for(i=0; tvb_reported_length_remaining(tvb, offset) > 0; i++) { + + sub_item = proto_tree_add_item(tree, hf_pn_mrp_type, new_tvb, offset, 1, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_mrp_type); + + /* MRP_TLVHeader.Type */ + offset = dissect_pn_uint8(new_tvb, offset, pinfo, sub_tree, hf_pn_mrp_type, &type); + + /* MRP_TLVHeader.Length */ + offset = dissect_pn_uint8(new_tvb, offset, pinfo, sub_tree, hf_pn_mrp_length, &length); + + if (i != 0) { + col_append_str(pinfo->cinfo, COL_INFO, ", "); + + proto_item_append_text(item, ", "); + } else { + proto_item_append_text(item, " "); + } + col_append_str(pinfo->cinfo, COL_INFO, val_to_str(type, pn_mrp_block_type_vals, "Unknown TLVType 0x%x")); + proto_item_append_text(item, "%s", val_to_str(type, pn_mrp_block_type_vals, "Unknown TLVType 0x%x")); + + switch(type) { + case 0x00: + /* no content */ + return offset; + break; + case 0x01: + offset = dissect_PNMRP_Common(new_tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x02: + offset = dissect_PNMRP_Test(new_tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x03: + offset = dissect_PNMRP_TopologyChange(new_tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x04: + case 0x05: /* dissection of up and down is identical! */ + offset = dissect_PNMRP_Link(new_tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x7f: + offset = dissect_PNMRP_Option(new_tvb, offset, pinfo, sub_tree, sub_item, length); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, sub_tree, length); + + } + } + + return offset; +} + + +/* Dissect MRP packets */ +static int +dissect_PNMRP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_item *ti = NULL; + proto_tree *mrp_tree = NULL; + + guint32 offset = 0; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-MRP"); + + /* Clear the information column on summary display */ + col_clear(pinfo->cinfo, COL_INFO); + + if (tree) + { + ti = proto_tree_add_item(tree, proto_pn_mrp, tvb, offset, -1, ENC_NA); + mrp_tree = proto_item_add_subtree(ti, ett_pn_mrp); + } + + dissect_PNMRP_PDU(tvb, offset, pinfo, mrp_tree, ti); + return tvb_captured_length(tvb); +} + + +void +proto_register_pn_mrp (void) +{ + static hf_register_info hf[] = { + { &hf_pn_mrp_type, + { "MRP_TLVHeader.Type", "pn_mrp.type", + FT_UINT8, BASE_HEX, VALS(pn_mrp_block_type_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_length, + { "MRP_TLVHeader.Length", "pn_mrp.length", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_version, + { "MRP_Version", "pn_mrp.version", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_sequence_id, + { "MRP_SequenceID", "pn_mrp.sequence_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Unique sequence number to each outstanding service request", HFILL }}, + + { &hf_pn_mrp_sa, + { "MRP_SA", "pn_mrp.sa", + FT_ETHER, BASE_NONE, 0x0, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_prio, + { "MRP_Prio", "pn_mrp.prio", + FT_UINT16, BASE_HEX, 0, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_port_role, + { "MRP_PortRole", "pn_mrp.port_role", + FT_UINT16, BASE_HEX, VALS(pn_mrp_port_role_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_ring_state, + { "MRP_RingState", "pn_mrp.ring_state", + FT_UINT16, BASE_HEX, VALS(pn_mrp_ring_state_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_interval, + { "MRP_Interval", "pn_mrp.interval", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Interval for next topology change event (in ms)", HFILL }}, + + { &hf_pn_mrp_transition, + { "MRP_Transition", "pn_mrp.transition", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Number of transitions between media redundancy lost and ok states", HFILL }}, + + { &hf_pn_mrp_time_stamp, + { "MRP_TimeStamp [ms]", "pn_mrp.time_stamp", + FT_UINT32, BASE_HEX, NULL, 0x0, + "Actual counter value of 1ms counter", HFILL }}, + + { &hf_pn_mrp_blocked, + { "MRP_Blocked", "pn_mrp.blocked", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_domain_uuid, + { "MRP_DomainUUID", "pn_mrp.domain_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_oui, + { "MRP_ManufacturerOUI", "pn_mrp.oui", + FT_UINT24, BASE_HEX, VALS(pn_mrp_oui_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_ed1type, + { "MRP_Ed1Type", "pn_mrp.ed1type", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_ed1_manufacturer_data, + { "MRP_Ed1ManufacturerData", "pn_mrp.ed1manufacturerdata", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_sub_option2, + { "MRP_SubOption2", "pn_mrp.sub_option2", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } }, + + { &hf_pn_mrp_sub_tlv_header_type, + { "MRP_SubTLVHeader.Type", "pn_mrp.sub_type", + FT_UINT8, BASE_HEX, VALS(pn_mrp_sub_tlv_header_type_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_sub_tlv_header_length, + { "MRP_SubTLVHeader.Length", "pn_mrp.sub_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_other_mrm_prio, + { "MRP_OtherMRMPrio", "pn_mrp.other_mrm_prio", + FT_UINT16, BASE_HEX, 0, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrp_other_mrm_sa, + { "MRP_OtherMRMSA", "pn_mrp.other_mrm_sa", + FT_ETHER, BASE_NONE, 0x0, 0x0, + NULL, HFILL }}, + { &hf_pn_mrp_manufacturer_data, + { "MRP_ManufacturerData", "pn_mrp.manufacturer_data", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }} + }; + + static gint *ett[] = { + &ett_pn_mrp, + &ett_pn_mrp_type, + &ett_pn_sub_tlv + }; + + proto_pn_mrp = proto_register_protocol ("PROFINET MRP", "PN-MRP", "pn_mrp"); + proto_register_field_array (proto_pn_mrp, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); + mrp_handle = register_dissector("pn_mrp", dissect_PNMRP, proto_pn_mrp); +} + + +void +proto_reg_handoff_pn_mrp (void) +{ + dissector_add_uint("ethertype", ETHERTYPE_MRP, mrp_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-pn-mrrt.c b/plugins/epan/profinet/packet-pn-mrrt.c new file mode 100644 index 00000000..5c332a5a --- /dev/null +++ b/plugins/epan/profinet/packet-pn-mrrt.c @@ -0,0 +1,247 @@ +/* packet-pn-mrrt.c + * Routines for PN-MRRT (PROFINET Media Redundancy for cyclic realtime data) + * packet dissection. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include + +#include "packet-pn.h" + +void proto_register_pn_mrrt(void); +void proto_reg_handoff_pn_mrrt(void); + +static int proto_pn_mrrt = -1; + +static int hf_pn_mrrt_sequence_id = -1; +static int hf_pn_mrrt_domain_uuid = -1; +static int hf_pn_mrrt_type = -1; +static int hf_pn_mrrt_length = -1; +static int hf_pn_mrrt_version = -1; +static int hf_pn_mrrt_sa = -1; + + +static gint ett_pn_mrrt = -1; + + + +static const value_string pn_mrrt_block_type_vals[] = { + { 0x00, "End" }, + { 0x01, "Common" }, + { 0x02, "Test" }, + /*0x03 - 0x7E Reserved */ + { 0x7F, "Organizationally Specific"}, + { 0, NULL }, +}; + + + + +static int +dissect_PNMRRT_Common(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length _U_) +{ + guint16 sequence_id; + e_guid_t uuid; + + + /* MRRT_SequenceID */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrrt_sequence_id, &sequence_id); + + /* MRRT_DomainUUID */ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_mrrt_domain_uuid, &uuid); + + col_append_str(pinfo->cinfo, COL_INFO, "Common"); + + proto_item_append_text(item, "Common"); + + return offset; +} + + +static int +dissect_PNMRRT_Test(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length _U_) +{ + guint8 mac[6]; + + + /* MRRT_SA */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_mrrt_sa, mac); + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + col_append_str(pinfo->cinfo, COL_INFO, "Test"); + + proto_item_append_text(item, "Test"); + + return offset; +} + +static int +dissect_PNMRRT_PDU(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item) +{ + guint16 version; + guint8 type; + guint8 length; + gint i = 0; + + + /* MRRT_Version */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrrt_version, &version); + + while (tvb_reported_length_remaining(tvb, offset) > 0) { + /* MRRT_TLVHeader.Type */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_mrrt_type, &type); + + /* MRRT_TLVHeader.Length */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_mrrt_length, &length); + + + if (i != 0) { + col_append_str(pinfo->cinfo, COL_INFO, ", "); + + proto_item_append_text(item, ", "); + } + + i++; + + switch(type) { + case 0x00: + /* no content */ + col_append_str(pinfo->cinfo, COL_INFO, "End"); + proto_item_append_text(item, "End"); + return offset; + break; + case 0x01: + offset = dissect_PNMRRT_Common(tvb, offset, pinfo, tree, item, length); + break; + case 0x02: + offset = dissect_PNMRRT_Test(tvb, offset, pinfo, tree, item, length); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length); + + col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TLVType 0x%x", type); + proto_item_append_text(item, "Unknown TLVType 0x%x", type); + break; + } + } + + return offset; +} + + +/* possibly dissect a PN-RT packet (frame ID must be in the appropriate range) */ +static gboolean +dissect_PNMRRT_Data_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, + void *data) +{ + /* the tvb will NOT contain the frame_id here, so get it from dissector data! */ + guint16 u16FrameID = GPOINTER_TO_UINT(data); + proto_item *item; + proto_tree *mrrt_tree; + int offset = 0; + guint32 u32SubStart; + + + /* frame id must be in valid range (MRRT) */ + if (u16FrameID != 0xFF60) { + /* we are not interested in this packet */ + return FALSE; + } + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-MRRT"); + col_clear(pinfo->cinfo, COL_INFO); + + /* subtree for MRRT */ + item = proto_tree_add_protocol_format(tree, proto_pn_mrrt, tvb, 0, 0, "PROFINET MRRT, "); + mrrt_tree = proto_item_add_subtree(item, ett_pn_mrrt); + u32SubStart = offset; + + offset = dissect_PNMRRT_PDU(tvb, offset, pinfo, mrrt_tree, item); + + proto_item_set_len(item, offset - u32SubStart); + + return TRUE; +} + + +void +proto_register_pn_mrrt (void) +{ + static hf_register_info hf[] = { + + { &hf_pn_mrrt_type, + { "Type", "pn_mrrt.type", + FT_UINT8, BASE_HEX, VALS(pn_mrrt_block_type_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_mrrt_length, + { "Length", "pn_mrrt.length", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrrt_version, + { "Version", "pn_mrrt.version", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrrt_sequence_id, + { "SequenceID", "pn_mrrt.sequence_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Unique sequence number to each outstanding service request", HFILL }}, + + { &hf_pn_mrrt_sa, + { "SA", "pn_mrrt.sa", + FT_ETHER, BASE_NONE, 0x0, 0x0, + NULL, HFILL }}, + + { &hf_pn_mrrt_domain_uuid, + { "DomainUUID", "pn_mrrt.domain_uuid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + }; + + + static gint *ett[] = { + &ett_pn_mrrt + }; + + proto_pn_mrrt = proto_register_protocol ("PROFINET MRRT", "PN-MRRT", "pn_mrrt"); + proto_register_field_array (proto_pn_mrrt, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); +} + + +void +proto_reg_handoff_pn_mrrt (void) +{ + + /* register ourself as an heuristic pn-rt payload dissector */ + heur_dissector_add("pn_rt", dissect_PNMRRT_Data_heur, "PROFINET MRRT IO", "pn_mrrt_pn_rt", proto_pn_mrrt, HEURISTIC_ENABLE); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-pn-ptcp.c b/plugins/epan/profinet/packet-pn-ptcp.c new file mode 100644 index 00000000..cd11896b --- /dev/null +++ b/plugins/epan/profinet/packet-pn-ptcp.c @@ -0,0 +1,1093 @@ +/* packet-pn-ptcp.c + * Routines for PN-PTCP (PROFINET Precision Time Clock Protocol) + * packet dissection. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include +#include + +#include "packet-pn.h" + +void proto_register_pn_ptcp(void); +void proto_reg_handoff_pn_ptcp(void); + +static int proto_pn_ptcp = -1; + +static int hf_pn_ptcp_header = -1; +static int hf_pn_ptcp_block = -1; +static int hf_pn_ptcp_block_tlvheader = -1; + +static int hf_pn_ptcp_res1 = -1; +static int hf_pn_ptcp_res2 = -1; +static int hf_pn_ptcp_delay10ns = -1; +static int hf_pn_ptcp_seq_id = -1; +static int hf_pn_ptcp_delay1ns_byte = -1; +static int hf_pn_ptcp_delay1ns_fup = -1; +static int hf_pn_ptcp_delay1ns = -1; + +static int hf_pn_ptcp_tl_length = -1; +static int hf_pn_ptcp_tl_type = -1; + +static int hf_pn_ptcp_master_source_address = -1; +static int hf_pn_ptcp_subdomain_uuid = -1; + +static int hf_pn_ptcp_port_mac_address = -1; + +static int hf_pn_ptcp_t2portrxdelay = -1; +static int hf_pn_ptcp_t3porttxdelay = -1; + +static int hf_pn_ptcp_t2timestamp = -1; + +static int hf_pn_ptcp_epoch_number = -1; +static int hf_pn_ptcp_seconds = -1; +static int hf_pn_ptcp_nanoseconds = -1; + +static int hf_pn_ptcp_flags = -1; +static int hf_pn_ptcp_currentutcoffset = -1; + +static int hf_pn_ptcp_master_priority1 = -1; +static int hf_pn_ptcp_master_priority_level = -1; +static int hf_pn_ptcp_master_priority1_res = -1; +static int hf_pn_ptcp_master_priority1_act =-1; + +static int hf_pn_ptcp_master_priority2 = -1; +static int hf_pn_ptcp_clock_class = -1; +static int hf_pn_ptcp_clock_accuracy = -1; +static int hf_pn_ptcp_clockvariance = -1; + +static int hf_pn_ptcp_oui = -1; +static int hf_pn_ptcp_profinet_subtype = -1; +static int hf_pn_ptcp_irdata_uuid = -1; + +static gint ett_pn_ptcp = -1; +static gint ett_pn_ptcp_header = -1; +static gint ett_pn_ptcp_block = -1; +static gint ett_pn_ptcp_block_header = -1; + +#define OUI_PROFINET_MULTICAST 0x010ECF /* PROFIBUS Nutzerorganisation e.V. */ + + +#define PN_PTCP_BT_END 0x00 +#define PN_PTCP_BT_SUBDOMAIN 0x01 +#define PN_PTCP_BT_TIME 0x02 +#define PN_PTCP_BT_TIME_EXTENSION 0x03 +#define PN_PTCP_BT_MASTER 0x04 +#define PN_PTCP_BT_PORT_PARAMETER 0x05 +#define PN_PTCP_BT_DELAY_PARAMETER 0x06 +#define PN_PTCP_BT_PORT_TIME 0x07 +#define PN_PTCP_BT_OPTION 0x7F +#define PN_PTCP_BT_RTDATA 0x7F + + +static const value_string pn_ptcp_block_type[] = { + { PN_PTCP_BT_END, "End" }, + { PN_PTCP_BT_SUBDOMAIN, "Subdomain"}, + { PN_PTCP_BT_TIME, "Time"}, + { PN_PTCP_BT_TIME_EXTENSION, "TimeExtension"}, + { PN_PTCP_BT_MASTER, "Master"}, + { PN_PTCP_BT_PORT_PARAMETER, "PortParameter"}, + { PN_PTCP_BT_DELAY_PARAMETER, "DelayParameter"}, + { PN_PTCP_BT_PORT_TIME, "PortTime"}, + /*0x08 - 0x7E Reserved */ + { PN_PTCP_BT_OPTION, "Organizationally Specific"}, + { 0, NULL } +}; + +static const value_string pn_ptcp_oui_vals[] = { + { OUI_PROFINET, "PROFINET" }, + { OUI_PROFINET_MULTICAST, "PROFINET" }, + { 0, NULL } +}; + +static const value_string pn_ptcp_master_prio1_vals[] = { + { 0x00, "Sync slave" }, + { 0x01, "Primary master" }, + { 0x02, "Secondary master" }, + { 0x03, "Reserved" }, + { 0x04, "Reserved" }, + { 0x05, "Reserved" }, + { 0x06, "Reserved" }, + { 0x07, "Reserved" }, + { 0, NULL } +}; + +static const value_string pn_ptcp_master_prio1_levels[] = { + { 0x00, "Level 0 (highest)" }, + { 0x01, "Level 1" }, + { 0x02, "Level 2" }, + { 0x03, "Level 3" }, + { 0x04, "Level 4" }, + { 0x05, "Level 5" }, + { 0x06, "Level 6" }, + { 0x07, "Level 7 (lowest)" }, + { 0, NULL } +}; + +static const value_string pn_ptcp_master_prio1_vals_active[] = { + { 0x00, "inactive" }, + { 0x01, "active" }, + { 0, NULL } +}; + +#if 0 +static const value_string pn_ptcp_master_prio1_short_vals[] = { + { 0x01, "Primary" }, + { 0x02, "Secondary" }, + { 0, NULL } +}; +#endif + +static const value_string pn_ptcp_master_prio2_vals[] = { + { 0xFF, "Default" }, + { 0, NULL } +}; + +static const value_string pn_ptcp_clock_class_vals[] = { + { 0xFF, "Slave-only clock" }, + { 0, NULL } +}; + +static const value_string pn_ptcp_clock_accuracy_vals[] = { + { 0x20, "25ns" }, + { 0x21, "100ns (Default)" }, + { 0x22, "250ns" }, + { 0x23, "1us" }, + { 0x24, "2.5us" }, + { 0x25, "10us" }, + { 0x26, "25us" }, + { 0x27, "100us" }, + { 0x28, "250us" }, + { 0x29, "1ms" }, + { 0xFE, "Unknown" }, + { 0, NULL } +}; + +static const value_string pn_ptcp_profinet_subtype_vals[] = { + { 0x01, "RTData" }, + { 0, NULL } +}; + + + + +static int +dissect_PNPTCP_TLVHeader(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint16 *type, guint16 *length) +{ + guint16 tl_type; + guint16 tl_length; + + + /* Type */ + dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_tl_type, &tl_type); + *type = tl_type >> 9; + + /* Length */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_tl_length, &tl_length); + *length = tl_length & 0x1FF; + + return offset; +} + + +static int +dissect_PNPTCP_Subdomain(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID) +{ + guint8 mac[6]; + e_guid_t uuid; + + + /* MasterSourceAddress */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_ptcp_master_source_address, mac); + + /* SubdomainUUID */ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_subdomain_uuid, &uuid); + + if ((u16FrameID == 0xff00) || (u16FrameID == 0xff01)) { + col_append_fstr(pinfo->cinfo, COL_INFO, ", Master=%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + + proto_item_append_text(item, ": MasterSource=%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + proto_item_append_text(item, ", Subdomain=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid.data1, uuid.data2, uuid.data3, + uuid.data4[0], uuid.data4[1], + uuid.data4[2], uuid.data4[3], + uuid.data4[4], uuid.data4[5], + uuid.data4[6], uuid.data4[7]); + + return offset; +} + + +static int +dissect_PNPTCP_Time(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item) +{ + guint16 EpochNumber; + guint32 Seconds; + guint32 NanoSeconds; + + + /* EpochNumber */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_epoch_number, &EpochNumber); + + /* Seconds */ + proto_tree_add_item_ret_uint(tree, hf_pn_ptcp_seconds, tvb, offset, 4, ENC_BIG_ENDIAN, &Seconds); + offset += 4; + + /* NanoSeconds */ + proto_tree_add_item_ret_uint(tree, hf_pn_ptcp_nanoseconds, tvb, offset, 4, ENC_BIG_ENDIAN, &NanoSeconds); + offset += 4; + + proto_item_append_text(item, ": Seconds=%u NanoSeconds=%u EpochNumber=%u", + Seconds, NanoSeconds, EpochNumber); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", Time: %4us %09uns, Epoch: %u", + Seconds, NanoSeconds, EpochNumber); + + return offset; +} + + +static int +dissect_PNPTCP_TimeExtension(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item) +{ + guint16 Flags; + guint16 CurrentUTCOffset; + + + /* Flags */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_flags, &Flags); + + /* CurrentUTCOffset */ + offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_currentutcoffset, &CurrentUTCOffset); + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + proto_item_append_text(item, ": Flags=0x%x, CurrentUTCOffset=%u", Flags, CurrentUTCOffset); + + return offset; +} + + +static int +dissect_PNPTCP_Master(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item) +{ + guint8 MasterPriority1; + guint8 MasterPriority2; + guint8 ClockClass; + guint8 ClockAccuracy; + gint16 ClockVariance; + + + /* MasterPriority1 is a bit field */ + /* Bit 0 - 2: PTCP_MasterPriority1.Priority */ + dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority1, &MasterPriority1); + /* Bit 3 - 5: PTCP_MasterPriority1.Level */ + dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority_level, &MasterPriority1); + /* Bit 6: PTCP_MasterPriority1.Reserved */ + dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority1_res, &MasterPriority1); + /* Bit 7: PTCP_MasterPriority1.Active */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority1_act, &MasterPriority1); + + /* MasterPriority2 */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_master_priority2, &MasterPriority2); + + /* ClockClass */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_clock_class, &ClockClass); + + /* ClockAccuracy */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_clock_accuracy, &ClockAccuracy); + + /* ClockVariance */ + offset = dissect_pn_int16(tvb, offset, pinfo, tree, hf_pn_ptcp_clockvariance, &ClockVariance); + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", Prio1=\"%s\"", + val_to_str(MasterPriority1 & 0x7, pn_ptcp_master_prio1_vals, "(Reserved: 0x%x)")); + + if ((MasterPriority1 & 0x80) == 0) { + proto_item_append_text(item, ": Prio1=\"%s\", Prio2=%s, Clock: Class=\"%s\", Accuracy=%s, Variance=%d", + val_to_str(MasterPriority1 & 0x7, pn_ptcp_master_prio1_vals, "(Reserved: 0x%x)"), + val_to_str(MasterPriority2, pn_ptcp_master_prio2_vals, "(Reserved: 0x%x)"), + val_to_str(ClockClass, pn_ptcp_clock_class_vals, "(Reserved: 0x%x)"), + val_to_str(ClockAccuracy, pn_ptcp_clock_accuracy_vals, "(Reserved: 0x%x)"), + ClockVariance); + } + else { + col_append_str(pinfo->cinfo, COL_INFO, " active"); + proto_item_append_text(item, ": Prio1=\"%s\" is active, Prio2=%s, Clock: Class=\"%s\", Accuracy=%s, Variance=%d", + val_to_str(MasterPriority1 & 0x7, pn_ptcp_master_prio1_vals, "(Reserved: 0x%x)"), + val_to_str(MasterPriority2, pn_ptcp_master_prio2_vals, "(Reserved: 0x%x)"), + val_to_str(ClockClass, pn_ptcp_clock_class_vals, "(Reserved: 0x%x)"), + val_to_str(ClockAccuracy, pn_ptcp_clock_accuracy_vals, "(Reserved: 0x%x)"), + ClockVariance); + } + + + return offset; +} + + +static int +dissect_PNPTCP_PortParameter(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item) +{ + guint32 t2portrxdelay; + guint32 t3porttxdelay; + + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* T2PortRxDelay */ + proto_tree_add_item_ret_uint(tree, hf_pn_ptcp_t2portrxdelay, tvb, offset, 4, ENC_BIG_ENDIAN, &t2portrxdelay); + offset += 4; + + /* T3PortTxDelay */ + proto_tree_add_item_ret_uint(tree, hf_pn_ptcp_t3porttxdelay, tvb, offset, 4, ENC_BIG_ENDIAN, &t3porttxdelay); + offset += 4; + + proto_item_append_text(item, ": T2PortRxDelay=%uns, T3PortTxDelay=%uns", + t2portrxdelay, t3porttxdelay); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", T2Rx=%uns, T3Tx=%uns", + t2portrxdelay, t3porttxdelay); + + return offset; +} + + +static int +dissect_PNPTCP_DelayParameter(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item) +{ + guint8 mac[6]; + + + /* PortMACAddress */ + offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_ptcp_port_mac_address, mac); + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + + proto_item_append_text(item, ": PortMAC=%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", PortMAC=%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + return offset; +} + + +static int +dissect_PNPTCP_PortTime(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item) +{ + guint32 t2timestamp; + + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* T2TimeStamp */ + proto_tree_add_item_ret_uint(tree, hf_pn_ptcp_t2timestamp, tvb, offset, 4, ENC_BIG_ENDIAN, &t2timestamp); + offset += 4; + + proto_item_append_text(item, ": T2TimeStamp=%uns", t2timestamp); + + col_append_fstr(pinfo->cinfo, COL_INFO, ", T2TS=%uns", t2timestamp); + + return offset; +} + + +static int +dissect_PNPTCP_Option_PROFINET(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 length) +{ + guint8 subType; + e_guid_t uuid; + + /* OUI already dissected! */ + + /* SubType */ + offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_profinet_subtype, &subType); + length -= 1; + + switch (subType) { + case 1: /* RTData */ + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + /* IRDataUUID */ + offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_irdata_uuid, &uuid); + proto_item_append_text(item, ": IRDataUUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + uuid.data1, uuid.data2, uuid.data3, + uuid.data4[0], uuid.data4[1], + uuid.data4[2], uuid.data4[3], + uuid.data4[4], uuid.data4[5], + uuid.data4[6], uuid.data4[7]); + + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length); + break; + } + + return offset; +} + + +static int +dissect_PNPTCP_Option(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 length) +{ + guint32 oui; + + + /* verify remaining TLV length */ + if (length < 4) + { + /* too short */ + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length); + return (offset); + } + + /* OUI (organizational unique id) */ + offset = dissect_pn_oid(tvb, offset, pinfo,tree, hf_pn_ptcp_oui, &oui); + length -= 3; + + switch (oui) + { + case OUI_PROFINET: + case OUI_PROFINET_MULTICAST: + proto_item_append_text(item, ": PROFINET"); + offset = dissect_PNPTCP_Option_PROFINET(tvb, offset, pinfo, tree, item, length); + break; + default: + /* SubType */ + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length); + } + + return (offset); +} + + +static int +dissect_PNPTCP_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, gboolean *end, guint16 u16FrameID) +{ + guint16 type; + guint16 length; + + proto_item *sub_item; + proto_tree *sub_tree; + proto_item *tlvheader_item; + proto_tree *tlvheader_tree; + guint32 u32SubStart; + + + *end = FALSE; + + /* block subtree */ + sub_item = proto_tree_add_item(tree, hf_pn_ptcp_block, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_ptcp_block); + u32SubStart = offset; + + /* tlvheader subtree */ + tlvheader_item = proto_tree_add_item(sub_tree, hf_pn_ptcp_block_tlvheader, tvb, offset, 2 /* len */, ENC_NA); + tlvheader_tree = proto_item_add_subtree(tlvheader_item, ett_pn_ptcp_block_header); + + offset = dissect_PNPTCP_TLVHeader(tvb, offset, pinfo, tlvheader_tree, sub_item, &type, &length); + + proto_item_set_text(sub_item, "%s", + val_to_str_const(type, pn_ptcp_block_type, "Unknown")); + + proto_item_append_text(tlvheader_item, ": Type=%s (%x), Length=%u", + val_to_str_const(type, pn_ptcp_block_type, "Unknown"), type, length); + + switch (type) { + case 0x00: /* End, no content */ + *end = TRUE; + break; + case 0x01: /* Subdomain */ + dissect_PNPTCP_Subdomain(tvb, offset, pinfo, sub_tree, sub_item, u16FrameID); + break; + case 0x02: /* Time */ + dissect_PNPTCP_Time(tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x03: /* TimeExtension */ + dissect_PNPTCP_TimeExtension(tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x04: /* Master */ + dissect_PNPTCP_Master(tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x05: /* PortParameter */ + dissect_PNPTCP_PortParameter(tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x06: /* DelayParameter */ + dissect_PNPTCP_DelayParameter(tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x07: /* PortTime */ + dissect_PNPTCP_PortTime(tvb, offset, pinfo, sub_tree, sub_item); + break; + case 0x7F: /* Organizational Specific */ + dissect_PNPTCP_Option(tvb, offset, pinfo, sub_tree, sub_item, length); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length); + } + offset += length; + + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + +static int +dissect_PNPTCP_blocks(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID) +{ + gboolean end = FALSE; + + /* as long as we have some bytes, try a new block */ + while (!end) { + offset = dissect_PNPTCP_block(tvb, offset, pinfo, tree, item, &end, u16FrameID); + } + + return offset; +} + + +static int +dissect_PNPTCP_FollowUpPDU(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, + const char *name, const char *name_short) +{ + proto_item *header_item; + proto_tree *header_tree; + guint16 seq_id; + gint32 delay1ns_fup; + + + /* dissect the header */ + header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, ENC_NA); + header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header); + + /* Padding 12 bytes */ + offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12); + + /* SequenceID */ + offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id); + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, header_tree); + + /* Delay1ns_FUP */ + proto_tree_add_item_ret_int(header_tree, hf_pn_ptcp_delay1ns_fup, tvb, offset, 4, ENC_BIG_ENDIAN, &delay1ns_fup); + offset += 4; + + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11dns", name, seq_id, delay1ns_fup); + proto_item_append_text(item, "%s: Sequence=%u, Delay=%dns", name_short, seq_id, delay1ns_fup); + proto_item_append_text(header_item, ": Sequence=%u, Delay=%dns", seq_id, delay1ns_fup); + + + /* dissect the TLV blocks */ + offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID); + + return offset; +} + + +static int +dissect_PNPTCP_RTSyncPDU(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, + const char *name, const char *name_short) +{ + proto_item *header_item; + proto_tree *header_tree; + guint32 delay10ns; + guint16 seq_id; + guint8 delay1ns_8; + guint64 delay1ns_64; + guint32 delay1ns_32; + guint32 delayms; + + + header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, ENC_NA); + header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header); + + /* Reserved_1 */ + proto_tree_add_item(tree, hf_pn_ptcp_res1, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* Reserved_2 */ + proto_tree_add_item(tree, hf_pn_ptcp_res2, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* Delay10ns */ + proto_tree_add_item_ret_uint(tree, hf_pn_ptcp_delay10ns, tvb, offset, 4, ENC_BIG_ENDIAN, &delay10ns); + offset += 4; + + /* SequenceID */ + offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id); + + /* Delay1ns */ + offset = dissect_pn_uint8(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns_byte, &delay1ns_8); + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, header_tree); + + /* Delay1ns */ + proto_tree_add_item_ret_uint(tree, hf_pn_ptcp_delay1ns, tvb, offset, 4, ENC_BIG_ENDIAN, &delay1ns_32); + offset += 4; + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, tree); + + + delay1ns_64 = ((guint64) delay10ns) * 10 + delay1ns_8 + delay1ns_32; + delayms = (guint32) (delay1ns_64 / (1000 * 1000)); + + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11" PRIu64 "ns", + name, seq_id, delay1ns_64); + proto_item_append_text(item, "%s: Sequence=%u, Delay=%" PRIu64 "ns", + name_short, seq_id, delay1ns_64); + proto_item_append_text(header_item, ": Sequence=%u, Delay=%" PRIu64 "ns", + seq_id, delay1ns_64); + + if (delay1ns_64 != 0) + proto_item_append_text(header_item, " (%u.%03u,%03u,%03u sec)", + delayms / 1000, + delayms % 1000, + (delay10ns % (1000*100)) / 100, + delay10ns % 100 * 10 + delay1ns_8); + + /* dissect the PDU */ + offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID); + + return offset; +} + + +static int +dissect_PNPTCP_AnnouncePDU(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, + const char *name, const char *name_short) +{ + proto_item *header_item; + proto_tree *header_tree; + guint16 seq_id; + + + /* dissect the header */ + header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, ENC_NA); + header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header); + + /* Padding 12 bytes */ + offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12); + + /* SequenceID */ + offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id); + + /* Padding 6 bytes */ + offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 6); + + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u", name, seq_id); + proto_item_append_text(item, "%s: Sequence=%u", name_short, seq_id); + proto_item_append_text(header_item, ": Sequence=%u", seq_id); + + + /* dissect the PDU */ + offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID); + + return offset; +} + + +static int +dissect_PNPTCP_DelayPDU(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID, + const char *name, const char *name_short) +{ + proto_item *header_item; + proto_tree *header_tree; + guint16 seq_id; + guint32 delay1ns; + + + /* dissect the header */ + header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, ENC_NA); + header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header); + + /* Padding 12 bytes */ + offset = dissect_pn_padding(tvb, offset, pinfo, header_tree, 12); + + /* SequenceID */ + offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id); + + /* Padding */ + offset = dissect_pn_align4(tvb, offset, pinfo, header_tree); + + /* Delay1ns_FUP */ + proto_tree_add_item_ret_uint(tree, hf_pn_ptcp_delay1ns, tvb, offset, 4, ENC_BIG_ENDIAN, &delay1ns); + offset += 4; + + col_append_fstr(pinfo->cinfo, COL_INFO, "%s, Seq=%3u, Delay=%11uns", name, seq_id, delay1ns); + proto_item_append_text(item, "%s: Sequence=%u, Delay=%uns", name_short, seq_id, delay1ns); + proto_item_append_text(header_item, ": Sequence=%u, Delay=%uns", seq_id, delay1ns); + + + /* dissect the PDU */ + offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item, u16FrameID); + + return offset; +} + + +/* possibly dissect a PN-RT packet (frame ID must be in the appropriate range) */ +static gboolean +dissect_PNPTCP_Data_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + /* the tvb will NOT contain the frame_id here, so get it from dissector data! */ + guint16 u16FrameID = GPOINTER_TO_UINT(data); + proto_item *item; + proto_tree *ptcp_tree; + int offset = 0; + guint32 u32SubStart; + + + /* frame id must be in valid range (acyclic Real-Time, PTCP) */ + /* 0x0000 - 0x007F: RTSyncPDU (with follow up) */ + /* 0x0080 - 0x00FF: RTSyncPDU (without follow up) */ + /* 0xFF00 - 0xFF1F: AnnouncePDU */ + /* 0xFF20 - 0xFF3F: FollowUpPDU */ + /* 0xFF40 - 0xFF5F: Delay...PDU */ + if ( ((u16FrameID >= 0x0100) && (u16FrameID < 0xFF00)) || (u16FrameID > 0xFF5F) ) { + /* we are not interested in this packet */ + return FALSE; + } + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-PTCP"); + col_clear(pinfo->cinfo, COL_INFO); + + /* subtree for PTCP */ + item = proto_tree_add_protocol_format(tree, proto_pn_ptcp, tvb, 0, 0, "PROFINET PTCP, "); + ptcp_tree = proto_item_add_subtree(item, ett_pn_ptcp); + u32SubStart = offset; + + switch (u16FrameID) { + /* range 1 (0x0000 - 0x007F) */ + /* 0x0000 - 0x001F reserved */ + case 0x0020: + offset = dissect_PNPTCP_RTSyncPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "RTSync FU (Clock)", "RTSync FU (Clock)"); + break; + case 0x0021: + offset = dissect_PNPTCP_RTSyncPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "RTSync FU (Time)", "RTSync FU (Time)"); + break; + /* 0x0022 - 0x007F reserved */ + + /* range 2 (0x0080 - 0x00FF) */ + case 0x0080: + offset = dissect_PNPTCP_RTSyncPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "RTSync (Clock)", "RTSync (Clock)"); + break; + case 0x0081: + offset = dissect_PNPTCP_RTSyncPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "RTSync (Time)", "RTSync (Time)"); + break; + /* 0x0081 - 0x00FF reserved */ + + /* range 7 (0xFF00 - 0xFF5F) */ + case 0xff00: + offset = dissect_PNPTCP_AnnouncePDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "Announce (Clock)", "Announce (Clock)"); + break; + case 0xff01: + offset = dissect_PNPTCP_AnnouncePDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "Announce (Time)", "Announce (Time)"); + break; + /* 0xFF02 - 0xFF1F reserved */ + case 0xff20: + offset = dissect_PNPTCP_FollowUpPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "FollowUp (Clock)", "FollowUp (Clock)"); + break; + case 0xff21: + offset = dissect_PNPTCP_FollowUpPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "FollowUp (Time)", "FollowUp (Time)"); + break; + /* 0xFF22 - 0xFF3F reserved */ + case 0xff40: + offset = dissect_PNPTCP_DelayPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "DelayReq ", "DelayReq"); + break; + case 0xff41: + offset = dissect_PNPTCP_DelayPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "DelayRes ", "DelayRes"); + break; + case 0xff42: + offset = dissect_PNPTCP_DelayPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "DelayFuRes ", "DelayFuRes"); + break; + case 0xff43: + offset = dissect_PNPTCP_DelayPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID, + "DelayRes ", "DelayRes"); + break; + /* 0xFF44 - 0xFF5F reserved */ + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset)); + + col_append_fstr(pinfo->cinfo, COL_INFO, "Reserved FrameID 0x%04x", u16FrameID); + + proto_item_append_text(item, "Reserved FrameID 0x%04x", u16FrameID); + + offset += tvb_captured_length_remaining(tvb, offset); + break; + } + + proto_item_set_len(item, offset - u32SubStart); + + return TRUE; +} + + +void +proto_register_pn_ptcp (void) +{ + static hf_register_info hf[] = { + { &hf_pn_ptcp_header, + { "Header", "pn_ptcp.header", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_block, + { "Block", "pn_ptcp.block", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_block_tlvheader, + { "TLVHeader", "pn_ptcp.tlvheader", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + + { &hf_pn_ptcp_res1, + { "Reserved 1", "pn_ptcp.res1", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_res2, + { "Reserved 2", "pn_ptcp.res2", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_delay10ns, + { "Delay10ns", "pn_ptcp.delay10ns", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_seq_id, + { "SequenceID", "pn_ptcp.sequence_id", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_delay1ns_byte, + { "Delay1ns_Byte", "pn_ptcp.delay1ns_byte", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_delay1ns, + { "Delay1ns", "pn_ptcp.delay1ns", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_delay1ns_fup, + { "Delay1ns_FUP", "pn_ptcp.delay1ns_fup", + FT_INT32, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + + { &hf_pn_ptcp_tl_length, + { "TypeLength.Length", "pn_ptcp.tl_length", + FT_UINT16, BASE_DEC, 0x0, 0x01FF, + NULL, HFILL }}, + + { &hf_pn_ptcp_tl_type, + { "TypeLength.Type", "pn_ptcp.tl_type", + FT_UINT16, BASE_DEC, 0x0, 0xFE00, + NULL, HFILL }}, + + + { &hf_pn_ptcp_master_source_address, + { "MasterSourceAddress", "pn_ptcp.master_source_address", + FT_ETHER, BASE_NONE, 0x0, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_subdomain_uuid, + { "SubdomainUUID", "pn_ptcp.subdomain_uuid", + FT_GUID, BASE_NONE, 0x0, 0x0, + NULL, HFILL }}, + + + { &hf_pn_ptcp_port_mac_address, + { "PortMACAddress", "pn_ptcp.port_mac_address", + FT_ETHER, BASE_NONE, 0x0, 0x0, + NULL, HFILL }}, + + + { &hf_pn_ptcp_t2portrxdelay, + { "T2PortRxDelay (ns)", "pn_ptcp.t2portrxdelay", + FT_UINT32, BASE_DEC, 0x0, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_t3porttxdelay, + { "T3PortTxDelay (ns)", "pn_ptcp.t3porttxdelay", + FT_UINT32, BASE_DEC, 0x0, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_t2timestamp, + { "T2TimeStamp (ns)", "pn_ptcp.t2timestamp", + FT_UINT32, BASE_DEC, 0x0, 0x0, + NULL, HFILL }}, + + + { &hf_pn_ptcp_epoch_number, + { "EpochNumber", "pn_ptcp.epoch_number", + FT_UINT16, BASE_DEC, 0x0, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_seconds, + { "Seconds", "pn_ptcp.seconds", + FT_UINT32, BASE_DEC, 0x0, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_nanoseconds, + { "NanoSeconds", "pn_ptcp.nanoseconds", + FT_UINT32, BASE_DEC, 0x0, 0x0, + NULL, HFILL }}, + + + { &hf_pn_ptcp_flags, + { "Flags", "pn_ptcp.flags", + FT_UINT16, BASE_HEX, 0x0, 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_currentutcoffset, + { "CurrentUTCOffset", "pn_ptcp.currentutcoffset", + FT_UINT16, BASE_DEC, 0x0, 0x0, + NULL, HFILL }}, + + + { &hf_pn_ptcp_master_priority1, + { "MasterPriority1.Priority", "pn_ptcp.master_priority1_prio", + FT_UINT8, BASE_HEX, VALS(pn_ptcp_master_prio1_vals), 0x07, + NULL, HFILL }}, + + { &hf_pn_ptcp_master_priority_level, + { "MasterPriority1.Level", "pn_ptcp.master_priority1_level", + FT_UINT8, BASE_HEX, VALS(pn_ptcp_master_prio1_levels), 0x38, + NULL, HFILL }}, + + { &hf_pn_ptcp_master_priority1_res, + { "MasterPriority1.Reserved", "pn_ptcp.master_priority1_res", + FT_UINT8, BASE_HEX, 0x0, 0x40, + NULL, HFILL }}, + + { &hf_pn_ptcp_master_priority1_act, + { "MasterPriority1.Active", "pn_ptcp.master_priority1_act", + FT_UINT8, BASE_HEX, VALS(pn_ptcp_master_prio1_vals_active), 0x80, + NULL, HFILL }}, + + { &hf_pn_ptcp_master_priority2, + { "MasterPriority2", "pn_ptcp.master_priority2", + FT_UINT8, BASE_DEC, VALS(pn_ptcp_master_prio2_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_clock_class, + { "ClockClass", "pn_ptcp.clock_class", + FT_UINT8, BASE_DEC, VALS(pn_ptcp_clock_class_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_clock_accuracy, + { "ClockAccuracy", "pn_ptcp.clock_accuracy", + FT_UINT8, BASE_DEC, VALS(pn_ptcp_clock_accuracy_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_clockvariance, + { "ClockVariance", "pn_ptcp.clockvariance", + FT_INT16, BASE_DEC, 0x0, 0x0, + NULL, HFILL }}, + + + { &hf_pn_ptcp_oui, + { "Organizationally Unique Identifier", "pn_ptcp.oui", + FT_UINT24, BASE_HEX, VALS(pn_ptcp_oui_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_ptcp_profinet_subtype, + { "Subtype", "pn_ptcp.subtype", + FT_UINT8, BASE_HEX, VALS(pn_ptcp_profinet_subtype_vals), 0x0, + "PROFINET Subtype", HFILL }}, + + + { &hf_pn_ptcp_irdata_uuid, + { "IRDataUUID", "pn_ptcp.irdata_uuid", + FT_GUID, BASE_NONE, 0x0, 0x0, + NULL, HFILL }}, + + }; + + static gint *ett[] = { + &ett_pn_ptcp, + &ett_pn_ptcp_header, + &ett_pn_ptcp_block, + &ett_pn_ptcp_block_header + }; + proto_pn_ptcp = proto_register_protocol ("PROFINET PTCP", "PN-PTCP", "pn_ptcp"); + proto_register_field_array (proto_pn_ptcp, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); +} + +void +proto_reg_handoff_pn_ptcp (void) +{ + /* register ourself as an heuristic pn-rt payload dissector */ + heur_dissector_add("pn_rt", dissect_PNPTCP_Data_heur, "PROFINET PTCP IO", "pn_ptcp_pn_rt", proto_pn_ptcp, HEURISTIC_ENABLE); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-pn-rsi.c b/plugins/epan/profinet/packet-pn-rsi.c new file mode 100644 index 00000000..94d61a8b --- /dev/null +++ b/plugins/epan/profinet/packet-pn-rsi.c @@ -0,0 +1,1087 @@ +/* packet-pn-rsi.c + * Routines for PN-RSI + * packet dissection. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "packet-pn.h" + +void proto_register_pn_rsi(void); +void proto_reg_handoff_pn_rsi(void); + +static int proto_pn_rsi = -1; + +static int hf_pn_rsi_dst_srv_access_point = -1; +static int hf_pn_rsi_src_srv_access_point = -1; + +static int hf_pn_rsi_pdu_type = -1; +static int hf_pn_rsi_pdu_type_type = -1; +static int hf_pn_rsi_pdu_type_version = -1; + +static int hf_pn_rsi_add_flags = -1; +static int hf_pn_rsi_add_flags_windowsize = -1; +static int hf_pn_rsi_add_flags_reserved1 = -1; +static int hf_pn_rsi_add_flags_tack = -1; +static int hf_pn_rsi_add_flags_morefrag = -1; +static int hf_pn_rsi_add_flags_notification = -1; +static int hf_pn_rsi_add_flags_reserved2 = -1; + +static int hf_pn_rsi_send_seq_num = -1; +static int hf_pn_rsi_ack_seq_num = -1; +static int hf_pn_rsi_var_part_len = -1; + +static int hf_pn_rsi_f_opnum_offset = -1; +static int hf_pn_rsi_f_opnum_offset_offset = -1; +static int hf_pn_rsi_f_opnum_offset_opnum = -1; +static int hf_pn_rsi_f_opnum_offset_callsequence = -1; + +static int hf_pn_rsi_conn_block = -1; +static int hf_pn_rsi_rsp_max_length = -1; +static int hf_pn_rsi_vendor_id = -1; +static int hf_pn_rsi_device_id = -1; +static int hf_pn_rsi_instance_id = -1; +static int hf_pn_rsi_interface = -1; + +static int hf_pn_rsi_svcs_block = -1; + +static int hf_pn_rsi_number_of_entries = -1; +static int hf_pn_rsi_pd_rsi_instance = -1; +static int hf_pn_rsi_device_type = -1; +static int hf_pn_rsi_order_id = -1; +static int hf_pn_rsi_im_serial_number = -1; +static int hf_pn_rsi_hw_revision = -1; +static int hf_pn_rsi_sw_revision_prefix = -1; +static int hf_pn_rsi_sw_revision = -1; + +static gint ett_pn_rsi = -1; +static gint ett_pn_rsi_pdu_type = -1; +static gint ett_pn_rsi_f_opnum_offset = -1; +static gint ett_pn_rsi_conn_block = -1; +static gint ett_pn_rsi_svcs_block = -1; +static gint ett_pn_rsi_add_flags = -1; +static gint ett_pn_rsi_rta = -1; +static gint ett_pn_io_pd_rsi_instance = -1; + +static expert_field ei_pn_rsi_error = EI_INIT; + +static const range_string pn_rsi_alarm_endpoint[] = { + { 0x0000, 0x7FFF, "RSI Initiator Instance (ISAP) or RSI Responder Instance (RSAP)" }, + { 0x8000, 0xFFFE, "Reserved" }, + { 0xFFFF, 0xFFFF, "CON-SAP" }, + { 0, 0, NULL } +}; + +static const range_string pn_rsi_pdu_type_type[] = { + { 0x00, 0x02, "Reserved" }, + { 0x03, 0x03, "RTA_TYPE_ACK" }, + { 0x04, 0x04, "RTA_TYPE_ERR" }, + { 0x05, 0x05, "RTA_TYPE_FREQ" }, + { 0x06, 0x06, "RTA_TYPE_FRSP" }, + { 0x07, 0x0F, "Reserved" }, + { 0, 0, NULL } +}; + +static const range_string pn_rsi_pdu_type_version[] = { + { 0x00, 0x00, "Reserved" }, + { 0x01, 0x01, "Version 1 of the protocol" }, + { 0x02, 0x02, "Version 2 of the protocol" }, + { 0x03, 0X0F, "Reserved" }, + { 0, 0, NULL } +}; + +static const value_string pn_rsi_add_flags_windowsize[] = { + { 0x00, "Reserved" }, + { 0x01, "Unknown WindowSize" }, + { 0x02, "Smallest WindowSize" }, + { 0x03, "Optional usable WindowSize" }, + { 0x04, "Optional usable WindowSize" }, + { 0x05, "Optional usable WindowSize" }, + { 0x06, "Optional usable WindowSize" }, + { 0x07, "Optional usable WindowSize" }, + { 0, NULL } +}; + +static const value_string pn_rsi_add_flags_tack[] = { + { 0x00, "No immediate acknowledge" }, + { 0x01, "Immediate acknowledge" }, + { 0, NULL } +}; + +static const value_string pn_rsi_add_flags_morefrag[] = { + { 0x00, "Last fragment" }, + { 0x01, "More fragments follows" }, + { 0, NULL } +}; + +static const value_string pn_rsi_add_flags_notification[] = { + { 0x00, "No action necessary" }, + { 0x01, "The ApplicationReadyBlock is available for reading with the service ReadNotification" }, + { 0, NULL } +}; + +static const range_string pn_rsi_seq_num[] = { + { 0x0000, 0x7FFF, "synchronization and transmission between initiator and responder" }, + { 0x8000, 0xFFFD, "Reserved" }, + { 0xFFFE, 0xFFFE, "synchronize initiator and responder for establishment of an AR" }, + { 0xFFFF, 0xFFFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const range_string pn_rsi_var_part_len[] = { + { 0x0000, 0x0000, "No RTA-SDU or RSI-SDU exists" }, + { 0x0001, 0x0598, "An RTA-SDU or RSI-PDU with VarPartLen octets exists" }, + { 0x0599, 0xFFFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const range_string pn_rsi_f_opnum_offset_offset[] = { + { 0x00000000, 0x00000000, "First fragment" }, + { 0x00000001, 0x00000003, "Reserved" }, + { 0x00000004, 0x00FFFFFF, "Not first fragment" }, + { 0, 0, NULL } +}; + +static const value_string pn_rsi_f_opnum_offset_opnum[] = { + { 0x00, "Connect" }, + { 0x01, "Reserved" }, + { 0x02, "Read" }, + { 0x03, "Write" }, + { 0x04, "Control" }, + { 0x05, "ReadImplicit" }, + { 0x06, "ReadConnectionless" }, + { 0x07, "ReadNotification" }, + { 0x08, "PrmWriteMore" }, + { 0x09, "PrmWriteEnd" }, + { 0x0A, "Reserved" }, + { 0x0B, "Reserved" }, + { 0x0C, "Reserved" }, + { 0x0D, "Reserved" }, + { 0x0E, "Reserved" }, + { 0x0F, "Reserved" }, + { 0x1F, "Reserved" }, + { 0, NULL } +}; + +static const range_string pn_rsi_f_opnum_offset_callsequence[] = { + { 0x00, 0x07, "Allowed values" }, + { 0, 0, NULL } +}; + +static const range_string pn_rsi_rsp_max_length[] = { + { 0x00000000, 0x00000003, "Reserved" }, + { 0x00000004, 0x00FFFFFF, "Usable" }, + { 0x01FFFFFF, 0xFFFFFFFF, "Reserved" }, + { 0, 0, NULL } +}; + +static const range_string pn_rsi_interface[] = { + { 0x00, 0x00, "IO device interface" }, + { 0x01, 0x01, "Read Implicit IO device interface" }, + { 0x02, 0x02, "CIM device interface" }, + { 0x03, 0x03, "Read Implicit CIM device interface" }, + { 0x04, 0xFF, "Reserved" }, + { 0, 0, NULL } +}; + +static int +dissect_FOpnumOffset(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, guint32 *u32FOpnumOffset) +{ + proto_item *sub_item; + proto_tree *sub_tree; + + sub_item = proto_tree_add_item(tree, hf_pn_rsi_f_opnum_offset, tvb, offset, 4, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_f_opnum_offset); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_f_opnum_offset_offset, u32FOpnumOffset); + dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_f_opnum_offset_opnum, u32FOpnumOffset); + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_f_opnum_offset_callsequence, u32FOpnumOffset); + + return offset; +} + +static int hf_pn_rsi_data_payload = -1; + +static int hf_pn_rsi_segments = -1; +static int hf_pn_rsi_segment = -1; +//static int hf_pn_rsi_data = -1; +static int hf_pn_rsi_segment_overlap = -1; +static int hf_pn_rsi_segment_overlap_conflict = -1; +static int hf_pn_rsi_segment_multiple_tails = -1; +static int hf_pn_rsi_segment_too_long_segment = -1; +static int hf_pn_rsi_segment_error = -1; +static int hf_pn_rsi_segment_count = -1; +static int hf_pn_rsi_reassembled_in = -1; +static int hf_pn_rsi_reassembled_length = -1; + +static reassembly_table pn_rsi_reassembly_table; + +void +pn_rsi_reassemble_init(void) +{ + reassembly_table_register(&pn_rsi_reassembly_table, &addresses_reassembly_table_functions); +} + +static gint ett_pn_rsi_segments = -1; +static gint ett_pn_rsi_segment = -1; +//static gint ett_pn_rsi_data = -1; +static gint ett_pn_rsi_data_payload = -1; + +static const fragment_items pn_rsi_frag_items = { + &ett_pn_rsi_segment, + &ett_pn_rsi_segments, + &hf_pn_rsi_segments, + &hf_pn_rsi_segment, + &hf_pn_rsi_segment_overlap, + &hf_pn_rsi_segment_overlap_conflict, + &hf_pn_rsi_segment_multiple_tails, + &hf_pn_rsi_segment_too_long_segment, + &hf_pn_rsi_segment_error, + &hf_pn_rsi_segment_count, + &hf_pn_rsi_reassembled_in, + &hf_pn_rsi_reassembled_length, + /* Reassembled data field */ + NULL, + "segments" +}; + +static int +dissect_pn_rta_remaining_user_data_bytes(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint8 *drep, guint32 length, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOpnum, int type) +{ + fragment_head *fd_frag; + fragment_head *fd_reass; + conversation_t *conv; + tvbuff_t *next_tvb; + proto_item *pn_rsi_tree_item; + proto_item *payload_item = NULL; + proto_item *payload_tree = NULL; + gboolean update_col_info = TRUE; + + if (pinfo->srcport != 0 && pinfo->destport != 0) { + /* COTP over RFC1006/TCP, try reassembling */ + conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, CONVERSATION_NONE, + pinfo->srcport, pinfo->destport, 0); + if (!conv) { + conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, CONVERSATION_NONE, + pinfo->srcport, pinfo->destport, 0); + } + + /* XXX - don't know if this will work with multiple segmented Ack's in a single TCP stream */ + fd_frag = fragment_get(&pn_rsi_reassembly_table, pinfo, conv->conv_index, NULL); + fd_reass = fragment_get_reassembled_id(&pn_rsi_reassembly_table, pinfo, conv->conv_index); + } + else { + /* plain COTP transport (without RFC1006/TCP), try reassembling */ + conv = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, CONVERSATION_NONE, + pinfo->clnp_srcref, pinfo->clnp_dstref, 0); + if (!conv) { + conv = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, CONVERSATION_NONE, + pinfo->clnp_srcref, pinfo->clnp_dstref, 0); + } + + /* XXX - don't know if this will work with multiple segmented Ack's in a single TCP stream */ + fd_frag = fragment_get(&pn_rsi_reassembly_table, pinfo, conv->conv_index, NULL); + fd_reass = fragment_get_reassembled_id(&pn_rsi_reassembly_table, pinfo, conv->conv_index); + } + + /* is this packet containing a "standalone" segment? */ + if (!u8MoreFrag && !fd_frag && !fd_reass) { + /* "standalone" segment, simply show payload and return */ + offset = dissect_blocks(tvb, offset, pinfo, tree, drep); + return offset; + } + + /* multiple segments */ + if (!pinfo->fd->visited && conv != NULL) { + /* we haven't seen it before, add to list of segments */ + fragment_add_seq_next(&pn_rsi_reassembly_table, tvb, offset, pinfo, conv->conv_index, + NULL /*Data comes from tvb as in packet-icmp-template.c */, + length, + u8MoreFrag); + + fd_reass = fragment_get_reassembled_id(&pn_rsi_reassembly_table, pinfo, conv->conv_index); + } + + /* update display */ + col_append_fstr(pinfo->cinfo, COL_INFO, " [%sPN IO RSI Segment]", + u8MoreFrag ? "" : "Last "); + + /* reassembling completed? */ + if (fd_reass != NULL) { + /* is this the packet to show the reassembed payload in? */ + if (pinfo->fd->num == fd_reass->reassembled_in) { + next_tvb = process_reassembled_data(tvb, 0, pinfo, + "Reassembled PN IO RSI packet", fd_reass, &pn_rsi_frag_items, &update_col_info, tree); + + /* XXX - create new parent tree item "Reassembled Data Segments" */ + payload_item = proto_tree_add_item(tree, hf_pn_rsi_data_payload, next_tvb, 0, tvb_captured_length(next_tvb), ENC_NA); + payload_tree = proto_item_add_subtree(payload_item, ett_pn_rsi_data_payload); + + offset = dissect_rsi_blocks(next_tvb, 0, pinfo, payload_tree, drep, u32FOpnumOffsetOpnum, type); + + /* the toplevel fragment subtree is now behind all desegmented data, + * move it right behind the DE2 tree item */ + // pn_rsi_tree_item = proto_tree_get_parent(tree); + + } + else { + /* segment of a multiple segment payload */ + proto_item *pi; + + pn_rsi_tree_item = proto_tree_get_parent(tree); + pi = proto_tree_add_uint(pn_rsi_tree_item, hf_pn_rsi_reassembled_in, + tvb, 0, 0, fd_reass->reassembled_in); + proto_item_set_generated(pi); + } + } + + return offset; +} + +/* dissect a PN-IO RSI SVCS block (on top of PN-RT protocol) */ +static int +dissect_RSI_SVCS_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum) +{ + proto_item* sub_item; + proto_tree *sub_tree; + + guint32 u32RsiHeaderSize = 4; + guint32 u32RspMaxLength; + + // PDU.FOpnumOffset.Offset + PDU.VarPartLen - 4 - RsiHeaderSize + gint32 length = u32FOpnumOffsetOffset + u16VarPartLen - 4 - u32RsiHeaderSize; + + sub_item = proto_tree_add_item(tree, hf_pn_rsi_svcs_block, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_svcs_block); + + if (u32FOpnumOffsetOffset == 0) + { + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_rsp_max_length, &u32RspMaxLength); + } + else if (u8MoreFrag == 0) + { + proto_item_append_text(sub_item, ", RSI Header of SVCS is at first segment"); + } + + if (length > 0) { + offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, sub_tree, drep, + tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_REQ); + } + return offset; +} + +/* dissect a PN-IO RSI CONN block (on top of PN-RT protocol) */ +static int +dissect_RSI_CONN_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum) +{ + proto_item *sub_item; + proto_tree *sub_tree; + + guint32 u32RspMaxLength; + guint16 u16VendorId; + guint16 u16DeviceId; + guint16 u16InstanceId; + guint8 u8RsiInterface; + guint32 u32RsiHeaderSize = 4; + + // PDU.FOpnumOffset.Offset + PDU.VarPartLen - 4 - RsiHeaderSize + gint32 length = u32FOpnumOffsetOffset + u16VarPartLen - 4 - u32RsiHeaderSize; + + sub_item = proto_tree_add_item(tree, hf_pn_rsi_conn_block, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_conn_block); + + if (u32FOpnumOffsetOffset == 0) { + + offset = dissect_dcerpc_uint32(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_rsp_max_length, &u32RspMaxLength); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_vendor_id, &u16VendorId); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_device_id, &u16DeviceId); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_instance_id, &u16InstanceId); + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_interface, &u8RsiInterface); + + offset = dissect_pn_padding(tvb, offset, pinfo, sub_tree, 1); + } + else if (u8MoreFrag == 0) + { + proto_item_append_text(sub_item, ", RSI Header of CONN is at first segment"); + } + + if (length > 0) { + offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, sub_tree, drep, + tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_REQ); + } + + return offset; +} + +/* dissect a PN-IO RSI FREQ RTA PDU (on top of PN-RT protocol) */ +static int +dissect_FREQ_RTA_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag) +{ + guint32 u32FOpnumOffset; + guint32 u32FOpnumOffsetOpnum; + guint32 u32FOpnumOffsetOffset; + offset = dissect_FOpnumOffset(tvb, offset, pinfo, tree, drep, &u32FOpnumOffset); + u32FOpnumOffsetOpnum = (u32FOpnumOffset & 0x1F000000) >> 24; + u32FOpnumOffsetOffset = u32FOpnumOffset & 0x00FFFFFF; + switch (u32FOpnumOffsetOpnum) { + case(0x0): /* RSI-CONN-PDU */ + col_append_str(pinfo->cinfo, COL_INFO, "Connect request"); + offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + case(0x1): /* Reserved */ + col_append_str(pinfo->cinfo, COL_INFO, "Reserved"); + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb)); + break; + case(0x2): /* RSI-SVCS-PDU (Only valid with ARUUID<>0) */ + col_append_str(pinfo->cinfo, COL_INFO, "Read request"); + offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + case(0x3): /* RSI-SVCS-PDU */ + col_append_str(pinfo->cinfo, COL_INFO, "Write request"); + offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + case(0x4): /* RSI-SVCS-PDU */ + col_append_str(pinfo->cinfo, COL_INFO, "Control request"); + offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + case(0x5): /* RSI-CONN-PDU (Only valid with ARUUID=0) */ + col_append_str(pinfo->cinfo, COL_INFO, "ReadImplicit request"); + offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + case(0x6): /* RSI-CONN-PDU (Only valid with ARUUID<>0) */ + col_append_str(pinfo->cinfo, COL_INFO, "ReadConnectionless request"); + offset = dissect_RSI_CONN_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + case(0x7): /* RSI-SVCS-PDU */ + col_append_str(pinfo->cinfo, COL_INFO, "ReadNotification request"); + offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + case(0x8): /* RSI-SVCS-PDU */ + col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteMore request"); + offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + case(0x9) : /* RSI-SVCS-PDU */ + col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteEnd request"); + offset = dissect_RSI_SVCS_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + break; + default: + col_append_str(pinfo->cinfo, COL_INFO, "Reserved"); + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb)); + break; + } + return offset; +} + +/* dissect a PN-IO RSI RSP block (on top of PN-RT protocol) */ +static int +dissect_RSI_RSP_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag, guint32 u32FOpnumOffsetOffset, guint32 u32FOpnumOffsetOpnum) +{ + guint32 u32RsiHeaderSize = 4; + + // PDU.FOpnumOffset.Offset + PDU.VarPartLen - 4 - RsiHeaderSize + gint32 length = u32FOpnumOffsetOffset + u16VarPartLen - 4 - u32RsiHeaderSize; + + if (u32FOpnumOffsetOffset == 0) + { + offset = dissect_PNIO_status(tvb, offset, pinfo, tree, drep); + } + + else if (u8MoreFrag == 0) + { + proto_item_append_text(tree, ", RSI Header of RSP is at first fragmented frame"); + } + + if (length > 0) { + offset = dissect_pn_rta_remaining_user_data_bytes(tvb, offset, pinfo, tree, drep, + tvb_captured_length_remaining(tvb, offset), u8MoreFrag, u32FOpnumOffsetOpnum, PDU_TYPE_RSP); + } + + return offset; +} + +/* dissect a PN-IO RSI FRSP RTA PDU (on top of PN-RT protocol) */ +static int +dissect_FRSP_RTA_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep, guint16 u16VarPartLen, guint8 u8MoreFrag) +{ + guint32 u32FOpnumOffset; + guint32 u32FOpnumOffsetOpnum; + guint32 u32FOpnumOffsetOffset; + offset = dissect_FOpnumOffset(tvb, offset, pinfo, tree, drep, &u32FOpnumOffset); + u32FOpnumOffsetOpnum = (u32FOpnumOffset & 0x1F000000) >> 24; + u32FOpnumOffsetOffset = u32FOpnumOffset & 0x00FFFFFF; + switch (u32FOpnumOffsetOpnum) { + case(0x0): /* Connect */ + col_append_str(pinfo->cinfo, COL_INFO, "Connect response"); + break; + case(0x1): /* Reserved */ + col_append_str(pinfo->cinfo, COL_INFO, "Reserved"); + break; + case(0x2): /* Read */ + col_append_str(pinfo->cinfo, COL_INFO, "Read response"); + break; + case(0x3): /* Write */ + col_append_str(pinfo->cinfo, COL_INFO, "Write response"); + break; + case(0x4): /* Control */ + col_append_str(pinfo->cinfo, COL_INFO, "Control response"); + break; + case(0x5): /* ReadImplicit */ + col_append_str(pinfo->cinfo, COL_INFO, "ReadImplicit response"); + break; + case(0x6): /* ReadConnectionless */ + col_append_str(pinfo->cinfo, COL_INFO, "ReadConnectionless response"); + break; + case(0x7): /* ReadNotification */ + col_append_str(pinfo->cinfo, COL_INFO, "ReadNotification response"); + break; + case(0x8): /* PrmWriteMore */ + col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteMore response"); + break; + case(0x9) : /* PrmWriteEnd */ + col_append_str(pinfo->cinfo, COL_INFO, "PrmWriteEnd response"); + break; + default: + col_append_str(pinfo->cinfo, COL_INFO, "Reserved"); + break; + } + offset = dissect_RSI_RSP_block(tvb, offset, pinfo, tree, drep, u16VarPartLen, u8MoreFrag, u32FOpnumOffsetOffset, u32FOpnumOffsetOpnum); + return offset; +} + +static int +dissect_RSIAdditionalFlags(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, guint8 *u8AddFlags) +{ + guint8 u8WindowSize; + guint8 u8Tack; + proto_item *sub_item; + proto_tree *sub_tree; + + /* additional flags */ + sub_item = proto_tree_add_item(tree, hf_pn_rsi_add_flags, tvb, offset, 1, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_add_flags); + /* Bit 0 - 2 : AddFlags.WindowSize */ + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_add_flags_windowsize, u8AddFlags); + /* Bit 3: AddFlags.Reserved */ + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_add_flags_reserved1, u8AddFlags); + /* Bit 4: AddFlags.TACK */ + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_add_flags_tack, u8AddFlags); + /* Bit 5: AddFlags.MoreFrag */ + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_add_flags_morefrag, u8AddFlags); + /* Bit 6: AddFlags.Notification */ + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_add_flags_notification, u8AddFlags); + /* Bit 7: AddFlags.Reserved */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_add_flags_reserved2, u8AddFlags); + u8WindowSize = *u8AddFlags & 0x03; + u8Tack = (*u8AddFlags & 0x10); + u8Tack = (u8Tack == 0x10) ? 1 : 0; + + proto_item_append_text(sub_item, ", Window Size: %u, Tack: %u ", + u8WindowSize, u8Tack); + return offset; +} + +/* dissect a PN-IO RTA RSI PDU (on top of PN-RT protocol) */ +int +dissect_PNIO_RSI(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint16 u16DestinationServiceAccessPoint; + guint16 u16SourceServiceAccessPoint; + guint8 u8PDUType; + guint8 u8PDUVersion; + guint8 u8AddFlags; + guint8 u8MoreFrag; + guint16 u16SendSeqNum; + guint16 u16AckSeqNum; + guint16 u16VarPartLen; + int start_offset = offset; + + proto_item *rta_item; + proto_tree *rta_tree; + + proto_item *sub_item; + proto_tree *sub_tree; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO-RSI"); + rta_item = proto_tree_add_protocol_format(tree, proto_pn_rsi, tvb, offset, tvb_captured_length(tvb), + "PROFINET IO RSI"); + + rta_tree = proto_item_add_subtree(rta_item, ett_pn_rsi_rta); + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_rsi_dst_srv_access_point, &u16DestinationServiceAccessPoint); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_rsi_src_srv_access_point, &u16SourceServiceAccessPoint); + + //col_append_fstr(pinfo->cinfo, COL_INFO, ", Src: 0x%x, Dst: 0x%x", + // u16SourceServiceAccessPoint, u16DestinationServiceAccessPoint); + + /* PDU type */ + sub_item = proto_tree_add_item(rta_tree, hf_pn_rsi_pdu_type, tvb, offset, 1, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_rsi_pdu_type); + + /* PDU type type - version of RTA 2*/ + dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_pdu_type_type, &u8PDUType); + u8PDUType &= 0x0F; + + /* PDU type version - version of RTA 2*/ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_pdu_type_version, &u8PDUVersion); + u8PDUVersion >>= 4; + //proto_item_append_text(sub_item, ", Type: %s, Version: %u", + // val_to_str(u8PDUType, pn_rsi_pdu_type_type, "Unknown"), + // u8PDUVersion); + offset = dissect_RSIAdditionalFlags(tvb, offset, pinfo, rta_tree, drep, &u8AddFlags); + u8MoreFrag = (u8AddFlags >> 5) & 0x1; + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_rsi_send_seq_num, &u16SendSeqNum); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_rsi_ack_seq_num, &u16AckSeqNum); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, rta_tree, drep, + hf_pn_rsi_var_part_len, &u16VarPartLen); + + switch (u8PDUType & 0x0F) { + case(3): /* ACK-RTA */ + col_append_str(pinfo->cinfo, COL_INFO, "ACK-RTA"); + + if (u8AddFlags & 0x40) { + + col_append_str(pinfo->cinfo, COL_INFO, ", Application Ready Notification"); + } + /* no additional data */ + break; + case(4): /* ERR-RTA */ + col_append_str(pinfo->cinfo, COL_INFO, "ERR-RTA"); + offset = dissect_PNIO_status(tvb, offset, pinfo, rta_tree, drep); + break; + case(5): /* FREQ-RTA */ + offset = dissect_FREQ_RTA_block(tvb, offset, pinfo, rta_tree, drep, u16VarPartLen, u8MoreFrag); + break; + case(6): /* FRSP-RTA */ + offset = dissect_FRSP_RTA_block(tvb, offset, pinfo, rta_tree, drep, u16VarPartLen, u8MoreFrag); + break; + default: + offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, tvb_captured_length(tvb)); + break; + } + + proto_item_set_len(rta_item, offset - start_offset); + + return offset; +} + +int +dissect_PDRsiInstances_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint16 u16NumberOfEntries; + guint16 u16VendorId; + guint16 u16DeviceId; + guint16 u16InstanceId; + guint8 u8RsiInterface; + const int deviceType_size = 25; + const int orderID_size = 20; + const int IMserialnumber_size = 16; + const int HWrevision_size = 5; + const int SWrevisionprefix_size = 1; + const int SWrevision_size = 9; + + if (u8BlockVersionHigh != 1 || u8BlockVersionLow != 0) { + expert_add_info_format(pinfo, item, &ei_pn_rsi_error, + "Block version %u.%u not implemented yet!", u8BlockVersionHigh, u8BlockVersionLow); + return offset; + } + + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, tree, drep, + hf_pn_rsi_number_of_entries, &u16NumberOfEntries); + + proto_item_append_text(item, ": NumberOfEntries:%u", u16NumberOfEntries); + + while (u16NumberOfEntries > 0) { + u16NumberOfEntries--; + + sub_item = proto_tree_add_item(tree, hf_pn_rsi_pd_rsi_instance, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_pd_rsi_instance); + /* VendorID */ + /* DeviceID */ + /* InstanceID */ + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_vendor_id, &u16VendorId); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_device_id, &u16DeviceId); + offset = dissect_dcerpc_uint16(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_instance_id, &u16InstanceId); + + /* RSI Interface */ + offset = dissect_dcerpc_uint8(tvb, offset, pinfo, sub_tree, drep, + hf_pn_rsi_interface, &u8RsiInterface); + + proto_item_append_text(sub_item, ": VendorID:%u, DeviceID:%u, InstanceID:%u, RsiInterface:%u", + u16VendorId, u16DeviceId, u16InstanceId, u8RsiInterface); + + /* Padding */ + offset = dissect_pn_padding(tvb, offset, pinfo, sub_tree, 1); + } + + /* SystemIdentification */ + /* DeviceType */ + proto_tree_add_item(tree, hf_pn_rsi_device_type, tvb, offset, deviceType_size, ENC_UTF_8); + offset += deviceType_size + 1; + + /* Blank */ + + /* OrderID */ + proto_tree_add_item(tree, hf_pn_rsi_order_id, tvb, offset, orderID_size, ENC_UTF_8); + offset += orderID_size + 1; + + /* Blank */ + + /* IM_Serial_Number */ + proto_tree_add_item(tree, hf_pn_rsi_im_serial_number, tvb, offset, IMserialnumber_size, ENC_UTF_8); + offset += IMserialnumber_size + 1; + + /* Blank */ + + /* HWRevision */ + proto_tree_add_item(tree, hf_pn_rsi_hw_revision, tvb, offset, HWrevision_size, ENC_UTF_8); + offset += HWrevision_size + 1; + + /* Blank */ + + /* SWRevisionPrefix */ + proto_tree_add_item(tree, hf_pn_rsi_sw_revision_prefix, tvb, offset, SWrevisionprefix_size, ENC_UTF_8); + offset += SWrevisionprefix_size; + + /* SWRevision */ + proto_tree_add_item(tree, hf_pn_rsi_sw_revision, tvb, offset, SWrevision_size, ENC_UTF_8); + offset += SWrevision_size; + return offset; +} + +void +init_pn_rsi(int proto) +{ + static hf_register_info hf[] = { + { &hf_pn_rsi_dst_srv_access_point, + { "DestinationServiceAccessPoint", "pn_rsi.dst_srv_access_point", + FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_alarm_endpoint), 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_src_srv_access_point, + { "SourceServiceAccessPoint", "pn_rsi.src_srv_access_point", + FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_alarm_endpoint), 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_pdu_type, + { "PDUType", "pn_rsi.pdu_type", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_pdu_type_type, + { "Type", "pn_rsi.pdu_type.type", + FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_pdu_type_type), 0x0F, + NULL, HFILL } + }, + { &hf_pn_rsi_pdu_type_version, + { "Version", "pn_rsi.pdu_type.version", + FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_pdu_type_version), 0xF0, + NULL, HFILL } + }, + { &hf_pn_rsi_add_flags, + { "AddFlags", "pn_rsi.add_flags", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_add_flags_windowsize, + { "WindowSize", "pn_rsi.add_flags_windowsize", + FT_UINT8, BASE_HEX, VALS(pn_rsi_add_flags_windowsize), 0x07, + NULL, HFILL } + }, + { &hf_pn_rsi_add_flags_reserved1, + { "Reserved", "pn_rsi.add_flags_reserved", + FT_UINT8, BASE_HEX, NULL, 0x08, + NULL, HFILL } + }, + { &hf_pn_rsi_add_flags_tack, + { "TACK", "pn_rsi.add_flags_tack", + FT_UINT8, BASE_HEX, VALS(pn_rsi_add_flags_tack), 0x10, + NULL, HFILL } + }, + { &hf_pn_rsi_add_flags_morefrag, + { "MoreFrag", "pn_rsi.add_flags_morefrag", + FT_UINT8, BASE_HEX, VALS(pn_rsi_add_flags_morefrag), 0x20, + NULL, HFILL } + }, + { &hf_pn_rsi_add_flags_notification, + { "Notification", "pn_rsi.add_flags_notification", + FT_UINT8, BASE_HEX, VALS(pn_rsi_add_flags_notification), 0x40, + NULL, HFILL } + }, + { &hf_pn_rsi_add_flags_reserved2, + { "Reserved", "pn_rsi.add_flags_reserved", + FT_UINT8, BASE_HEX, NULL, 0x80, + NULL, HFILL } + }, + { &hf_pn_rsi_send_seq_num, + { "SendSeqNum", "pn_rsi.send_seq_num", + FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_seq_num), 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_ack_seq_num, + { "AckSeqNum", "pn_rsi.ack_seq_num", + FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_seq_num), 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_var_part_len, + { "VarPartLen", "pn_rsi.var_part_len", + FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_var_part_len), 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_f_opnum_offset, + { "FOpnumOffset", "pn_rsi.f_opnum_offset", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_f_opnum_offset_offset, + { "FOpnumOffset.Offset", "pn_rsi.f_opnum_offset.offset", + FT_UINT32, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_f_opnum_offset_offset), 0x00FFFFFF, + NULL, HFILL } + }, + { &hf_pn_rsi_f_opnum_offset_opnum, + { "FOpnumOffset.Opnum", "pn_rsi.f_opnum_offset.opnum", + FT_UINT32, BASE_HEX, VALS(pn_rsi_f_opnum_offset_opnum), 0x1F000000, + NULL, HFILL } + }, + { &hf_pn_rsi_f_opnum_offset_callsequence, + { "FOpnumOffset.CallSequence", "pn_rsi.f_opnum_offset.callsequence", + FT_UINT32, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_f_opnum_offset_callsequence), 0xE0000000, + NULL, HFILL } + }, + { &hf_pn_rsi_conn_block, + { "RSI CONN Block", "pn_rsi.conn_block", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_rsp_max_length, + { "RspMaxLength", "pn_rsi.rsp_max_length", + FT_UINT32, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_rsp_max_length), 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_vendor_id, + { "VendorID", "pn_rsi.vendor_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_device_id, + { "DeviceID", "pn_rsi.device_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_instance_id, + { "InstanceID", "pn_rsi.instance_id", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_interface, + { "RsiInterface", "pn_rsi.interface", + FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(pn_rsi_interface), 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_svcs_block, + { "RSI SVCS Block", "pn_rsi.svcs_block", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_number_of_entries, + { "NumberOfEntries", "pn_rsi.number_of_entries", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_pd_rsi_instance, + { "PDRsiInstance", "pn_rsi.pd_rsi_instance", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_device_type, + { "DeviceType", "pn_rsi.device_type", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_order_id, + { "OrderID", "pn_rsi.order_id", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_im_serial_number, + { "IM_Serial_Number", "pn_rsi.im_serial_number", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_hw_revision, + { "HWRevision", "pn_rsi.hw_revision", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_sw_revision_prefix, + { "SWRevisionPrefix", "pn_rsi.sw_revision_prefix", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_sw_revision, + { "SWRevision", "pn_rsi.sw_revision", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + /*&hf_pn_rsi_segment_too_long_segment, + &hf_pn_rsi_segment_error, + &hf_pn_rsi_segment_count, + &hf_pn_rsi_reassembled_in, + &hf_pn_rsi_reassembled_length,*/ + { &hf_pn_rsi_segment, + { "RSI Segment", "pn_rsi.segment", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_segments, + { "PN RSI Segments", "pn_rsi.segments", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_segment_overlap, + { "Segment overlap", "pn_rsi.segment.overlap", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Segment overlaps with other segments", HFILL } + }, + { &hf_pn_rsi_segment_overlap_conflict, + { "Conflicting data in segment overlap", "pn_rsi.segment.overlap.conflict", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Overlapping segments contained conflicting data", HFILL } + }, + { &hf_pn_rsi_segment_multiple_tails, + { "Multiple tail segments found", "pn_rsi.segment.multipletails", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Several tails were found when reassembling the packet", HFILL } + }, + { &hf_pn_rsi_segment_too_long_segment, + { "Segment too long", "pn_rsi.segment.toolongsegment", + FT_BOOLEAN, BASE_NONE, NULL, 0x0, + "Segment contained data past end of packet", HFILL } + }, + { &hf_pn_rsi_segment_error, + { "Reassembly error", "pn_rsi.segment.error", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "Reassembly error due to illegal segments", HFILL } + }, + { &hf_pn_rsi_segment_count, + { "Segment count", "pn_rsi.segment.count", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_rsi_reassembled_in, + { "Reassembled pn_rsi in frame", "pn_rsi.reassembled_in", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "This pn_rsi packet is reassembled in this frame", HFILL } + }, + { &hf_pn_rsi_reassembled_length, + { "Reassembled pn_rsi length", "pn_rsi.reassembled.length", + FT_UINT32, BASE_DEC, NULL, 0x0, + "The total length of the reassembled payload", HFILL } + }, + { &hf_pn_rsi_data_payload, + { "PN IO RSI Data Payload", "pn_rsi.data_payload", + FT_NONE, BASE_NONE, NULL, 0x0, + "", HFILL } + } + }; + + static gint *ett[] = { + &ett_pn_rsi, + &ett_pn_rsi_pdu_type, + &ett_pn_rsi_f_opnum_offset, + &ett_pn_rsi_conn_block, + &ett_pn_rsi_svcs_block, + &ett_pn_rsi_add_flags, + &ett_pn_rsi_rta, + &ett_pn_io_pd_rsi_instance, + &ett_pn_rsi_segments, + &ett_pn_rsi_segment, + &ett_pn_rsi_data_payload + }; + + static ei_register_info ei[] = { + { &ei_pn_rsi_error, { "pn_rsi.error", PI_UNDECODED, PI_NOTE, "Block version not implemented yet!", EXPFILL } } + + }; + + expert_module_t* expert_pn_rsi; + + proto_pn_rsi = proto; + + proto_register_field_array(proto, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_pn_rsi = expert_register_protocol(proto_pn_rsi); + expert_register_field_array(expert_pn_rsi, ei, array_length(ei)); + + register_init_routine(pn_rsi_reassemble_init); +} diff --git a/plugins/epan/profinet/packet-pn-rt.c b/plugins/epan/profinet/packet-pn-rt.c new file mode 100644 index 00000000..581ff013 --- /dev/null +++ b/plugins/epan/profinet/packet-pn-rt.c @@ -0,0 +1,1204 @@ +/* packet-pn-rt.c + * Routines for pn-rt (PROFINET Real-Time) packet dissection. + * This is the base for other PROFINET protocols like IO, CBA, DCP, ... + * (the "content subdissectors" will register themselves using a heuristic) + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "packet-pn.h" + + +void proto_register_pn_rt(void); +void proto_reg_handoff_pn_rt(void); + +#define PROFINET_UDP_PORT 0x8892 + +/* Define the pn-rt proto */ +static int proto_pn_rt = -1; +static gboolean pnio_desegment = TRUE; + +static dissector_handle_t pn_rt_handle; + +/* Define many header fields for pn-rt */ +static int hf_pn_rt_frame_id = -1; +static int hf_pn_rt_cycle_counter = -1; +static int hf_pn_rt_transfer_status = -1; +static int hf_pn_rt_data_status = -1; +static int hf_pn_rt_data_status_ignore = -1; +static int hf_pn_rt_frame_info_type = -1; +static int hf_pn_rt_frame_info_function_meaning_input_conv = -1; +static int hf_pn_rt_frame_info_function_meaning_output_conv = -1; +static int hf_pn_rt_data_status_Reserved_2 = -1; +static int hf_pn_rt_data_status_ok = -1; +static int hf_pn_rt_data_status_operate = -1; +static int hf_pn_rt_data_status_res3 = -1; +static int hf_pn_rt_data_status_valid = -1; +static int hf_pn_rt_data_status_redundancy = -1; +static int hf_pn_rt_data_status_redundancy_output_cr = -1; +static int hf_pn_rt_data_status_redundancy_input_cr_state_is_backup = -1; +static int hf_pn_rt_data_status_redundancy_input_cr_state_is_primary = -1; +static int hf_pn_rt_data_status_primary = -1; + +static int hf_pn_rt_sf_crc16 = -1; +static int hf_pn_rt_sf_crc16_status = -1; +static int hf_pn_rt_sf = -1; +static int hf_pn_rt_sf_position = -1; +/* static int hf_pn_rt_sf_position_control = -1; */ +static int hf_pn_rt_sf_data_length = -1; +static int hf_pn_rt_sf_cycle_counter = -1; + +static int hf_pn_rt_frag = -1; +static int hf_pn_rt_frag_data_length = -1; +static int hf_pn_rt_frag_status = -1; +static int hf_pn_rt_frag_status_more_follows = -1; +static int hf_pn_rt_frag_status_error = -1; +static int hf_pn_rt_frag_status_fragment_number = -1; +static int hf_pn_rt_frag_data = -1; + + +/* + * Define the trees for pn-rt + * We need one tree for pn-rt itself and one for the pn-rt data status subtree + */ +static int ett_pn_rt = -1; +static int ett_pn_rt_data_status = -1; +static int ett_pn_rt_sf = -1; +static int ett_pn_rt_frag = -1; +static int ett_pn_rt_frag_status = -1; + +static expert_field ei_pn_rt_sf_crc16 = EI_INIT; + +/* + * Here are the global variables associated with + * the various user definable characteristics of the dissection + */ +/* Place summary in proto tree */ +static gboolean pn_rt_summary_in_tree = TRUE; + +/* heuristic to find the right pn-rt payload dissector */ +static heur_dissector_list_t heur_subdissector_list; + + +#if 0 +static const value_string pn_rt_position_control[] = { + { 0x00, "CRC16 and CycleCounter shall not be checked" }, + { 0x80, "CRC16 and CycleCounter valid" }, + { 0, NULL } +}; +#endif + +static const true_false_string tfs_pn_rt_ds_redundancy_output_cr = + { "Unknown", "Redundancy has no meaning for OutputCRs, it is set to the fixed value of zero" }; + +static const true_false_string tfs_pn_rt_ds_redundancy_input_cr_state_is_backup = + { "None primary AR of a given AR-set is present", "Default - One primary AR of a given AR-set is present" }; + +static const true_false_string tfs_pn_rt_ds_redundancy_input_cr_state_is_primary = + { "The ARState from the IO device point of view is Backup", "Default - The ARState from the IO device point of view is Primary" }; + +static const value_string pn_rt_frame_info_function_meaning_input_conv[] = { + {0x00, "Backup Acknowledge without actual data" }, + {0x02, "Primary Missing without actual data" }, + {0x04, "Backup Acknowledge with actual data independent from the Arstate" }, + {0x05, "Primary Acknowledge"}, + {0x06, "Primary Missing with actual data independent from the Arstate" }, + {0x07, "Primary Fault" }, + {0, NULL} +}; + +static const value_string pn_rt_frame_info_function_meaning_output_conv[] = { + { 0x04, "Backup Request" }, + { 0x05, "Primary Request" }, + { 0, NULL } +}; + +static const true_false_string tfs_pn_rt_ds_redundancy = + { "None primary AR of a given AR-set is present", "Redundancy has no meaning for OutputCRs / One primary AR of a given AR-set is present" }; + +static const value_string pn_rt_frag_status_error[] = { + { 0x00, "reserved" }, + { 0x01, "reserved: invalid should be zero" }, + { 0, NULL } +}; + +static const value_string pn_rt_frag_status_more_follows[] = { + { 0x00, "Last fragment" }, + { 0x01, "More fragments follow" }, + { 0, NULL } +}; + +/* Copied and renamed from proto.c because global value_strings don't work for plugins */ +static const value_string plugin_proto_checksum_vals[] = { + { PROTO_CHECKSUM_E_BAD, "Bad" }, + { PROTO_CHECKSUM_E_GOOD, "Good" }, + { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" }, + { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" }, + + { 0, NULL } +}; + +static void +dissect_DataStatus(tvbuff_t *tvb, int offset, proto_tree *tree, packet_info *pinfo, guint8 u8DataStatus) +{ + proto_item *sub_item; + proto_tree *sub_tree; + guint8 u8DataValid; + guint8 u8Redundancy; + guint8 u8State; + conversation_t *conversation; + gboolean inputFlag = FALSE; + gboolean outputFlag = FALSE; + apduStatusSwitch *apdu_status_switch; + + u8State = (u8DataStatus & 0x01); + u8Redundancy = (u8DataStatus >> 1) & 0x01; + u8DataValid = (u8DataStatus >> 2) & 0x01; + + /* if PN Connect Request has been read, IOC mac is dl_src and IOD mac is dl_dst */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_UDP, 0, 0, 0); + + if (conversation != NULL) { + apdu_status_switch = (apduStatusSwitch*)conversation_get_proto_data(conversation, proto_pn_io_apdu_status); + if (apdu_status_switch != NULL && apdu_status_switch->isRedundancyActive) { + /* IOC -> IOD: OutputCR */ + if (addresses_equal(&(pinfo->src), conversation_key_addr1(conversation->key_ptr)) && addresses_equal(&(pinfo->dst), conversation_key_addr2(conversation->key_ptr))) { + outputFlag = TRUE; + inputFlag = FALSE; + } + /* IOD -> IOC: InputCR */ + if (addresses_equal(&(pinfo->dst), conversation_key_addr1(conversation->key_ptr)) && addresses_equal(&(pinfo->src), conversation_key_addr2(conversation->key_ptr))) { + inputFlag = TRUE; + outputFlag = FALSE; + } + } + } + + /* input conversation is found */ + if (inputFlag) + { + proto_tree_add_string_format_value(tree, hf_pn_rt_frame_info_type, tvb, + offset, 0, "Input", "Input Frame (IO_Device -> IO_Controller)"); + } + /* output conversation is found. */ + else if (outputFlag) + { + proto_tree_add_string_format_value(tree, hf_pn_rt_frame_info_type, tvb, + offset, 0, "Output", "Output Frame (IO_Controller -> IO_Device)"); + } + + sub_item = proto_tree_add_uint_format(tree, hf_pn_rt_data_status, + tvb, offset, 1, u8DataStatus, + "DataStatus: 0x%02x (Frame: %s and %s, Provider: %s and %s)", + u8DataStatus, + (u8DataStatus & 0x04) ? "Valid" : "Invalid", + (u8DataStatus & 0x01) ? "Primary" : "Backup", + (u8DataStatus & 0x20) ? "Ok" : "Problem", + (u8DataStatus & 0x10) ? "Run" : "Stop"); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_rt_data_status); + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_ignore, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_Reserved_2, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_ok, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_operate, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_res3, tvb, offset, 1, u8DataStatus); + /* input conversation is found */ + if (inputFlag) + { + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_valid, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(tree, hf_pn_rt_frame_info_function_meaning_input_conv, tvb, offset, 1, u8DataStatus); + if (u8State == 0 && u8Redundancy == 0 && u8DataValid == 1) + { + proto_tree_add_boolean(sub_tree, hf_pn_rt_data_status_redundancy_input_cr_state_is_backup, tvb, offset, 1, u8DataStatus); + } + else if (u8State == 0 && u8Redundancy == 0 && u8DataValid == 0) + { + proto_tree_add_boolean(sub_tree, hf_pn_rt_data_status_redundancy_input_cr_state_is_backup, tvb, offset, 1, u8DataStatus); + } + else if (u8State == 0 && u8Redundancy == 1 && u8DataValid == 1) + { + proto_tree_add_boolean(sub_tree, hf_pn_rt_data_status_redundancy_input_cr_state_is_backup, tvb, offset, 1, u8DataStatus); + } + else if (u8State == 0 && u8Redundancy == 1 && u8DataValid == 0) + { + proto_tree_add_boolean(sub_tree, hf_pn_rt_data_status_redundancy_input_cr_state_is_backup, tvb, offset, 1, u8DataStatus); + } + else if (u8State == 1 && u8Redundancy == 0 && u8DataValid == 1) + { + proto_tree_add_boolean(sub_tree, hf_pn_rt_data_status_redundancy_input_cr_state_is_primary, tvb, offset, 1, u8DataStatus); + } + else if (u8State == 1 && u8Redundancy == 1 && u8DataValid == 1) + { + proto_tree_add_boolean(sub_tree, hf_pn_rt_data_status_redundancy_input_cr_state_is_primary, tvb, offset, 1, u8DataStatus); + } + + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_primary, tvb, offset, 1, u8DataStatus); + return; + } + // output conversation is found. + else if (outputFlag) + { + proto_tree_add_uint(tree, hf_pn_rt_frame_info_function_meaning_output_conv, tvb, offset, 1, u8DataStatus); + + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_valid, tvb, offset, 1, u8DataStatus); + proto_tree_add_boolean(sub_tree, hf_pn_rt_data_status_redundancy_output_cr, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_primary, tvb, offset, 1, u8DataStatus); + + return; + } + + // If no conversation is found + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_valid, tvb, offset, 1, u8DataStatus); + proto_tree_add_boolean(sub_tree, hf_pn_rt_data_status_redundancy, tvb, offset, 1, u8DataStatus); + proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_primary, tvb, offset, 1, u8DataStatus); +} + + +static gboolean +IsDFP_Frame(tvbuff_t *tvb, packet_info *pinfo, guint16 u16FrameID) +{ + guint16 u16SFCRC16; + guint8 u8SFPosition; + guint8 u8SFDataLength = 255; + int offset = 0; + guint32 u32SubStart; + guint16 crc; + gint tvb_len = 0; + unsigned char virtualFramebuffer[16]; + + /* try to build a temporaray buffer for generating this CRC */ + if (!pinfo->src.data || !pinfo->dst.data || + pinfo->dst.type != AT_ETHER || pinfo->src.type != AT_ETHER) { + /* if we don't have src/dst mac addresses then we assume it's not + * to avoid various crashes */ + return FALSE; + } + memcpy(&virtualFramebuffer[0], pinfo->dst.data, 6); + memcpy(&virtualFramebuffer[6], pinfo->src.data, 6); + virtualFramebuffer[12] = 0x88; + virtualFramebuffer[13] = 0x92; + virtualFramebuffer[15] = (unsigned char) (u16FrameID &0xff); + virtualFramebuffer[14] = (unsigned char) (u16FrameID>>8); + crc = crc16_plain_init(); + crc = crc16_plain_update(crc, &virtualFramebuffer[0], 16); + crc = crc16_plain_finalize(crc); + /* can check this CRC only by having built a temporary data buffer out of the pinfo data */ + u16SFCRC16 = tvb_get_letohs(tvb, offset); + if (u16SFCRC16 != 0) /* no crc! */ + { + if (u16SFCRC16 != crc) + { + return(FALSE); + } + } + /* end of first CRC check */ + + offset += 2; /*Skip first crc */ + tvb_len = tvb_captured_length(tvb); + if (offset + 4 > tvb_len) + return FALSE; + if (tvb_get_letohs(tvb, offset) == 0) + return FALSE; /* no valid DFP frame */ + while (1) { + u32SubStart = offset; + + u8SFPosition = tvb_get_guint8(tvb, offset); + offset += 1; + + u8SFDataLength = tvb_get_guint8(tvb, offset); + offset += 1; + + if (u8SFDataLength == 0) { + break; + } + + offset += 2; + + offset += u8SFDataLength; + if (offset > tvb_len) + return /*TRUE; */FALSE; + + u16SFCRC16 = tvb_get_letohs(tvb, offset); + if (u16SFCRC16 != 0) { + if (u8SFPosition & 0x80) { + crc = crc16_plain_tvb_offset_seed(tvb, u32SubStart, offset-u32SubStart, 0); + if (crc != u16SFCRC16) { + return FALSE; + } else { + } + } else { + } + } + offset += 2; + } + return TRUE; +} + +/* possibly dissect a CSF_SDU related PN-RT packet */ +gboolean +dissect_CSF_SDU_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + /* the sub tvb will NOT contain the frame_id here! */ + guint16 u16FrameID = GPOINTER_TO_UINT(data); + guint16 u16SFCRC16; + guint8 u8SFPosition; + guint8 u8SFDataLength = 255; + guint8 u8SFCycleCounter; + guint8 u8SFDataStatus; + gint offset = 0; + guint32 u32SubStart; + proto_item *sub_item; + proto_tree *sub_tree; + guint16 crc; + + + /* possible FrameID ranges for DFP */ + if ((u16FrameID < 0x0100) || (u16FrameID > 0x3FFF)) + return (FALSE); + if (IsDFP_Frame(tvb, pinfo, u16FrameID)) { + /* can't check this CRC, as the checked data bytes are not available */ + u16SFCRC16 = tvb_get_letohs(tvb, offset); + if (u16SFCRC16 != 0) { + /* Checksum verify will always succeed */ + /* XXX - should we combine the two calls to always show "unverified"? */ + proto_tree_add_checksum(tree, tvb, offset, hf_pn_rt_sf_crc16, hf_pn_rt_sf_crc16_status, &ei_pn_rt_sf_crc16, pinfo, u16SFCRC16, + ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY); + } + else { + proto_tree_add_checksum(tree, tvb, offset, hf_pn_rt_sf_crc16, hf_pn_rt_sf_crc16_status, &ei_pn_rt_sf_crc16, pinfo, 0, + ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); + } + offset += 2; + + while (1) { + sub_item = proto_tree_add_item(tree, hf_pn_rt_sf, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_rt_sf); + u32SubStart = offset; + + u8SFPosition = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(sub_tree, hf_pn_rt_sf_position, tvb, offset, 1, u8SFPosition); + offset += 1; + + u8SFDataLength = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(sub_tree, hf_pn_rt_sf_data_length, tvb, offset, 1, u8SFDataLength); + offset += 1; + + if (u8SFDataLength == 0) { + proto_item_append_text(sub_item, ": Pos:%u, Length:%u", u8SFPosition, u8SFDataLength); + proto_item_set_len(sub_item, offset - u32SubStart); + break; + } + + u8SFCycleCounter = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(sub_tree, hf_pn_rt_sf_cycle_counter, tvb, offset, 1, u8SFCycleCounter); + offset += 1; + + u8SFDataStatus = tvb_get_guint8(tvb, offset); + dissect_DataStatus(tvb, offset, sub_tree, pinfo, u8SFDataStatus); + offset += 1; + + offset = dissect_pn_user_data(tvb, offset, pinfo, sub_tree, u8SFDataLength, "DataItem"); + + u16SFCRC16 = tvb_get_letohs(tvb, offset); + + if (u16SFCRC16 != 0 /* "old check": u8SFPosition & 0x80 */) { + crc = crc16_plain_tvb_offset_seed(tvb, u32SubStart, offset-u32SubStart, 0); + proto_tree_add_checksum(tree, tvb, offset, hf_pn_rt_sf_crc16, hf_pn_rt_sf_crc16_status, &ei_pn_rt_sf_crc16, pinfo, crc, + ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY); + } else { + proto_tree_add_checksum(tree, tvb, offset, hf_pn_rt_sf_crc16, hf_pn_rt_sf_crc16_status, &ei_pn_rt_sf_crc16, pinfo, 0, + ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); + } + offset += 2; + + proto_item_append_text(sub_item, ": Pos:%u, Length:%u, Cycle:%u, Status: 0x%02x (%s,%s,%s,%s)", + u8SFPosition, u8SFDataLength, u8SFCycleCounter, u8SFDataStatus, + (u8SFDataStatus & 0x04) ? "Valid" : "Invalid", + (u8SFDataStatus & 0x01) ? "Primary" : "Backup", + (u8SFDataStatus & 0x20) ? "Ok" : "Problem", + (u8SFDataStatus & 0x10) ? "Run" : "Stop"); + + proto_item_set_len(sub_item, offset - u32SubStart); + } + + return TRUE; + } + + else { + dissect_pn_user_data(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset), + "PROFINET IO Cyclic Service Data Unit"); + } + + return FALSE; + +} + +/* for reasemble processing we need some inits.. */ +/* Register PNIO defrag table init routine. */ + +static reassembly_table pdu_reassembly_table; +static GHashTable *reasembled_frag_table = NULL; + +static dissector_table_t ethertype_subdissector_table; + +static guint32 start_frag_OR_ID[16]; + + +static void +pnio_defragment_init(void) +{ + guint32 i; + for (i=0; i < 16; i++) /* init the reasemble help array */ + start_frag_OR_ID[i] = 0; + reasembled_frag_table = g_hash_table_new(NULL, NULL); +} + +static void +pnio_defragment_cleanup(void) +{ + g_hash_table_destroy(reasembled_frag_table); +} + +/* possibly dissect a FRAG_PDU related PN-RT packet */ +static gboolean +dissect_FRAG_PDU_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + /* the sub tvb will NOT contain the frame_id here! */ + guint16 u16FrameID = GPOINTER_TO_UINT(data); + int offset = 0; + + + /* possible FrameID ranges for FRAG_PDU */ + if (u16FrameID >= 0xFF80 && u16FrameID <= 0xFF8F) { + proto_item *sub_item; + proto_tree *sub_tree; + proto_item *status_item; + proto_tree *status_tree; + guint8 u8FragDataLength; + guint8 u8FragStatus; + gboolean bMoreFollows; + guint8 uFragNumber; + + sub_item = proto_tree_add_item(tree, hf_pn_rt_frag, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_rt_frag); + + u8FragDataLength = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(sub_tree, hf_pn_rt_frag_data_length, tvb, offset, 1, u8FragDataLength); + offset += 1; + + status_item = proto_tree_add_item(sub_tree, hf_pn_rt_frag_status, tvb, offset, 1, ENC_NA); + status_tree = proto_item_add_subtree(status_item, ett_pn_rt_frag_status); + + u8FragStatus = tvb_get_guint8(tvb, offset); + proto_tree_add_uint(status_tree, hf_pn_rt_frag_status_more_follows, tvb, offset, 1, u8FragStatus); + proto_tree_add_uint(status_tree, hf_pn_rt_frag_status_error, tvb, offset, 1, u8FragStatus); + proto_tree_add_uint(status_tree, hf_pn_rt_frag_status_fragment_number, tvb, offset, 1, u8FragStatus); + offset += 1; + uFragNumber = u8FragStatus & 0x3F; /* bits 0 to 5 */ + bMoreFollows = (u8FragStatus & 0x80) != 0; + proto_item_append_text(status_item, ": Number: %u, %s", + uFragNumber, + val_to_str_const( (u8FragStatus & 0x80) >> 7, pn_rt_frag_status_more_follows, "Unknown")); + + /* Is this a string or a bunch of bytes? Should it be FT_BYTES? */ + proto_tree_add_string_format(sub_tree, hf_pn_rt_frag_data, tvb, offset, tvb_captured_length_remaining(tvb, offset), "data", + "Fragment Length: %d bytes", tvb_captured_length_remaining(tvb, offset)); + col_append_fstr(pinfo->cinfo, COL_INFO, " Fragment Length: %d bytes", tvb_captured_length_remaining(tvb, offset)); + + dissect_pn_user_data_bytes(tvb, offset, pinfo, sub_tree, tvb_captured_length_remaining(tvb, offset), FRAG_DATA); + if ((guint)tvb_captured_length_remaining(tvb, offset) < (guint)(u8FragDataLength *8)) { + proto_item_append_text(status_item, ": FragDataLength out of Framerange -> discarding!"); + return (TRUE); + } + /* defragmentation starts here */ + if (pnio_desegment) + { + guint32 u32FragID; + guint32 u32ReasembleID /*= 0xfedc ??*/; + fragment_head *pdu_frag; + + u32FragID = (u16FrameID & 0xf); + if (uFragNumber == 0) + { /* this is the first "new" fragment, so set up a new key Id */ + guint32 u32FrameKey; + u32FrameKey = (pinfo->num << 2) | u32FragID; + /* store it in the array */ + start_frag_OR_ID[u32FragID] = u32FrameKey; + } + u32ReasembleID = start_frag_OR_ID[u32FragID]; + /* use frame data instead of "pnio fraglen" which sets 8 octet steps */ + pdu_frag = fragment_add_seq(&pdu_reassembly_table, tvb, offset, + pinfo, u32ReasembleID, NULL, uFragNumber, + (tvb_captured_length_remaining(tvb, offset))/*u8FragDataLength*8*/, bMoreFollows, 0); + + if (pdu_frag && !bMoreFollows) /* PDU is complete! and last fragment */ + { /* store this fragment as the completed fragment in hash table */ + g_hash_table_insert(reasembled_frag_table, GUINT_TO_POINTER(pinfo->num), pdu_frag); + start_frag_OR_ID[u32FragID] = 0; /* reset the starting frame counter */ + } + if (!bMoreFollows) /* last fragment */ + { + pdu_frag = (fragment_head *)g_hash_table_lookup(reasembled_frag_table, GUINT_TO_POINTER(pinfo->num)); + if (pdu_frag) /* found a matching fragment; dissect it */ + { + guint16 type; + tvbuff_t *pdu_tvb; + + /* create the new tvb for defragmented frame */ + pdu_tvb = tvb_new_chain(tvb, pdu_frag->tvb_data); + /* add the defragmented data to the data source list */ + add_new_data_source(pinfo, pdu_tvb, "Reassembled Profinet Frame"); + /* PDU is complete: look for the Ethertype and give it to the appropriate dissection routine */ + type = tvb_get_ntohs(pdu_tvb, 0); + pdu_tvb = tvb_new_subset_remaining(pdu_tvb, 2); + if (!dissector_try_uint(ethertype_subdissector_table, type, pdu_tvb, pinfo, tree)) + call_data_dissector(pdu_tvb, pinfo, tree); + } + } + return TRUE; + } + else + return TRUE; + } + return FALSE; +} + + +/* + * dissect_pn_rt - The dissector for the Soft-Real-Time protocol + */ +static int +dissect_pn_rt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + gint pdu_len; + gint data_len; + guint16 u16FrameID; + guint8 u8DataStatus; + guint8 u8TransferStatus; + guint16 u16CycleCounter; + const gchar *pszProtAddInfo; + const gchar *pszProtShort; + const gchar *pszProtSummary; + const gchar *pszProtComment; + proto_tree *pn_rt_tree, *ti; + gchar szFieldSummary[100]; + tvbuff_t *next_tvb; + gboolean bCyclic; + heur_dtbl_entry_t *hdtbl_entry; + conversation_t* conversation; + guint8 isTimeAware = FALSE; + + /* If the link-layer dissector for the protocol above us knows whether + * the packet, as handed to it, includes a link-layer FCS, what it + * hands to us should not include the FCS; if that's not the case, + * that's a bug in that dissector, and should be fixed there. + * + * If the link-layer dissector for the protocol above us doesn't know + * whether the packet, as handed to us, includes a link-layer FCS, + * there are limits as to what can be done there; the dissector + * ultimately needs a "yes, it has an FCS" preference setting, which + * both the Ethernet and 802.11 dissectors do. If that's not the case + * for a dissector, that's a deficiency in that dissector, and should + * be fixed there. + * + * Therefore, we assume we are not handed a packet that includes an + * FCS. If we are ever handed such a packet, either the link-layer + * dissector needs to be fixed or the link-layer dissector's preference + * needs to be set for your capture (even if that means adding such + * a preference). This dissector (and other dissectors for protcols + * running atop the link layer) should not attempt to process the + * FCS themselves, as that will just break things. */ + + /* Initialize variables */ + pn_rt_tree = NULL; + ti = NULL; + + /* + * Set the columns now, so that they'll be set correctly if we throw + * an exception. We can set them (or append things) later again .... + */ + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-RT"); + col_set_str(pinfo->cinfo, COL_INFO, "PROFINET Real-Time"); + + pdu_len = tvb_reported_length(tvb); + if (pdu_len < 6) { + dissect_pn_malformed(tvb, 0, pinfo, tree, pdu_len); + return 0; + } + + /* TimeAwareness Information needed for differentiating RTC3 - RTSteam frames */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + + if (conversation != NULL) { + isTimeAware = GPOINTER_TO_UINT(conversation_get_proto_data(conversation, proto_pn_io_time_aware_status)); + } + + /* build some "raw" data */ + u16FrameID = tvb_get_ntohs(tvb, 0); + if (u16FrameID <= 0x001F) { + pszProtShort = "PN-RT"; + pszProtAddInfo = "reserved, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x0000-0x001F: Reserved ID"; + bCyclic = FALSE; + } else if (u16FrameID <= 0x0021) { + pszProtShort = "PN-PTCP"; + pszProtAddInfo = "Synchronization, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x0020-0x0021: Real-Time: Sync (with follow up)"; + bCyclic = FALSE; + } else if (u16FrameID <= 0x007F) { + pszProtShort = "PN-RT"; + pszProtAddInfo = "reserved, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x0022-0x007F: Reserved ID"; + bCyclic = FALSE; + } else if (u16FrameID <= 0x0081) { + pszProtShort = "PN-PTCP"; + pszProtAddInfo = "Synchronization, "; + pszProtSummary = "Isochronous-Real-Time"; + pszProtComment = "0x0080-0x0081: Real-Time: Sync (without follow up)"; + bCyclic = FALSE; + } else if (u16FrameID <= 0x00FF) { + pszProtShort = "PN-RT"; + pszProtAddInfo = "reserved, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x0082-0x00FF: Reserved ID"; + bCyclic = FALSE; + } else if (u16FrameID <= 0x6FF && !isTimeAware) { + pszProtShort = "PN-RTC3"; + pszProtAddInfo = "RTC3, "; + pszProtSummary = "Isochronous-Real-Time"; + pszProtComment = "0x0100-0x06FF: RED: Real-Time(class=3): non redundant, normal or DFP"; + bCyclic = TRUE; + } else if (u16FrameID <= 0x0FFF && !isTimeAware) { + pszProtShort = "PN-RTC3"; + pszProtAddInfo = "RTC3, "; + pszProtSummary = "Isochronous-Real-Time"; + pszProtComment = "0x0700-0x0FFF: RED: Real-Time(class=3): redundant, normal or DFP"; + bCyclic = TRUE; + } else if (u16FrameID <= 0x7FFF && !isTimeAware) { + pszProtShort = "PN-RT"; + pszProtAddInfo = "reserved, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x1000-0x7FFF: Reserved ID"; + bCyclic = FALSE; + } else if (u16FrameID <= 0x0FFF && isTimeAware) { + pszProtShort = "PN-RT"; + pszProtAddInfo = "reserved, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x0100-0x0FFF: Reserved ID"; + bCyclic = FALSE; + } else if (u16FrameID <= 0x2FFF && isTimeAware) { + pszProtShort = "PN-RTCS"; + pszProtAddInfo = "RT_STREAM, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x1000-0x2FFF: RT_CLASS_STREAM"; + bCyclic = TRUE; + } else if (u16FrameID <= 0x37FF && isTimeAware) { + pszProtShort = "PN-RT"; + pszProtAddInfo = "reserved, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x3000-0x37FF: Reserved ID"; + bCyclic = FALSE; + } else if (u16FrameID <= 0x3FFF && isTimeAware) { + pszProtShort = "PN-RTCS"; + pszProtAddInfo = "RT_STREAM, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0x3800-0x3FFF: RT_CLASS_STREAM"; + bCyclic = TRUE; + } else if (u16FrameID <= 0xBBFF) { + pszProtShort = "PN-RTC1"; + pszProtAddInfo = "RTC1, "; + pszProtSummary = "cyclic Real-Time"; + pszProtComment = "0x8000-0xBBFF: Real-Time(class=1 unicast): non redundant, normal"; + bCyclic = TRUE; + } else if (u16FrameID <= 0xBFFF) { + pszProtShort = "PN-RTC1"; + pszProtAddInfo = "RTC1, "; + pszProtSummary = "cyclic Real-Time"; + pszProtComment = "0xBC00-0xBFFF: Real-Time(class=1 multicast): non redundant, normal"; + bCyclic = TRUE; + } else if (u16FrameID <= 0xF7FF) { + /* check if udp frame on PNIO port */ + if (pinfo->destport == 0x8892) + { /* UDP frame */ + pszProtShort = "PN-RTCUDP,"; + pszProtAddInfo = "RT_CLASS_UDP, "; + pszProtComment = "0xC000-0xF7FF: Real-Time(UDP unicast): Cyclic"; + } + else + { /* layer 2 frame */ + pszProtShort = "PN-RT"; + pszProtAddInfo = "RTC1(legacy), "; + pszProtComment = "0xC000-0xF7FF: Real-Time(class=1 unicast): Cyclic"; + } + pszProtSummary = "cyclic Real-Time"; + bCyclic = TRUE; + } else if (u16FrameID <= 0xFBFF) { + if (pinfo->destport == 0x8892) + { /* UDP frame */ + pszProtShort = "PN-RTCUDP,"; + pszProtAddInfo = "RT_CLASS_UDP, "; + pszProtComment = "0xF800-0xFBFF:: Real-Time(UDP multicast): Cyclic"; + } + else + { /* layer 2 frame */ + pszProtShort = "PN-RT"; + pszProtAddInfo = "RTC1(legacy), "; + pszProtComment = "0xF800-0xFBFF: Real-Time(class=1 multicast): Cyclic"; + } + pszProtSummary = "cyclic Real-Time"; + bCyclic = TRUE; + } else if (u16FrameID <= 0xFDFF) { + pszProtShort = "PN-RTA"; + pszProtAddInfo = "Reserved, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "0xFC00-0xFDFF: Reserved"; + bCyclic = FALSE; + if (u16FrameID == 0xfc01) { + pszProtShort = "PN-RTA"; + pszProtAddInfo = "Alarm High, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "Real-Time: Acyclic PN-IO Alarm high priority"; + } + + } else if (u16FrameID <= 0xFEFF) { + pszProtShort = "PN-RTA"; + pszProtAddInfo = "Reserved, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "0xFE00-0xFEFF: Real-Time: Reserved"; + bCyclic = FALSE; + if (u16FrameID == 0xFE01) { + pszProtShort = "PN-RTA"; + pszProtAddInfo = "Alarm Low, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "Real-Time: Acyclic PN-IO Alarm low priority"; + } + if (u16FrameID == 0xFE02) { + pszProtShort = "PN-RSI"; + pszProtAddInfo = ""; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "Real-Time: Acyclic PN-IO RSI"; + } + if (u16FrameID == FRAME_ID_DCP_HELLO) { + pszProtShort = "PN-RTA"; + pszProtAddInfo = ""; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "Real-Time: DCP (Dynamic Configuration Protocol) hello"; + } + if (u16FrameID == FRAME_ID_DCP_GETORSET) { + pszProtShort = "PN-RTA"; + pszProtAddInfo = ""; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "Real-Time: DCP (Dynamic Configuration Protocol) get/set"; + } + if (u16FrameID == FRAME_ID_DCP_IDENT_REQ) { + pszProtShort = "PN-RTA"; + pszProtAddInfo = ""; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "Real-Time: DCP (Dynamic Configuration Protocol) identify multicast request"; + } + if (u16FrameID == FRAME_ID_DCP_IDENT_RES) { + pszProtShort = "PN-RTA"; + pszProtAddInfo = ""; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "Real-Time: DCP (Dynamic Configuration Protocol) identify response"; + } + } else if (u16FrameID <= 0xFF01) { + pszProtShort = "PN-PTCP"; + pszProtAddInfo = "RTA Sync, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "0xFF00-0xFF01: PTCP Announce"; + bCyclic = FALSE; + } else if (u16FrameID <= 0xFF1F) { + pszProtShort = "PN-PTCP"; + pszProtAddInfo = "RTA Sync, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "0xFF02-0xFF1F: Reserved"; + bCyclic = FALSE; + } else if (u16FrameID <= 0xFF21) { + pszProtShort = "PN-PTCP"; + pszProtAddInfo = "Follow Up, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "0xFF20-0xFF21: PTCP Follow Up"; + bCyclic = FALSE; + } else if (u16FrameID <= 0xFF22) { + pszProtShort = "PN-PTCP"; + pszProtAddInfo = "Follow Up, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "0xFF22-0xFF3F: Reserved"; + bCyclic = FALSE; + } else if (u16FrameID <= 0xFF43) { + pszProtShort = "PN-PTCP"; + pszProtAddInfo = "Delay, "; + pszProtSummary = "acyclic Real-Time"; + pszProtComment = "0xFF40-0xFF43: Acyclic Real-Time: Delay"; + bCyclic = FALSE; + } else if (u16FrameID <= 0xFF7F) { + pszProtShort = "PN-RT"; + pszProtAddInfo = "Reserved, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0xFF44-0xFF7F: reserved ID"; + bCyclic = FALSE; + } else if (u16FrameID <= 0xFF8F) { + pszProtShort = "PN-RT"; + pszProtAddInfo = ""; + pszProtSummary = "Fragmentation"; + pszProtComment = "0xFF80-0xFF8F: Fragmentation"; + bCyclic = FALSE; + } else { + pszProtShort = "PN-RT"; + pszProtAddInfo = "Reserved, "; + pszProtSummary = "Real-Time"; + pszProtComment = "0xFF90-0xFFFF: reserved ID"; + bCyclic = FALSE; + } + + /* decode optional cyclic fields at the packet end and build the summary line */ + if (bCyclic) { + /* cyclic transfer has cycle counter, data status and transfer status fields at the end */ + u16CycleCounter = tvb_get_ntohs(tvb, pdu_len - 4); + u8DataStatus = tvb_get_guint8(tvb, pdu_len - 2); + u8TransferStatus = tvb_get_guint8(tvb, pdu_len - 1); + + snprintf (szFieldSummary, sizeof(szFieldSummary), + "%sID:0x%04x, Len:%4u, Cycle:%5u (%s,%s,%s,%s)", + pszProtAddInfo, u16FrameID, pdu_len - 2 - 4, u16CycleCounter, + (u8DataStatus & 0x04) ? "Valid" : "Invalid", + (u8DataStatus & 0x01) ? "Primary" : "Backup", + (u8DataStatus & 0x20) ? "Ok" : "Problem", + (u8DataStatus & 0x10) ? "Run" : "Stop"); + + /* user data length is packet len - frame id - optional cyclic status fields */ + data_len = pdu_len - 2 - 4; + } else { + /* satisfy the gcc compiler, so it won't throw an "uninitialized" warning */ + u16CycleCounter = 0; + u8DataStatus = 0; + u8TransferStatus = 0; + + /* acyclic transfer has no fields at the end */ + snprintf (szFieldSummary, sizeof(szFieldSummary), + "%sID:0x%04x, Len:%4u", + pszProtAddInfo, u16FrameID, pdu_len - 2); + + /* user data length is packet len - frame id field */ + data_len = pdu_len - 2; + } + + /* build protocol tree only, if tree is really used */ + if (tree) { + /* build pn_rt protocol tree with summary line */ + if (pn_rt_summary_in_tree) { + ti = proto_tree_add_protocol_format(tree, proto_pn_rt, tvb, 0, pdu_len, + "PROFINET %s, %s", pszProtSummary, szFieldSummary); + } else { + ti = proto_tree_add_item(tree, proto_pn_rt, tvb, 0, pdu_len, ENC_NA); + } + pn_rt_tree = proto_item_add_subtree(ti, ett_pn_rt); + + /* add frame ID */ + proto_tree_add_uint_format(pn_rt_tree, hf_pn_rt_frame_id, tvb, + 0, 2, u16FrameID, "FrameID: 0x%04x (%s)", u16FrameID, pszProtComment); + + if (bCyclic) { + /* add cycle counter */ + proto_tree_add_uint_format(pn_rt_tree, hf_pn_rt_cycle_counter, tvb, + pdu_len - 4, 2, u16CycleCounter, "CycleCounter: %u", u16CycleCounter); + + /* add data status subtree */ + dissect_DataStatus(tvb, pdu_len - 2, pn_rt_tree, pinfo, u8DataStatus); + + /* add transfer status */ + if (u8TransferStatus) { + proto_tree_add_uint_format(pn_rt_tree, hf_pn_rt_transfer_status, tvb, + pdu_len - 1, 1, u8TransferStatus, + "TransferStatus: 0x%02x (ignore this frame)", u8TransferStatus); + } else { + proto_tree_add_uint_format(pn_rt_tree, hf_pn_rt_transfer_status, tvb, + pdu_len - 1, 1, u8TransferStatus, + "TransferStatus: 0x%02x (OK)", u8TransferStatus); + } + } + } + + /* update column info now */ + if (u16FrameID == 0xFE02) + { + snprintf(szFieldSummary, sizeof(szFieldSummary), "%s", ""); + } + col_add_str(pinfo->cinfo, COL_INFO, szFieldSummary); + col_set_str(pinfo->cinfo, COL_PROTOCOL, pszProtShort); + + /* get frame user data tvb (without header and footer) */ + next_tvb = tvb_new_subset_length(tvb, 2, data_len); + + /* ask heuristics, if some sub-dissector is interested in this packet payload */ + if (!dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, GUINT_TO_POINTER( (guint32) u16FrameID))) { + /*col_set_str(pinfo->cinfo, COL_INFO, "Unknown");*/ + + /* Oh, well, we don't know this; dissect it as data. */ + dissect_pn_undecoded(next_tvb, 0, pinfo, tree, tvb_captured_length(next_tvb)); + } + return tvb_captured_length(tvb); +} + + +/* Register all the bits needed by the filtering engine */ +void +proto_register_pn_rt(void) +{ + static hf_register_info hf[] = { + { &hf_pn_rt_frame_id, + { "FrameID", "pn_rt.frame_id", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_cycle_counter, + { "CycleCounter", "pn_rt.cycle_counter", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_data_status, + { "DataStatus", "pn_rt.ds", + FT_UINT8, BASE_HEX, 0, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_ignore, + { "Ignore (1:Ignore/0:Evaluate)", "pn_rt.ds_ignore", FT_UINT8, BASE_HEX, 0, 0x80, + NULL, HFILL }}, + + { &hf_pn_rt_frame_info_type, + { "PN Frame Type", "pn_rt.ds_frame_info_type", FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_frame_info_function_meaning_input_conv, + { "Function/Meaning", "pn_rt.ds_frame_info_meaning", + FT_UINT8, BASE_HEX, VALS(pn_rt_frame_info_function_meaning_input_conv), 0x7, + NULL, HFILL } }, + + { &hf_pn_rt_frame_info_function_meaning_output_conv, + { "Function/Meaning", "pn_rt.ds_frame_info_meaning", + FT_UINT8, BASE_HEX, VALS(pn_rt_frame_info_function_meaning_output_conv), 0x7, + NULL, HFILL } }, + + { &hf_pn_rt_data_status_Reserved_2, + { "Reserved_2 (should be zero)", "pn_rt.ds_Reserved_2", + FT_UINT8, BASE_HEX, 0, 0x40, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_ok, + { "StationProblemIndicator (1:Ok/0:Problem)", "pn_rt.ds_ok", + FT_UINT8, BASE_HEX, 0, 0x20, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_operate, + { "ProviderState (1:Run/0:Stop)", "pn_rt.ds_operate", + FT_UINT8, BASE_HEX, 0, 0x10, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_res3, + { "Reserved_3 (should be zero)", "pn_rt.ds_res3", + FT_UINT8, BASE_HEX, 0, 0x08, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_valid, + { "DataValid (1:Valid/0:Invalid)", "pn_rt.ds_valid", + FT_UINT8, BASE_HEX, 0, 0x04, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_redundancy, + { "Redundancy", "pn_rt.ds_redundancy", + FT_BOOLEAN, 8, TFS(&tfs_pn_rt_ds_redundancy), 0x02, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_redundancy_output_cr, + { "Redundancy", "pn_rt.ds_redundancy", + FT_BOOLEAN, 8, TFS(&tfs_pn_rt_ds_redundancy_output_cr), 0x02, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_redundancy_input_cr_state_is_backup, + { "Redundancy", "pn_rt.ds_redundancy", + FT_BOOLEAN, 8, TFS(&tfs_pn_rt_ds_redundancy_input_cr_state_is_backup), 0x02, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_redundancy_input_cr_state_is_primary, + { "Redundancy", "pn_rt.ds_redundancy", + FT_BOOLEAN, 8, TFS(&tfs_pn_rt_ds_redundancy_input_cr_state_is_primary), 0x02, + NULL, HFILL }}, + + { &hf_pn_rt_data_status_primary, + { "State (1:Primary/0:Backup)", "pn_rt.ds_primary", + FT_UINT8, BASE_HEX, 0, 0x01, + NULL, HFILL }}, + + { &hf_pn_rt_transfer_status, + { "TransferStatus", "pn_rt.transfer_status", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_sf, + { "SubFrame", "pn_rt.sf", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_sf_crc16, + { "SFCRC16", "pn_rt.sf.crc16", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_sf_crc16_status, + { "SFCRC16 status", "pn_rt.sf.crc16.status", + FT_UINT8, BASE_NONE, VALS(plugin_proto_checksum_vals), 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_sf_position, + { "Position", "pn_rt.sf.position", + FT_UINT8, BASE_DEC, NULL, 0x7F, + NULL, HFILL }}, + +#if 0 + { &hf_pn_rt_sf_position_control, + { "Control", "pn_rt.sf.position_control", + FT_UINT8, BASE_DEC, VALS(pn_rt_position_control), 0x80, + NULL, HFILL }}, +#endif + + { &hf_pn_rt_sf_data_length, + { "DataLength", "pn_rt.sf.data_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_sf_cycle_counter, + { "CycleCounter", "pn_rt.sf.cycle_counter", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_frag, + { "PROFINET Fragment", "pn_rt.frag", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_frag_data_length, + { "FragDataLength", "pn_rt.frag_data_length", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_frag_status, + { "FragStatus", "pn_rt.frag_status", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + { &hf_pn_rt_frag_status_more_follows, + { "MoreFollows", "pn_rt.frag_status.more_follows", + FT_UINT8, BASE_HEX, VALS(pn_rt_frag_status_more_follows), 0x80, + NULL, HFILL }}, + + { &hf_pn_rt_frag_status_error, + { "Reserved", "pn_rt.frag_status.error", + FT_UINT8, BASE_HEX, VALS(pn_rt_frag_status_error), 0x40, + NULL, HFILL }}, + + { &hf_pn_rt_frag_status_fragment_number, + { "FragmentNumber (zero based)", "pn_rt.frag_status.fragment_number", + FT_UINT8, BASE_DEC, NULL, 0x3F, + NULL, HFILL }}, + + /* Is this a string or a bunch of bytes? Should it be FT_BYTES? */ + { &hf_pn_rt_frag_data, + { "FragData", "pn_rt.frag_data", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + }; + static gint *ett[] = { + &ett_pn_rt, + &ett_pn_rt_data_status, + &ett_pn_rt_sf, + &ett_pn_rt_frag, + &ett_pn_rt_frag_status + }; + + static ei_register_info ei[] = { + { &ei_pn_rt_sf_crc16, { "pn_rt.sf.crc16_bad", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, + }; + + module_t *pn_rt_module; + expert_module_t* expert_pn_rt; + + proto_pn_rt = proto_register_protocol("PROFINET Real-Time Protocol", + "PN-RT", "pn_rt"); + pn_rt_handle = register_dissector("pn_rt", dissect_pn_rt, proto_pn_rt); + + proto_register_field_array(proto_pn_rt, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_pn_rt = expert_register_protocol(proto_pn_rt); + expert_register_field_array(expert_pn_rt, ei, array_length(ei)); + + /* Register our configuration options */ + + pn_rt_module = prefs_register_protocol(proto_pn_rt, NULL); + + prefs_register_bool_preference(pn_rt_module, "summary_in_tree", + "Show PN-RT summary in protocol tree", + "Whether the PN-RT summary line should be shown in the protocol tree", + &pn_rt_summary_in_tree); + + prefs_register_bool_preference(pn_rt_module, "desegment", + "reassemble PNIO Fragments", + "Reassemble PNIO Fragments and get them decoded", + &pnio_desegment); + + /* register heuristics anchor for payload dissectors */ + heur_subdissector_list = register_heur_dissector_list("pn_rt", proto_pn_rt); + + init_pn (proto_pn_rt); + register_init_routine(pnio_defragment_init); + register_cleanup_routine(pnio_defragment_cleanup); + reassembly_table_register(&pdu_reassembly_table, + &addresses_reassembly_table_functions); +} + + +/* The registration hand-off routine is called at startup */ +void +proto_reg_handoff_pn_rt(void) +{ + dissector_add_uint("ethertype", ETHERTYPE_PROFINET, pn_rt_handle); + dissector_add_uint_with_preference("udp.port", PROFINET_UDP_PORT, pn_rt_handle); + + heur_dissector_add("pn_rt", dissect_CSF_SDU_heur, "PROFINET CSF_SDU IO", "pn_csf_sdu_pn_rt", proto_pn_rt, HEURISTIC_ENABLE); + heur_dissector_add("pn_rt", dissect_FRAG_PDU_heur, "PROFINET Frag PDU IO", "pn_frag_pn_rt", proto_pn_rt, HEURISTIC_ENABLE); + + ethertype_subdissector_table = find_dissector_table("ethertype"); +} + + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-pn-rtc-one.c b/plugins/epan/profinet/packet-pn-rtc-one.c new file mode 100644 index 00000000..383909a2 --- /dev/null +++ b/plugins/epan/profinet/packet-pn-rtc-one.c @@ -0,0 +1,1356 @@ +/* packet-pn-rtc-one.c + * Routines for PROFINET IO - RTC1 dissection. + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * The PN-IO protocol is a field bus protocol related to decentralized + * periphery and is developed by the PROFIBUS Nutzerorganisation e.V. (PNO), + * see: www.profibus.com + * + * + * PN-IO is based on the common DCE-RPC and the "lightweight" PN-RT + * (ethernet type 0x8892) protocols. + * + * The context manager (CM) part is handling context information + * (like establishing, ...) and is using DCE-RPC as its underlying + * protocol. + * + * The actual cyclic data transfer and acyclic notification uses the + * "lightweight" PN-RT protocol. + * + * There are some other related PROFINET protocols (e.g. PN-DCP, which is + * handling addressing topics). + * + * Please note: the PROFINET CBA protocol is independent of the PN-IO protocol! + */ + +/* + * Cyclic PNIO RTC1 Data Dissection: + * + * To dissect cyclic PNIO RTC1 frames, this plug-in has to collect important module + * information out of "Ident OK", "Connect Request" and "Write Response" + * frames first. + * + * The data of Stationname-, -type and -id will be gained out of + * packet-pn-dcp.c. The header packet-pn.h will transfer those data between + * those two files. + * + * This file is used as a "addon" for packet-dcerpc-pn-io.c. Within "packet-dcerpc-pn-io.c" + * the defined structures in "packet-pn.h" will be filled with all necessary information. + * Those informations will be used in thise file to dissect cyclic PNIO RTC1 and PROFIsafe + * frames. Furthermore since RTC1 is a special frame type of PNIO, this dissection uses the + * already defined protocol PNIO. + * + * Overview for cyclic PNIO RTC1 data dissection functions: + * -> dissect_PNIO_C_SDU_RTC1 (general dissection of RTC1) + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "packet-pn.h" + + +#define F_MESSAGE_TRAILER_4BYTE 4 /* PROFIsafe: Defines the Amount of Bytes for CRC and Status-/Controlbyte in PROFIsafe 2.4 */ +#define F_MESSAGE_TRAILER_5BYTE 5 /* PROFIsafe: Defines the Amount of Bytes for CRC and Status-/Controlbyte in PROFIsafe 2.6 */ +#define PN_INPUT_CR 1 /* PROFINET Input Connect Request value */ +#define PN_INPUT_DATADESCRITPION 1 /* PROFINET Input Data Description value */ + +#define PA_PROFILE_API 0x9700u + +static int proto_pn_io_rtc1 = -1; + +/* General module information */ +static int hf_pn_io_frame_info_type = -1; +static int hf_pn_io_frame_info_vendor = -1; +static int hf_pn_io_frame_info_nameofstation = -1; +static int hf_pn_io_frame_info_gsd_found = -1; +static int hf_pn_io_frame_info_gsd_error = -1; +static int hf_pn_io_frame_info_gsd_path = -1; +static int hf_pn_io_io_data_object = -1; +static int hf_pn_io_io_data_object_info_module_diff = -1; +static int hf_pn_io_io_data_object_info_moduleidentnumber = -1; +static int hf_pn_io_io_data_object_info_submoduleidentnumber = -1; + +static int hf_pn_io_iocs = -1; +static int hf_pn_io_iops = -1; +static int hf_pn_io_ioxs_extension = -1; +static int hf_pn_io_ioxs_res14 = -1; +static int hf_pn_io_ioxs_instance = -1; +static int hf_pn_io_ioxs_datastate = -1; + +/* PROFIsafe statusbyte and controlbyte */ +static int hf_pn_io_ps_sb = -1; +static int hf_pn_io_ps_sb_iparOK = -1; +static int hf_pn_io_ps_sb_DeviceFault = -1; +static int hf_pn_io_ps_sb_CECRC = -1; +static int hf_pn_io_ps_sb_WDtimeout = -1; +static int hf_pn_io_ps_sb_FVactivated = -1; +static int hf_pn_io_ps_sb_Toggle_d = -1; +static int hf_pn_io_ps_sb_ConsNr_reset = -1; +static int hf_pn_io_ps_sb_res = -1; +static int hf_pn_io_ps_sb_toggelBitChanged = -1; +static int hf_pn_io_ps_sb_toggelBitChange_slot_nr = -1; +static int hf_pn_io_ps_sb_toggelBitChange_subslot_nr = -1; + +static int hf_pn_io_ps_cb = -1; +static int hf_pn_io_ps_cb_iparEN = -1; +static int hf_pn_io_ps_cb_OAReq = -1; +static int hf_pn_io_ps_cb_resetConsNr = -1; +static int hf_pn_io_ps_cb_useTO2 = -1; +static int hf_pn_io_ps_cb_activateFV = -1; +static int hf_pn_io_ps_cb_Toggle_h = -1; +static int hf_pn_io_ps_cb_Chf_ACK = -1; +static int hf_pn_io_ps_cb_loopcheck = -1; +static int hf_pn_io_ps_cb_toggelBitChanged = -1; +static int hf_pn_io_ps_cb_toggelBitChange_slot_nr = -1; +static int hf_pn_io_ps_cb_toggelBitChange_subslot_nr = -1; + +/* PROFIsafe */ +static int hf_pn_io_ps_f_dest_adr = -1; +static int hf_pn_io_ps_f_data = -1; + +/* PA Profile 4.02 */ +static int hf_pn_pa_profile_status = -1; +static int hf_pn_pa_profile_status_quality = -1; +static int hf_pn_pa_profile_status_substatus_bad = -1; +static int hf_pn_pa_profile_status_substatus_uncertain = -1; +static int hf_pn_pa_profile_status_substatus_good = -1; +static int hf_pn_pa_profile_status_update_event = -1; +static int hf_pn_pa_profile_status_simulate = -1; +static int hf_pn_pa_profile_value_8bit = -1; +static int hf_pn_pa_profile_value_16bit = -1; +static int hf_pn_pa_profile_value_float = -1; + +static gint ett_pn_io_rtc = -1; +static gint ett_pn_io_ioxs = -1; +static gint ett_pn_io_io_data_object = -1; +static gint ett_pn_pa_profile_status = -1; + +static expert_field ei_pn_io_too_many_data_objects = EI_INIT; + +static const value_string pn_io_ioxs_extension[] = { + { 0x00 /* 0*/, "No IOxS octet follows" }, + { 0x01 /* 1*/, "One more IOxS octet follows" }, + { 0, NULL } +}; + +static const value_string pn_io_ioxs_instance[] = { + { 0x00 /* 0*/, "Detected by subslot" }, + { 0x01 /* 1*/, "Detected by slot" }, + { 0x02 /* 2*/, "Detected by IO device" }, + { 0x03 /* 3*/, "Detected by IO controller" }, + { 0, NULL } +}; + +static const value_string pn_io_ioxs_datastate[] = { + { 0x00 /* 0*/, "Bad" }, + { 0x01 /* 1*/, "Good" }, + { 0, NULL } +}; + +static const value_string pn_pa_profile_status_quality[] = { + { 0x00 /* 0*/, "BAD" }, + { 0x01 /* 1*/, "UNCERTAIN" }, + { 0x02 /* 2*/, "GOOD" }, + { 0, NULL } +}; + +static const value_string pn_pa_profile_status_substatus_bad[] = { + { 0x0, "Non specific" }, + { 0x2, "Not connected" }, + { 0x8, "Passivated" }, + { 0x9, "Maintenance alarm, more diagnosis" }, + { 0xA, "Process related, no maintenance" }, + { 0xF, "Function check, value not usable" }, + { 0, NULL } +}; + +static const value_string pn_pa_profile_status_substatus_uncertain[] = { + { 0x2, "Substitute set" }, + { 0x3, "Initial value" }, + { 0xA, "Maintenance demanded" }, + { 0xE, "Process related, no maintenance" }, + { 0, NULL } +}; + +static const value_string pn_pa_profile_status_substatus_good[] = { + { 0x0, "Good" }, + { 0x7, "Local override" }, + { 0x8, "Initial fail safe" }, + { 0x9, "Maintenance required" }, + { 0xA, "Maintenance demanded" }, + { 0xF, "Function check" }, + { 0, NULL } +}; + +static const value_string pn_pa_profile_status_update_event[] = { + { 0x0, "No event" }, + { 0x1, "Update event" }, + { 0, NULL } +}; + +static const value_string pn_pa_profile_status_simulate[] = { + { 0x0, "Simulation off" }, + { 0x1, "Simulation active" }, + { 0, NULL } +}; + + +static int * const ps_sb_fields[] = { + &hf_pn_io_ps_sb_res, + &hf_pn_io_ps_sb_ConsNr_reset, + &hf_pn_io_ps_sb_Toggle_d, + &hf_pn_io_ps_sb_FVactivated, + &hf_pn_io_ps_sb_WDtimeout, + &hf_pn_io_ps_sb_CECRC, + &hf_pn_io_ps_sb_DeviceFault, + &hf_pn_io_ps_sb_iparOK, + NULL +}; + +static int * const ps_cb_fields[] = { + &hf_pn_io_ps_cb_loopcheck, + &hf_pn_io_ps_cb_Chf_ACK, + &hf_pn_io_ps_cb_Toggle_h, + &hf_pn_io_ps_cb_activateFV, + &hf_pn_io_ps_cb_useTO2, + &hf_pn_io_ps_cb_resetConsNr, + &hf_pn_io_ps_cb_OAReq, + &hf_pn_io_ps_cb_iparEN, + NULL +}; + +static int * const ioxs_fields[] = { + &hf_pn_io_ioxs_datastate, + &hf_pn_io_ioxs_instance, + &hf_pn_io_ioxs_res14, + &hf_pn_io_ioxs_extension, + NULL +}; + +/* +static int * const pa_profile_status_fields[] = { + &hf_pn_pa_profile_status_quality, + &hf_pn_pa_profile_status_substatus_bad, + &hf_pn_pa_profile_status_substatus_uncertain, + &hf_pn_pa_profile_status_substatus_good, + &hf_pn_pa_profile_status_update_event, + &hf_pn_pa_profile_status_simulate, + NULL +}; +*/ + +/* Dissector for PROFIsafe Status Byte */ +static int +dissect_pn_io_ps_SB(tvbuff_t *tvb, int offset, +packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int hfindex, int * const *fields) +{ + + if (tree) { + guint8 u8StatusByte; + proto_item *sb_item; + + u8StatusByte = tvb_get_guint8(tvb, offset); + + /* Add Status Byte subtree */ + sb_item = proto_tree_add_bitmask_with_flags(tree, tvb, offset, hfindex, ett_pn_io_ioxs, fields, + ENC_LITTLE_ENDIAN, BMT_NO_APPEND); + proto_item_append_text(sb_item, " (%s)", ((u8StatusByte == 0x20) || (u8StatusByte == 0x00)) ? "normal" : "unnormal"); + } + + return offset + 1; +} + + +/* Dissector for PROFIsafe Control Byte */ +static int +dissect_pn_io_ps_CB(tvbuff_t *tvb, int offset, +packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int hfindex, int * const *fields) +{ + + if (tree) { + guint8 u8ControlByte; + proto_item *cb_item; + + u8ControlByte = tvb_get_guint8(tvb, offset); + + /* Add Status Byte subtree */ + cb_item = proto_tree_add_bitmask_with_flags(tree, tvb, offset, hfindex, ett_pn_io_ioxs, fields, + ENC_LITTLE_ENDIAN, BMT_NO_APPEND); + proto_item_append_text(cb_item, " (%s)", ((u8ControlByte == 0x20) || (u8ControlByte == 0x00) || + (u8ControlByte == 0xa0) || (u8ControlByte == 0x80)) ? "normal" : "unnormal"); + } + + return offset + 1; +} + + +/* Dissector for IOCS (As each IOCS stands for a specific Slot & Subslot) */ +static int +dissect_PNIO_IOCS(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree, + guint8 *drep _U_, int hfindex, guint16 slotNr, guint16 subSlotNr, int * const *fields) +{ + + if (tree) { + guint8 u8IOxS; + proto_item *ioxs_item; + + u8IOxS = tvb_get_guint8(tvb, offset); + + /* Add ioxs subtree */ + ioxs_item = proto_tree_add_bitmask_with_flags(tree, tvb, offset, hfindex, + ett_pn_io_ioxs, fields, ENC_LITTLE_ENDIAN, BMT_NO_APPEND); + proto_item_append_text(ioxs_item, + " (%s%s), Slot: 0x%x, Subslot: 0x%x", + (u8IOxS & 0x01) ? "another IOxS follows " : "", + (u8IOxS & 0x80) ? "good" : "bad", + slotNr, + subSlotNr); + } + + return offset + 1; +} + + +/* dissect the IOxS (IOCS, IOPS) field */ +static int +dissect_PNIO_IOxS(tvbuff_t *tvb, int offset, +packet_info *pinfo _U_, proto_tree *tree, guint8 *drep _U_, int hfindex, int * const *fields) +{ + + if (tree) { + guint8 u8IOxS; + proto_item *ioxs_item; + + u8IOxS = tvb_get_guint8(tvb, offset); + + /* Add ioxs subtree */ + ioxs_item = proto_tree_add_bitmask_with_flags(tree, tvb, offset, hfindex, + ett_pn_io_ioxs, fields, ENC_LITTLE_ENDIAN, BMT_NO_APPEND); + proto_item_append_text(ioxs_item, + " (%s%s)", + (u8IOxS & 0x01) ? "another IOxS follows " : "", + (u8IOxS & 0x80) ? "good" : "bad"); + } + + return offset + 1; +} + + +/* Universel dissector for flexibel PROFIsafe Data 8 to 64 Bits */ +static int +dissect_pn_io_ps_uint(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, + proto_tree *tree, guint8 *drep, +int hfindex, guint8 bytelength, guint64 *pdata) +{ + guint64 data; + gboolean generalDissection; + + generalDissection = FALSE; + + switch (bytelength) { + case 1: /* 8 Bit Safety IO Data */ + data = tvb_get_guint8(tvb, offset); + if (pdata) + *pdata = data; + break; + + case 2: /* 16 Bit Safety IO Data */ + data = tvb_get_letohs(tvb, offset); + if (pdata) + *pdata = data; + break; + + case 3: /* 24 Bit Safety IO Data */ + data = tvb_get_letoh24(tvb, offset); + if (pdata) + *pdata = data; + break; + + case 4: /* 32 Bit Safety IO Data */ + data = tvb_get_letohl(tvb, offset); + if (pdata) + *pdata = data; + break; + + case 5: /* 40 Bit Safety IO Data */ + data = tvb_get_letoh40(tvb, offset); + if (pdata) + *pdata = data; + break; + + case 6: /* 48 Bit Safety IO Data */ + data = tvb_get_letoh48(tvb, offset); + if (pdata) + *pdata = data; + break; + + case 7: /* 56 Bit Safety IO Data */ + data = tvb_get_letoh56(tvb, offset); + if (pdata) + *pdata = data; + break; + + case 8: /* 64 Bit Safety IO Data */ + data = tvb_get_letoh64(tvb, offset); + if (pdata) + *pdata = data; + break; + + default: /* Safety IO Data is too big to save it into one variable */ + dissect_pn_user_data(tvb, offset, pinfo, tree, bytelength, "Safety IO Data"); + generalDissection = TRUE; + break; + } + + if (tree && generalDissection == FALSE) { + proto_tree_add_item(tree, hfindex, tvb, offset, bytelength, DREP_ENC_INTEGER(drep)); + } + + return offset + bytelength; +} + + +/* dissect a PN-IO RTC1 Cyclic Service Data Unit */ +int +dissect_PNIO_C_SDU_RTC1(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep _U_, guint16 frameid) +{ + proto_tree *data_tree = NULL; + + /* Count & offset for comparation of the arrays */ + guint16 frameOffset; + guint32 objectCounter; + gboolean inputFlag; + gboolean outputFlag; + gboolean psInfoText; /* Used to display only once per frame the info text "PROFIsafe Device" */ + + proto_item *data_item; + proto_item *IODataObject_item; + proto_item *IODataObject_item_info; + proto_tree *IODataObject_tree; + proto_item *ModuleID_item; + proto_item *ModuleDiff_item; + + wmem_strbuf_t *moduleName; + + guint8 toggleBitSb; + guint8 toggleBitCb; + guint64 f_data; + + guint8 statusbyte; + guint8 controlbyte; + guint8 safety_io_data_length; + + guint16 number_io_data_objects_input_cr; + guint16 number_iocs_input_cr; + guint16 number_io_data_objects_output_cr; + guint16 number_iocs_output_cr; + + conversation_t *conversation; + stationInfo *station_info = NULL; + iocsObject *iocs_object; + ioDataObject *io_data_object; + moduleDiffInfo *module_diff_info; + wmem_list_frame_t *frame; + wmem_list_frame_t *frame_diff; + + /* Initial */ + frameOffset = 0; + f_data = 0; + inputFlag = FALSE; + outputFlag = FALSE; + psInfoText = FALSE; + number_io_data_objects_input_cr = 0; + number_iocs_input_cr = 0; + number_io_data_objects_output_cr = 0; + number_iocs_output_cr = 0; + + wmem_list_frame_t *aruuid_frame; + ARUUIDFrame *current_aruuid_frame = NULL; + guint32 current_aruuid = 0; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO"); /* set protocol name */ + + data_item = proto_tree_add_protocol_format(tree, proto_pn_io_rtc1, tvb, offset, tvb_captured_length(tvb), + "PROFINET IO Cyclic Service Data Unit: %u bytes", tvb_captured_length(tvb)); + data_tree = proto_item_add_subtree(data_item, ett_pn_io_rtc); + + /* dissect_dcerpc_uint16(tvb, offset, pinfo, data_tree, drep, hf_pn_io_packedframe_SFCRC, &u16SFCRC); */ + if (!(dissect_CSF_SDU_heur(tvb, pinfo, data_tree, NULL) == FALSE)) + return(tvb_captured_length(tvb)); + + /* Only dissect cyclic RTC1 frames, if PN Connect Request has been read */ + conversation = find_conversation(pinfo->num, &pinfo->dl_src, &pinfo->dl_dst, CONVERSATION_NONE, 0, 0, 0); + + /* Detect input data package and output data package */ + if (conversation != NULL) { + if (aruuid_frame_setup_list != NULL) { + for (aruuid_frame = wmem_list_tail(aruuid_frame_setup_list); aruuid_frame != NULL; aruuid_frame = wmem_list_frame_prev(aruuid_frame)) { + current_aruuid_frame = (ARUUIDFrame*)wmem_list_frame_data(aruuid_frame); + /* There are prerequisites to dissect RTC frame data */ + /* Current station info must be found before RTC frame dissection starts */ + /* if RTC frame has setup frame and setup frame number is less than RTC frame number AND if RTC frame has release frame and release frame number is greater than RTC frame number */ + /* if RTC frame has setup frame and setup frame number is less than RTC frame number AND RTC frame does not have release frame yet! */ + /* then, get AR UUID of current station info */ + if ((current_aruuid_frame->setupframe && current_aruuid_frame->setupframe < pinfo->num) && + ((current_aruuid_frame->releaseframe && current_aruuid_frame->releaseframe > pinfo->num) || + !current_aruuid_frame->releaseframe)) { + if (current_aruuid_frame->inputframe == frameid) { + current_aruuid = current_aruuid_frame->aruuid.data1; + break; + } + else if (current_aruuid_frame->outputframe == frameid) { + current_aruuid = current_aruuid_frame->aruuid.data1; + break; + } + } + } + } + + station_info = (stationInfo*)conversation_get_proto_data(conversation, current_aruuid); + + if (station_info != NULL) { + pn_find_dcp_station_info(station_info, conversation); + + if (pnio_ps_selection == TRUE) { + col_set_str(pinfo->cinfo, COL_PROTOCOL, "PNIO_PS"); /* set PROFISsafe protocol name */ + } + + if (addresses_equal(&(pinfo->src), conversation_key_addr1(conversation->key_ptr)) && addresses_equal(&(pinfo->dst), conversation_key_addr2(conversation->key_ptr))) { + inputFlag = TRUE; + outputFlag = FALSE; + number_io_data_objects_input_cr = station_info->ioDataObjectNr_in; + number_iocs_input_cr = station_info->iocsNr_in; + } + + if (addresses_equal(&(pinfo->dst), conversation_key_addr1(conversation->key_ptr)) && addresses_equal(&(pinfo->src), conversation_key_addr2(conversation->key_ptr))) { + outputFlag = TRUE; + inputFlag = FALSE; + number_io_data_objects_output_cr = station_info->ioDataObjectNr_out; + number_iocs_output_cr = station_info->iocsNr_out; + } + } + } + + /* ------- Input (PNIO) / Response (PNIO_PS) Frame Handling ------- */ + if (inputFlag) { + if (pnio_ps_selection == TRUE) { + proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_type, tvb, + offset, 0, "Response", "Response Frame (IO_Device -> IO_Controller)"); + } + else { + proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_type, tvb, + offset, 0, "Input", "Input Frame (IO_Device -> IO_Controller)"); + } + + if (station_info != NULL) { + if (station_info->typeofstation != NULL) { + proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_vendor, tvb, 0, + 0, station_info->typeofstation, "\"%s\"", station_info->typeofstation); + } + if (station_info->nameofstation != NULL) { + proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_nameofstation, tvb, 0, + 0, station_info->nameofstation, "\"%s\"", station_info->nameofstation); + } + + if (station_info->gsdPathLength == TRUE) { /* given path isn't too long for the array */ + if (station_info->gsdFound == TRUE) { /* found a GSD-file */ + if (station_info->gsdLocation != NULL) { + IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_found, tvb, offset, 0, ENC_NA); + proto_item_append_text(IODataObject_item_info, ": \"%s\"", station_info->gsdLocation); + } + } + else { + if (station_info->gsdLocation != NULL) { + IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_error, tvb, offset, 0, ENC_NA); + proto_item_append_text(IODataObject_item_info, " Please place relevant GSD-file under \"%s\"", station_info->gsdLocation); + } + } + } + else { + IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_path, tvb, offset, 0, ENC_NA); + proto_item_append_text(IODataObject_item_info, " Please check your GSD-file networkpath. (No Path configured)"); + } + } + + /* ---- Input IOData-/IOCS-Object Handling ---- */ + objectCounter = number_io_data_objects_input_cr + number_iocs_input_cr; + if (objectCounter > (guint)tvb_reported_length_remaining(tvb, offset)) { + expert_add_info_format(pinfo, data_item, &ei_pn_io_too_many_data_objects, "Too many data objects: %d", objectCounter); + return(tvb_captured_length(tvb)); + } + + while (objectCounter--) { + /* ---- Input IO Data Object Handling ---- */ + if (station_info != NULL) { + for (frame = wmem_list_head(station_info->ioobject_data_in); frame != NULL; frame = wmem_list_frame_next(frame)) { + io_data_object = (ioDataObject*)wmem_list_frame_data(frame); + if (io_data_object->frameOffset == frameOffset) { + /* Found following object */ + + IODataObject_item = proto_tree_add_item(data_tree, hf_pn_io_io_data_object, tvb, offset, 0, ENC_NA); + IODataObject_tree = proto_item_add_subtree(IODataObject_item, ett_pn_io_io_data_object); + + /* Control: the Device still uses the correct ModuleIdentNumber? */ + for (frame_diff = wmem_list_head(station_info->diff_module); frame_diff != NULL; frame_diff = wmem_list_frame_next(frame_diff)) { + module_diff_info = (moduleDiffInfo*)wmem_list_frame_data(frame_diff); + if (io_data_object->moduleIdentNr != module_diff_info->modulID) { + ModuleDiff_item = proto_tree_add_item(IODataObject_tree, hf_pn_io_io_data_object_info_module_diff, tvb, 0, 0, ENC_NA); + proto_item_append_text(ModuleDiff_item, ": Device using ModuleIdentNumber 0x%08x instead of 0x%08x", module_diff_info->modulID, io_data_object->moduleIdentNr); + break; + } + } + + proto_tree_add_uint(IODataObject_tree, hf_pn_io_io_data_object_info_moduleidentnumber, tvb, 0, 0, io_data_object->moduleIdentNr); + proto_tree_add_uint(IODataObject_tree, hf_pn_io_io_data_object_info_submoduleidentnumber, tvb, 0, 0, io_data_object->subModuleIdentNr); + + /* PROFIsafe Supported Inputmodule handling */ + if (io_data_object->profisafeSupported == TRUE && pnio_ps_selection == TRUE) { + if (io_data_object->profisafeSupported == TRUE && psInfoText == FALSE) { + /* Only add one information string per device to the infotext */ + col_append_str(pinfo->cinfo, COL_INFO, ", PROFIsafe Device"); /* Add string to wireshark infotext */ + psInfoText = TRUE; + } + + proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_f_dest_adr, tvb, 0, 0, io_data_object->f_dest_adr); + + /* Get Safety IO Data */ + if (io_data_object->f_crc_seed == FALSE) { + safety_io_data_length = io_data_object->length - F_MESSAGE_TRAILER_4BYTE; + } else { + safety_io_data_length = io_data_object->length - F_MESSAGE_TRAILER_5BYTE; + } + + if (safety_io_data_length > 0) { + offset = dissect_pn_io_ps_uint(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_ps_f_data, + safety_io_data_length, &f_data); + } + + /* ---- Check for new PNIO data using togglebit ---- */ + statusbyte = tvb_get_guint8(tvb, offset); + toggleBitSb = statusbyte & 0x20; /* get ToggleBit of StatusByte */ + + if (io_data_object->lastToggleBit != toggleBitSb) { /* ToggleBit has changed --> new Data incoming */ + /* Special Filter for ToggleBit within Statusbyte */ + ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_sb_toggelBitChanged, tvb, offset, 0, toggleBitSb); + proto_item_set_hidden(ModuleID_item); + + ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_sb_toggelBitChange_slot_nr, tvb, offset, 0, io_data_object->slotNr); + proto_item_set_hidden(ModuleID_item); + + ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_sb_toggelBitChange_subslot_nr, tvb, offset, 0, io_data_object->subSlotNr); + proto_item_set_hidden(ModuleID_item); + } + + offset = dissect_pn_io_ps_SB(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_ps_sb, ps_sb_fields); + offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->f_crc_len, "CRC"); + + io_data_object->last_sb_cb = statusbyte; /* save the value of current statusbyte */ + io_data_object->lastToggleBit = toggleBitSb; /* save the value of current togglebit within statusbyte */ + } /* END of PROFIsafe Module Handling */ + + else { + /* Module is not PROFIsafe supported */ + if (io_data_object->api == PA_PROFILE_API) + { + offset = dissect_pn_pa_profile_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data"); + } + else + { + offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data"); + } + } + + if (io_data_object->discardIOXS == FALSE) { + offset = dissect_PNIO_IOxS(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_iops, ioxs_fields); + proto_item_set_len(IODataObject_item, io_data_object->length + 1); /* Length = Databytes + IOXS Byte */ + } + else { + proto_item_set_len(IODataObject_item, io_data_object->length); /* Length = Databytes */ + } + + proto_item_append_text(IODataObject_item, ": Slot: 0x%x Subslot: 0x%x", + io_data_object->slotNr, io_data_object->subSlotNr); + + + /* ModuleIdentNr appears not only once in GSD-file -> set module name more generally */ + if (io_data_object->amountInGSDML > 1) { /* if ModuleIdentNr only appears once in GSD-file, use the found GSD-file-ModuleName, else ... */ + if (io_data_object->slotNr == 0) { + moduleName = wmem_strbuf_new(pinfo->pool, "Headstation"); + } + else { + moduleName = wmem_strbuf_new(pinfo->pool, "Module"); + } + + if (io_data_object->profisafeSupported == TRUE) { + /* PROFIsafe */ + if (io_data_object->length >= 5) { /* 5 due to 3 CRC bytes & 1 status byte & (at least) 1 data byte */ + wmem_strbuf_append(moduleName, ", DI"); + } + else { + wmem_strbuf_append(moduleName, ", DO"); + } + } + else { + /* PROFINET */ + if (io_data_object->length > 0) { + wmem_strbuf_append(moduleName, ", DI"); + } + else { + wmem_strbuf_append(moduleName, ", DO"); + } + } + + io_data_object->moduleNameStr = wmem_strdup(wmem_file_scope(), wmem_strbuf_get_str(moduleName)); + } + + proto_item_append_text(IODataObject_item, " ModuleName: \"%s\"", io_data_object->moduleNameStr); + + /* emphasize the PROFIsafe supported Modul */ + if (io_data_object->profisafeSupported == TRUE && pnio_ps_selection == TRUE) { + (proto_item_append_text(IODataObject_item, " (PROFIsafe Module)")); + } + + + /* Set frameOffset to its new value, to find the next object */ + frameOffset = frameOffset + io_data_object->length; /* frameOffset = current value + data bytes */ + if (io_data_object->discardIOXS == FALSE) { + frameOffset = frameOffset + 1; /* frameOffset = current value + iops byte */ + } + } + } + } + + /* ---- Input IOCS Object Handling ---- */ + if (station_info != NULL) { + for (frame = wmem_list_head(station_info->iocs_data_in); frame != NULL; frame = wmem_list_frame_next(frame)) { + iocs_object = (iocsObject*)wmem_list_frame_data(frame); + if (iocs_object->frameOffset == frameOffset) { + offset = dissect_PNIO_IOCS(tvb, offset, pinfo, data_tree, drep, hf_pn_io_iocs, iocs_object->slotNr, + iocs_object->subSlotNr, ioxs_fields); + + /* Set frameOffset to its new value, to find the next object */ + frameOffset = frameOffset + 1; /* frameOffset = current value + iops byte */ + + break; + } + } + } + } + + /* Dissect padding */ + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset), "GAP and RTCPadding"); + } /* END of Input Frame Handling */ + + /* ----- Output (PNIO) / Request (PNIO_PS) Frame Handling ------ */ + else if (outputFlag) { + if (pnio_ps_selection == TRUE) { + proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_type, tvb, + offset, 0, "Request", "Request Frame (IO_Controller -> IO_Device)"); + } + else { + proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_type, tvb, + offset, 0, "Output", "Output Frame (IO_Controller -> IO_Device)"); + } + + if (station_info != NULL) { + if (station_info->typeofstation != NULL) { + proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_vendor, tvb, 0, + 0, station_info->typeofstation, "\"%s\"", station_info->typeofstation); + } + if (station_info->nameofstation != NULL) { + proto_tree_add_string_format_value(data_tree, hf_pn_io_frame_info_nameofstation, tvb, 0, + 0, station_info->nameofstation, "\"%s\"", station_info->nameofstation); + } + + if (station_info->gsdPathLength == TRUE) { /* given path isn't too long for the array */ + if (station_info->gsdFound == TRUE) { /* found a GSD-file */ + if (station_info->gsdLocation != NULL) { + IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_found, tvb, offset, 0, ENC_NA); + proto_item_append_text(IODataObject_item_info, ": \"%s\"", station_info->gsdLocation); + } + } + else { + if (station_info->gsdLocation != NULL) { + IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_error, tvb, offset, 0, ENC_NA); + proto_item_append_text(IODataObject_item_info, " Please place relevant GSD-file under \"%s\"", station_info->gsdLocation); + } + } + } + else { + IODataObject_item_info = proto_tree_add_item(data_tree, hf_pn_io_frame_info_gsd_path, tvb, offset, 0, ENC_NA); + proto_item_append_text(IODataObject_item_info, " Please check your GSD-file networkpath. (No Path configured)"); + } + } + + /* ---- Output IOData-/IOCS-Object Handling ---- */ + objectCounter = number_io_data_objects_output_cr + number_iocs_output_cr; + if (objectCounter > (guint)tvb_reported_length_remaining(tvb, offset)) { + expert_add_info_format(pinfo, data_item, &ei_pn_io_too_many_data_objects, "Too many data objects: %d", objectCounter); + return(tvb_captured_length(tvb)); + } + while (objectCounter--) { + /* ---- Output IO Data Object Handling ---- */ + if (station_info != NULL) { + for (frame = wmem_list_head(station_info->ioobject_data_out); frame != NULL; frame = wmem_list_frame_next(frame)) { + io_data_object = (ioDataObject*)wmem_list_frame_data(frame); + if (io_data_object != NULL && io_data_object->frameOffset == frameOffset) { + /* Found following object */ + + IODataObject_item = proto_tree_add_item(data_tree, hf_pn_io_io_data_object, tvb, offset, 0, ENC_NA); + IODataObject_tree = proto_item_add_subtree(IODataObject_item, ett_pn_io_io_data_object); + + /* Control: the Device still uses the correct ModuleIdentNumber? */ + for (frame_diff = wmem_list_head(station_info->diff_module); frame_diff != NULL; frame_diff = wmem_list_frame_next(frame_diff)) { + module_diff_info = (moduleDiffInfo*)wmem_list_frame_data(frame_diff); + if (io_data_object->moduleIdentNr != module_diff_info->modulID) { + ModuleDiff_item = proto_tree_add_item(IODataObject_tree, hf_pn_io_io_data_object_info_module_diff, tvb, 0, 0, ENC_NA); + proto_item_append_text(ModuleDiff_item, ": Device using ModuleIdentNumber 0x%08x instead of 0x%08x", module_diff_info->modulID, io_data_object->moduleIdentNr); + break; + } + } + + proto_tree_add_uint(IODataObject_tree, hf_pn_io_io_data_object_info_moduleidentnumber, tvb, 0, 0, io_data_object->moduleIdentNr); + proto_tree_add_uint(IODataObject_tree, hf_pn_io_io_data_object_info_submoduleidentnumber, tvb, 0, 0, io_data_object->subModuleIdentNr); + + if (io_data_object->profisafeSupported == TRUE && pnio_ps_selection == TRUE) { + if (io_data_object->profisafeSupported == TRUE && psInfoText == FALSE) { + /* Only add one information string per device to the infotext */ + col_append_str(pinfo->cinfo, COL_INFO, ", PROFIsafe Device"); /* Add string to wireshark infotext */ + psInfoText = TRUE; + } + + proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_f_dest_adr, tvb, 0, 0, io_data_object->f_dest_adr); + + /* Get Safety IO Data */ + if (io_data_object->f_crc_seed == FALSE) { + safety_io_data_length = io_data_object->length - F_MESSAGE_TRAILER_4BYTE; + } else { + safety_io_data_length = io_data_object->length - F_MESSAGE_TRAILER_5BYTE; + } + + if (safety_io_data_length > 0) { + offset = dissect_pn_io_ps_uint(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_ps_f_data, + safety_io_data_length, &f_data); + } + + /* ---- Check for new PNIO data using togglebit ---- */ + controlbyte = tvb_get_guint8(tvb, offset); + toggleBitCb = controlbyte & 0x20; /* get ToggleBit of Controlbyte */ + + if (io_data_object->lastToggleBit != toggleBitCb) { /* ToggleBit has changed --> new Data incoming */ + /* Special Filter for ToggleBit within Controlbyte */ + ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_cb_toggelBitChanged, tvb, offset, 0, toggleBitCb); + proto_item_set_hidden(ModuleID_item); + + ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_cb_toggelBitChange_slot_nr, tvb, offset, 0, io_data_object->slotNr); + proto_item_set_hidden(ModuleID_item); + + ModuleID_item = proto_tree_add_uint(IODataObject_tree, hf_pn_io_ps_cb_toggelBitChange_subslot_nr, tvb, offset, 0, io_data_object->subSlotNr); + proto_item_set_hidden(ModuleID_item); + } + + offset = dissect_pn_io_ps_CB(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_ps_cb, ps_cb_fields); + offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->f_crc_len, "CRC"); + + io_data_object->last_sb_cb = controlbyte; /* save the value of current controlbyte */ + io_data_object->lastToggleBit = toggleBitCb; /* save the value of current togglebit within controlbyte */ + } /* End of PROFIsafe Module Handling */ + else { + /* Module is not PROFIsafe supported */ + if (io_data_object->api == PA_PROFILE_API) + { + offset = dissect_pn_pa_profile_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data"); + } + else + { + offset = dissect_pn_user_data(tvb, offset, pinfo, IODataObject_tree, io_data_object->length, "IO Data"); + } + } + + if (io_data_object->discardIOXS == FALSE) { + offset = dissect_PNIO_IOxS(tvb, offset, pinfo, IODataObject_tree, drep, hf_pn_io_iops, ioxs_fields); + proto_item_set_len(IODataObject_item, io_data_object->length + 1); /* Length = Databytes + IOXS Byte */ + } + else { + proto_item_set_len(IODataObject_item, io_data_object->length); /* Length = Databytes */ + } + + proto_item_append_text(IODataObject_item, ": Slot: 0x%x Subslot: 0x%x", + io_data_object->slotNr, io_data_object->subSlotNr); + + + /* ModuleIdentNr appears not only once in GSD-file -> set module name more generally */ + if (io_data_object->amountInGSDML > 1) { /* if ModuleIdentNr only appears once in GSD-file, use the found GSD-file-ModuleName, else ... */ + if (io_data_object->slotNr == 0) { + moduleName = wmem_strbuf_new(pinfo->pool, "Headstation"); + } + else { + moduleName = wmem_strbuf_new(pinfo->pool, "Module"); + } + + if (io_data_object->profisafeSupported == TRUE) { + /* PROFIsafe */ + if (io_data_object->length >= 5) { /* 5 due to 3 CRC bytes & 1 status byte & (at least) 1 data byte */ + wmem_strbuf_append(moduleName, ", DO"); + } + else { + wmem_strbuf_append(moduleName, ", DI"); + } + } + else { + /* PROFINET */ + if (io_data_object->length > 0) { + wmem_strbuf_append(moduleName, ", DO"); + } + else { + wmem_strbuf_append(moduleName, ", DI"); + } + } + + io_data_object->moduleNameStr = wmem_strdup(wmem_file_scope(), wmem_strbuf_get_str(moduleName)); + } + + proto_item_append_text(IODataObject_item, " ModuleName: \"%s\"", io_data_object->moduleNameStr); + + /* emphasize the PROFIsafe supported Modul */ + if (io_data_object->profisafeSupported == TRUE && pnio_ps_selection == TRUE) { + proto_item_append_text(IODataObject_item, " (PROFIsafe Module)"); + } + + /* Set frameOffset to its new value, to find the next object */ + frameOffset = frameOffset + io_data_object->length; /* frameOffset = current value + data bytes */ + if (io_data_object->discardIOXS == FALSE) { + frameOffset = frameOffset + 1; /* frameOffset = current value + iops byte */ + } + } + } + } + + /* ---- Output IOCS Object Handling ---- */ + if (station_info != NULL) { + for (frame = wmem_list_head(station_info->iocs_data_out); frame != NULL; frame = wmem_list_frame_next(frame)) { + iocs_object = (iocsObject*)wmem_list_frame_data(frame); + if (iocs_object->frameOffset == frameOffset) { + offset = dissect_PNIO_IOCS(tvb, offset, pinfo, data_tree, drep, hf_pn_io_iocs, iocs_object->slotNr, + iocs_object->subSlotNr, ioxs_fields); + + /* Set frameOffset to its new value, to find the next object */ + frameOffset = frameOffset + 1; /* frameOffset = current value + iops byte */ + + break; + } + } + } + } + + /* Dissect padding */ + offset = dissect_pn_user_data(tvb, offset, pinfo, tree, tvb_captured_length_remaining(tvb, offset), "GAP and RTCPadding"); + } /* END of Output Frame Handling */ + + return offset; +} + + +/* dissect the PA Profile status field */ +static int +dissect_pn_pa_profile_status(tvbuff_t *tvb, int offset, + packet_info *pinfo _U_, proto_tree *tree, int hfindex) +{ + + if (tree) { + guint8 u8status; + guint8 quality; + proto_item *status_item; + proto_tree *status_tree; + const gchar* quality_name = NULL; + + u8status = tvb_get_guint8(tvb, offset); + quality = (u8status >> 6u) & 0x3u; + + /* add status subtree */ + status_item = proto_tree_add_uint(tree, hfindex, tvb, offset, 1, u8status); + + quality_name = try_val_to_str(quality, pn_pa_profile_status_quality); + + proto_item_append_text(status_item, + " (%s)", + (quality_name != NULL) ? quality_name : "invalid"); + + status_tree = proto_item_add_subtree(status_item, ett_pn_pa_profile_status); + + proto_tree_add_item(status_tree, hf_pn_pa_profile_status_quality, tvb, offset, 1, ENC_NA); + + switch(quality) + { + case 0: + proto_tree_add_item(status_tree, hf_pn_pa_profile_status_substatus_bad, tvb, offset, 1, ENC_NA); + break; + case 1: + proto_tree_add_item(status_tree, hf_pn_pa_profile_status_substatus_uncertain, tvb, offset, 1, ENC_NA); + break; + case 2: + proto_tree_add_item(status_tree, hf_pn_pa_profile_status_substatus_good, tvb, offset, 1, ENC_NA); + break; + default: + break; + } + proto_tree_add_item(status_tree, hf_pn_pa_profile_status_update_event, tvb, offset, 1, ENC_NA); + proto_tree_add_item(status_tree, hf_pn_pa_profile_status_simulate, tvb, offset, 1, ENC_NA); + } + + return offset + 1; +} + +int +dissect_pn_pa_profile_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 length, const char *text) +{ + (void)text; + /* + All PA Profile submodules carry an 8-bit "status" plus the real data, which + currently is a float, an 8-bit integer or a 16-bit integer. + So we will have either 2, 3 or 5 bytes. + */ + if (length == 2u) + { + proto_tree_add_item(tree, hf_pn_pa_profile_value_8bit, tvb, offset, 1, ENC_BIG_ENDIAN); + dissect_pn_pa_profile_status(tvb, offset+1, pinfo, tree, hf_pn_pa_profile_status); + } + else if (length == 3u) + { + proto_tree_add_item(tree, hf_pn_pa_profile_value_16bit, tvb, offset, 2, ENC_BIG_ENDIAN); + dissect_pn_pa_profile_status(tvb, offset+2, pinfo, tree, hf_pn_pa_profile_status); + } + else if (length == 5u) + { + proto_tree_add_item(tree, hf_pn_pa_profile_value_float, tvb, offset, 4, ENC_BIG_ENDIAN); + dissect_pn_pa_profile_status(tvb, offset+4, pinfo, tree, hf_pn_pa_profile_status); + } + else + { + /* Delegate to standard user data if unknown */ + (void)dissect_pn_user_data(tvb, offset, pinfo, tree, length, "IO Data"); + } + + return offset + length; +} + +void +init_pn_io_rtc1(int proto) +{ + static hf_register_info hf[] = { + { &hf_pn_io_io_data_object, + { "IODataObject", "pn_io.io_data_object", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_io_data_object_info_module_diff, + { "Difference", "pn_io.io_data_object.diff_module", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_io_data_object_info_moduleidentnumber, + { "ModuleIdentNumber", "pn_io.io_data_object.module_nr", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_io_data_object_info_submoduleidentnumber, + { "SubmoduleIdentNumber", "pn_io.io_data_object.submodule_nr", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_info_type, + { "PN Frame Type", "pn_io.frame_info.type", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_info_vendor, + { "DeviceVendorValue", "pn_io.frame_info.vendor", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_info_nameofstation, + { "NameOfStation", "pn_io.frame_info.nameofstation", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_info_gsd_found, + { "GSD-file found", "pn_io.frame_info.gsd_found", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_info_gsd_error, + { "GSD-file not found.", "pn_io.frame_info.gsd_error", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_frame_info_gsd_path, + { "GSD-file networkpath failure!", "pn_io.frame_info.gsd_path", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iocs, + { "IOCS", "pn_io.ioxs", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_iops, + { "IOPS", "pn_io.ioxs", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ioxs_extension, + { "Extension", "pn_io.ioxs.extension", + FT_UINT8, BASE_HEX, VALS(pn_io_ioxs_extension), 0x01, + NULL, HFILL } + }, + { &hf_pn_io_ioxs_res14, + { "Reserved", "pn_io.ioxs.res14", + FT_UINT8, BASE_HEX, NULL, 0x1E, + NULL, HFILL } + }, + { &hf_pn_io_ioxs_instance, + { "Instance", "pn_io.ioxs.instance", + FT_UINT8, BASE_HEX, VALS(pn_io_ioxs_instance), 0x60, + NULL, HFILL } + }, + { &hf_pn_io_ioxs_datastate, + { "DataState", "pn_io.ioxs.datastate", + FT_UINT8, BASE_HEX, VALS(pn_io_ioxs_datastate), 0x80, + NULL, HFILL } + }, + /* PROFIsafe parameter */ + /* Status Byte & Control Byte for PROFIsafe --- dissector handle */ + { &hf_pn_io_ps_sb, + { "Status Byte", "pn_io.ps.sb", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_toggelBitChanged, + { "Status Byte", "pn_io.ps.sb.toggle_d_changed", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_toggelBitChange_slot_nr, + { "Slot_Number", "pn_io.ps.sb.toggle_d_changed.slot", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_toggelBitChange_subslot_nr, + { "Sub_Slot_Number", "pn_io.ps.sb.toggle_d_changed.subslot", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb, + { "Control Byte", "pn_io.ps.cb", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_toggelBitChanged, + { "Control Byte", "pn_io.ps.cb.toggle_h_changed", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_toggelBitChange_slot_nr, + { "Slot_Number", "pn_io.ps.cb.toggle_h_changed.slot", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_toggelBitChange_subslot_nr, + { "Sub_Slot_Number", "pn_io.ps.cb.toggle_h_changed.subslot", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + /* Structures for dissecting Status Byte & Control Byte PROFIsafe ---dissector details */ + { &hf_pn_io_ps_sb_iparOK, + { "iPar_OK - F-Device has new iParameter values assigned", "pn_io.ps.sb.iPar_OK", + FT_UINT8, BASE_HEX, NULL, 0x01, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_DeviceFault, + { "Device_Fault - Failure exists in F-Device or F-Module", "pn_io.ps.sb.DeviceFault", + FT_UINT8, BASE_HEX, NULL, 0x02, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_CECRC, + { "CE_CRC - CRC Communication fault", "pn_io.ps.sb.CE_CRC", + FT_UINT8, BASE_HEX, NULL, 0x04, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_WDtimeout, + { "WD_timeout - WatchDog timeout Communication fault", "pn_io.ps.sb.WD_timeout", + FT_UINT8, BASE_HEX, NULL, 0x08, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_FVactivated, + { "FV_activated - Fail-safe values (FV) activated", "pn_io.ps.sb.FV_activated", + FT_UINT8, BASE_HEX, NULL, 0x10, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_Toggle_d, + { "Toggle_d - Device-based Toggle Bit", "pn_io.ps.sb.Toggle_d", + FT_UINT8, BASE_HEX, NULL, 0x20, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_ConsNr_reset, + { "cons_nr_R - F-Device has reset its consecutive number counter", "pn_io.ps.sb.cons_nr_R", + FT_UINT8, BASE_HEX, NULL, 0x40, + NULL, HFILL } + }, + { &hf_pn_io_ps_sb_res, + { "Bit7 - reserved for future releases", "pn_io.ps.sb.bit7", + FT_UINT8, BASE_HEX, NULL, 0x80, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_iparEN, + { "iPar_EN - iParameter assignment deblocked", "pn_io.ps.cb.iparEN", + FT_UINT8, BASE_HEX, NULL, 0x01, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_OAReq, + { "OA_Req - Operator acknowledge requested", "pn_io.ps.cb.OA_Req", + FT_UINT8, BASE_HEX, NULL, 0x02, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_resetConsNr, + { "R_cons_nr - Set the Virtual Consecutive Number within the F-Device to be \"0\"", "pn_io.ps.cb.R_cons_nr", + FT_UINT8, BASE_HEX, NULL, 0x04, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_useTO2, + { "Bit3 - Reserved or Use the secondary watchdog (Use_TO2)", "pn_io.ps.cb.bit3", + FT_UINT8, BASE_HEX, NULL, 0x08, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_activateFV, + { "activate_FV - Fail-safe values (FV) to be activated", "pn_io.ps.cb.activate_FV", + FT_UINT8, BASE_HEX, NULL, 0x10, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_Toggle_h, + { "Toggle_h - Host-based Toggle Bit", "pn_io.ps.cb.Toggle_h", + FT_UINT8, BASE_HEX, NULL, 0x20, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_Chf_ACK, + { "Bit6 - Reserved or Operator acknowledge after cleared channel fault (ChF_Ack)", "pn_io.ps.cb.bit6", + FT_UINT8, BASE_HEX, NULL, 0x40, + NULL, HFILL } + }, + { &hf_pn_io_ps_cb_loopcheck, + { "Bit7 - Reserved or Loop-back check (Loopcheck, shall be set to 1)", "pn_io.ps.cb.bit7", + FT_UINT8, BASE_HEX, NULL, 0x80, + NULL, HFILL } + }, + /* PROFIsafe */ + { &hf_pn_io_ps_f_dest_adr, + { "F_Dest_Add", "pn_io.ps.f_dest_add", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_ps_f_data, + { "SafetyIO Data", "pn_io.ps.f_data", + FT_UINT64, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_pa_profile_status, + { "Status", "pn_io.pa.status", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_pa_profile_status_quality, + { "Quality", "pn_io.pa.status.quality", + FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_quality), 0xC0, + NULL, HFILL } + }, + { &hf_pn_pa_profile_status_substatus_bad, + { "Substatus", "pn_io.pa.status.substatus", + FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_bad), 0x3C, + NULL, HFILL } + }, + { &hf_pn_pa_profile_status_substatus_uncertain, + { "Substatus", "pn_io.pa.status.substatus", + FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_uncertain), 0x3C, + NULL, HFILL } + }, + { &hf_pn_pa_profile_status_substatus_good, + { "Substatus", "pn_io.pa.status.substatus", + FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_substatus_good), 0x3C, + NULL, HFILL } + }, + { &hf_pn_pa_profile_status_update_event, + { "Update Event", "pn_io.pa.status.update", + FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_update_event), 0x02, + NULL, HFILL } + }, + { &hf_pn_pa_profile_status_simulate, + { "Simulate", "pn_io.pa.status.simulate", + FT_UINT8, BASE_HEX, VALS(pn_pa_profile_status_simulate), 0x01, + NULL, HFILL } + }, + { &hf_pn_pa_profile_value_8bit, + { "Value", "pn_io.pa.value", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_pa_profile_value_16bit, + { "Value", "pn_io.pa.value", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_pa_profile_value_float, + { "Value", "pn_io.pa.value.float", + FT_FLOAT, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + }; + + static gint *ett[] = { + &ett_pn_io_rtc, + &ett_pn_io_ioxs, + &ett_pn_io_io_data_object, + &ett_pn_pa_profile_status + }; + + static ei_register_info ei[] = { + { &ei_pn_io_too_many_data_objects, { "pn_io.too_many_data_objects", PI_MALFORMED, PI_ERROR, "Too many data objects", EXPFILL }}, + }; + + expert_module_t* expert_pn_io; + + proto_pn_io_rtc1 = proto; + proto_register_field_array(proto, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_pn_io = expert_register_protocol(proto_pn_io_rtc1); + expert_register_field_array(expert_pn_io, ei, array_length(ei)); +} + + +/* +* Editor modelines - https://www.wireshark.org/tools/modelines.html +* +* Local variables: +* c-basic-offset: 4 +* tab-width: 8 +* indent-tabs-mode: nil +* End: +* +* vi: set shiftwidth=4 tabstop=8 expandtab: +* :indentSize=4:tabSize=8:noTabs=true: +*/ diff --git a/plugins/epan/profinet/packet-pn.c b/plugins/epan/profinet/packet-pn.c new file mode 100644 index 00000000..9bdbc3cc --- /dev/null +++ b/plugins/epan/profinet/packet-pn.c @@ -0,0 +1,1518 @@ +/* packet-pn.c + * Common functions for other PROFINET protocols like IO, CBA, DCP, ... + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#include "config.h" + +#include + +#include +#include +#include +#include + +#include "packet-pn.h" + +static int hf_pn_padding = -1; +static int hf_pn_undecoded_data = -1; +static int hf_pn_user_data = -1; +static int hf_pn_user_bytes = -1; +static int hf_pn_frag_bytes = -1; +static int hf_pn_malformed = -1; + +static int hf_pn_io_status = -1; + +static int hf_pn_io_error_code = -1; +static int hf_pn_io_error_decode = -1; +static int hf_pn_io_error_code1 = -1; +static int hf_pn_io_error_code1_pniorw = -1; +static int hf_pn_io_error_code1_pnio = -1; +static int hf_pn_io_error_code2 = -1; +static int hf_pn_io_error_code2_pniorw = -1; +static int hf_pn_io_error_code2_pnio_1 = -1; +static int hf_pn_io_error_code2_pnio_2 = -1; +static int hf_pn_io_error_code2_pnio_3 = -1; +static int hf_pn_io_error_code2_pnio_4 = -1; +static int hf_pn_io_error_code2_pnio_5 = -1; +static int hf_pn_io_error_code2_pnio_6 = -1; +static int hf_pn_io_error_code2_pnio_7 = -1; +static int hf_pn_io_error_code2_pnio_8 = -1; +static int hf_pn_io_error_code2_pnio_13 = -1; +static int hf_pn_io_error_code2_pnio_20 = -1; +static int hf_pn_io_error_code2_pnio_21 = -1; +static int hf_pn_io_error_code2_pnio_22 = -1; +static int hf_pn_io_error_code2_pnio_23 = -1; +static int hf_pn_io_error_code2_pnio_40 = -1; +static int hf_pn_io_error_code2_pnio_60 = -1; +static int hf_pn_io_error_code2_pnio_61 = -1; +static int hf_pn_io_error_code2_pnio_62 = -1; +static int hf_pn_io_error_code2_pnio_63 = -1; +static int hf_pn_io_error_code2_pnio_64 = -1; +static int hf_pn_io_error_code2_pnio_65 = -1; +static int hf_pn_io_error_code2_pnio_66 = -1; +static int hf_pn_io_error_code2_pnio_70 = -1; +static int hf_pn_io_error_code2_pnio_71 = -1; +static int hf_pn_io_error_code2_pnio_72 = -1; +static int hf_pn_io_error_code2_pnio_73 = -1; +static int hf_pn_io_error_code2_pnio_74 = -1; +static int hf_pn_io_error_code2_pnio_75 = -1; +static int hf_pn_io_error_code2_pnio_76 = -1; +static int hf_pn_io_error_code2_pnio_77 = -1; +static int hf_pn_io_error_code2_pnio_253 = -1; +static int hf_pn_io_error_code2_pnio_255 = -1; + +static gint ett_pn_io_status = -1; + +static expert_field ei_pn_undecoded_data = EI_INIT; +static expert_field ei_pn_io_error_code1 = EI_INIT; +static expert_field ei_pn_io_error_code2 = EI_INIT; + +static const value_string pn_io_error_code[] = { + { 0x00, "OK" }, + { 0x81, "PNIO" }, + { 0xCF, "RTA error" }, + { 0xDA, "AlarmAck" }, + { 0xDB, "IODConnectRes" }, + { 0xDC, "IODReleaseRes" }, + { 0xDD, "IODControlRes" }, + { 0xDE, "IODReadRes" }, + { 0xDF, "IODWriteRes" }, + { 0, NULL } +}; + +static const value_string pn_io_error_decode[] = { + { 0x00, "OK" }, + { 0x80, "PNIORW" }, + { 0x81, "PNIO" }, + { 0, NULL } +}; + +/* dummy for unknown decode */ +static const value_string pn_io_error_code1[] = { + { 0x00, "OK" }, + { 0, NULL } +}; + +/* dummy for unknown decode/code1 combination */ +static const value_string pn_io_error_code2[] = { + { 0x00, "OK" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code1_pniorw[] = { + /* high nibble 0-9 not specified -> legacy codes */ + { 0xa0, "application: read error" }, + { 0xa1, "application: write error" }, + { 0xa2, "application: module failure" }, + { 0xa3, "application: not specified" }, + { 0xa4, "application: not specified" }, + { 0xa5, "application: not specified" }, + { 0xa6, "application: not specified" }, + { 0xa7, "application: busy" }, + { 0xa8, "application: version conflict" }, + { 0xa9, "application: feature not supported" }, + { 0xaa, "application: User specific 1" }, + { 0xab, "application: User specific 2" }, + { 0xac, "application: User specific 3" }, + { 0xad, "application: User specific 4" }, + { 0xae, "application: User specific 5" }, + { 0xaf, "application: User specific 6" }, + { 0xb0, "access: invalid index" }, + { 0xb1, "access: write length error" }, + { 0xb2, "access: invalid slot/subslot" }, + { 0xb3, "access: type conflict" }, + { 0xb4, "access: invalid area" }, + { 0xb5, "access: state conflict" }, + { 0xb6, "access: access denied" }, + { 0xb7, "access: invalid range" }, + { 0xb8, "access: invalid parameter" }, + { 0xb9, "access: invalid type" }, + { 0xba, "access: backup" }, + { 0xbb, "access: User specific 7" }, + { 0xbc, "access: User specific 8" }, + { 0xbd, "access: User specific 9" }, + { 0xbe, "access: User specific 10" }, + { 0xbf, "access: User specific 11" }, + { 0xc0, "resource: read constrain conflict" }, + { 0xc1, "resource: write constrain conflict" }, + { 0xc2, "resource: resource busy" }, + { 0xc3, "resource: resource unavailable" }, + { 0xc4, "resource: not specified" }, + { 0xc5, "resource: not specified" }, + { 0xc6, "resource: not specified" }, + { 0xc7, "resource: not specified" }, + { 0xc8, "resource: User specific 12" }, + { 0xc9, "resource: User specific 13" }, + { 0xca, "resource: User specific 14" }, + { 0xcb, "resource: User specific 15" }, + { 0xcc, "resource: User specific 16" }, + { 0xcd, "resource: User specific 17" }, + { 0xce, "resource: User specific 18" }, + { 0xcf, "resource: User specific 19" }, + /* high nibble d-f user specific */ + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pniorw[] = { + /* all values are user specified */ + { 0, NULL } +}; + +static const value_string pn_io_error_code1_pnio[] = { + { 0x00 /* 0*/, "Reserved" }, + { 0x01 /* 1*/, "Connect: Faulty ARBlockReq" }, + { 0x02 /* 2*/, "Connect: Faulty IOCRBlockReq" }, + { 0x03 /* 3*/, "Connect: Faulty ExpectedSubmoduleBlockReq" }, + { 0x04 /* 4*/, "Connect: Faulty AlarmCRBlockReq" }, + { 0x05 /* 5*/, "Connect: Faulty PrmServerBlockReq" }, + { 0x06 /* 6*/, "Connect: Faulty MCRBlockReq" }, + { 0x07 /* 7*/, "Connect: Faulty ARRPCBlockReq" }, + { 0x08 /* 8*/, "Read/Write Record: Faulty Record" }, + { 0x09 /* 9*/, "Connect: Faulty IRInfoBlock" }, + { 0x0A /* 10*/, "Connect: Faulty SRInfoBlock" }, + { 0x0B /* 11*/, "Connect: Faulty ARFSUBlock" }, + { 0x0C /* 12*/, "Connect: Faulty ARVendorBlockReq" }, + { 0x0D /* 13*/, "Connect: Faulty RSInfoBlock" }, + { 0x14 /* 20*/, "IODControl: Faulty ControlBlockConnect" }, + { 0x15 /* 21*/, "IODControl: Faulty ControlBlockPlug" }, + { 0x16 /* 22*/, "IOXControl: Faulty ControlBlock after a connect est." }, + { 0x17 /* 23*/, "IOXControl: Faulty ControlBlock a plug alarm" }, + { 0x18 /* 24*/, "IOXControl: Faulty ControlBlockPrmBegin" }, + { 0x19 /* 25*/, "IOXControl: Faulty SubmoduleListBlock" }, + + { 0x28 /* 40*/, "Release: Faulty ReleaseBlock" }, + + { 0x32 /* 50*/, "Response: Faulty ARBlockRes" }, + { 0x33 /* 51*/, "Response: Faulty IOCRBlockRes" }, + { 0x34 /* 52*/, "Response: Faulty AlarmCRBlockRes" }, + { 0x35 /* 53*/, "Response: Faulty ModuleDifflock" }, + { 0x36 /* 54*/, "Response: Faulty ARRPCBlockRes" }, + { 0x37 /* 55*/, "Response: Faulty ARServerBlockRes" }, + { 0x38 /* 56*/, "Response: Faulty ARVendorBlockRes" }, + + { 0x3c /* 60*/, "AlarmAck Error Codes" }, + { 0x3d /* 61*/, "CMDEV" }, + { 0x3e /* 62*/, "CMCTL" }, + { 0x3f /* 63*/, "CTLDINA" }, + { 0x40 /* 64*/, "CMRPC" }, + { 0x41 /* 65*/, "ALPMI" }, + { 0x42 /* 66*/, "ALPMR" }, + { 0x43 /* 67*/, "LMPM" }, + { 0x44 /* 68*/, "MAC" }, + { 0x45 /* 69*/, "RPC" }, + { 0x46 /* 70*/, "APMR" }, + { 0x47 /* 71*/, "APMS" }, + { 0x48 /* 72*/, "CPM" }, + { 0x49 /* 73*/, "PPM" }, + { 0x4a /* 74*/, "DCPUCS" }, + { 0x4b /* 75*/, "DCPUCR" }, + { 0x4c /* 76*/, "DCPMCS" }, + { 0x4d /* 77*/, "DCPMCR" }, + { 0x4e /* 78*/, "FSPM" }, + { 0x4f /* 79*/, "RSI" }, + { 0x50 /* 80*/, "RSIR" }, + + { 0x64 /*100*/, "CTLSM" }, + { 0x65 /*101*/, "CTLRDI" }, + { 0x66 /*102*/, "CTLRDR" }, + { 0x67 /*103*/, "CTLWRI" }, + { 0x68 /*104*/, "CTLWRR" }, + { 0x69 /*105*/, "CTLIO" }, + { 0x6a /*106*/, "CTLSU" }, + { 0x6b /*107*/, "CTLRPC" }, + { 0x6c /*108*/, "CTLBE" }, + { 0x6d /*109*/, "CTLSRL" }, + { 0x6e /*110*/, "NME" }, + { 0x6f /*111*/, "TDE" }, + { 0x70 /*112*/, "PCE" }, + { 0x71 /*113*/, "NCE" }, + { 0x72 /*114*/, "NUE" }, + { 0x73 /*115*/, "BNME" }, + { 0x74 /*116*/, "CTLSAM" }, + + { 0xc8 /*200*/, "CMSM" }, + { 0xca /*202*/, "CMRDR" }, + { 0xcc /*204*/, "CMWRR" }, + { 0xcd /*205*/, "CMIO" }, + { 0xce /*206*/, "CMSU" }, + { 0xd0 /*208*/, "CMINA" }, + { 0xd1 /*209*/, "CMPBE" }, + { 0xd2 /*210*/, "CMSRL" }, + { 0xd3 /*211*/, "CMDMC" }, + { 0xd4 /*212*/, "CMSAM" }, + + { 0xfd /*253*/, "RTA_ERR_CLS_PROTOCOL" }, + { 0xff /*255*/, "User specific" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_1[] = { + /* CheckingRules for ARBlockReq */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter ARType" }, + { 5, "Error in Parameter ARUUID" }, + { 7, "Error in Parameter CMInitiatorMACAddress" }, + { 8, "Error in Parameter CMInitiatorObjectUUID" }, + { 9, "Error in Parameter ARProperties" }, + { 10, "Error in Parameter CMInitiatorActivityTimeoutFactor" }, + { 11, "Error in Parameter InitiatorUDPRTPort" }, + { 12, "Error in Parameter StationNameLength" }, + { 13, "Error in Parameter CMInitiatorStationName" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_2[] = { + /* CheckingRules for IOCRBlockReq */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter IOCRType" }, + { 5, "Error in Parameter IOCRReference" }, + { 6, "Error in Parameter LT" }, + { 7, "Error in Parameter IOCRProperties" }, + { 8, "Error in Parameter DataLength" }, + { 9, "Error in Parameter FrameID" }, + { 10, "Error in Parameter SendClockFactor" }, + { 11, "Error in Parameter ReductionRatio" }, + { 12, "Error in Parameter Phase" }, + { 14, "Error in Parameter FrameSendOffset" }, + { 15, "Error in Parameter WatchdogFactor" }, + { 16, "Error in Parameter DataHoldFactor" }, + { 17, "Error in Parameter IOCRTagHeader" }, + { 18, "Error in Parameter IOCRMulticastMacAddress" }, + { 19, "Error in Parameter NumberOfAPI" }, + { 20, "Error in Parameter API" }, + { 21, "Error in Parameter NumberOfIODataObjects" }, + { 22, "Error in Parameter SlotNumber" }, + { 23, "Error in Parameter SubslotNumber" }, + { 24, "Error in Parameter IODataObjectFrameOffset" }, + { 25, "Error in Parameter NumberOfIOCS" }, + { 26, "Error in Parameter SlotNumber" }, + { 27, "Error in Parameter SubslotNumber" }, + { 28, "Error in Parameter IOCSFrameOffset" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_3[] = { + /* CheckingRules for ExpectedSubmoduleBlockReq */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter NumberOfAPI" }, + { 5, "Error in Parameter API" }, + { 6, "Error in Parameter SlotNumber" }, + { 7, "Error in Parameter ModuleIdentNumber" }, + { 8, "Error in Parameter ModuleProperties" }, + { 9, "Error in Parameter NumberOfSubmodules" }, + { 10, "Error in Parameter SubslotNumber" }, + { 12, "Error in Parameter SubmoduleProperties" }, + { 13, "Error in Parameter DataDescription" }, + { 14, "Error in Parameter SubmoduleDataLength" }, + { 15, "Error in Parameter LengthIOPS" }, + { 16, "Error in Parameter LengthIOCS" }, + { 0, NULL } +}; + + +static const value_string pn_io_error_code2_pnio_4[] = { + /* CheckingRules for AlarmCRBlockReq */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter AlarmCRType" }, + { 5, "Error in Parameter LT" }, + { 6, "Error in Parameter AlarmCRProperties" }, + { 7, "Error in Parameter RTATimeoutFactor" }, + { 8, "Error in Parameter RTARetries" }, + { 10, "Error in Parameter MaxAlarmDataLength" }, + { 11, "Error in Parameter AlarmCRTagHeaderHigh" }, + { 12, "Error in Parameter AlarmCRTagHeaderLow" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_5[] = { + /* CheckingRules for PrmServerBlockReq */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 6, "Error in Parameter CMInitiatorActivityTimeoutFactor" }, + { 7, "Error in Parameter StationNameLength" }, + { 8, "Error in Parameter ParameterServerStationName" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_6[] = { + /* CheckingRules for MCRBlockReq */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter IOCRReference" }, + { 5, "Error in Parameter AddressResolutionProperties" }, + { 6, "Error in Parameter MCITimeoutFactor" }, + { 7, "Error in Parameter StationNameLength" }, + { 8, "Error in Parameter ProviderStationName" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_7[] = { + /* CheckingRules for MCRBlockReq */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter InitiatorRPCServerPort" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_8[] = { + /* CheckingRules for Read/Write ParameterReqHeader */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 5, "Error in Parameter ARUUID" }, + { 6, "Error in Parameter API" }, + { 7, "Error in Parameter SlotNumber" }, + { 8, "Error in Parameter SubslotNumber" }, + { 9, "Error in Parameter Padding" }, + { 10, "Error in Parameter Index" }, + { 11, "Error in Parameter RecordDataLength" }, + { 12, "Error in Parameter TargetARUUID" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_13[] = { + /* CheckingRules for RSInfoBlock */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter Padding" }, + { 5, "Error in Parameter RSProperties" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_20[] = { + /* CheckingRules for ControlBlockConnect */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter Padding" }, + { 6, "Error in Parameter SessionKey" }, + { 7, "Error in Parameter Padding" }, + { 8, "Error in Parameter ControlCommand" }, + { 9, "Error in Parameter ControlBlockProperties" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_21[] = { + /* CheckingRules for ControlBlockPlug */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter Padding" }, + { 6, "Error in Parameter SessionKey" }, + { 7, "Error in Parameter AlarmSequenceNumber" }, + { 8, "Error in Parameter ControlCommand" }, + { 9, "Error in Parameter ControlBlockProperties" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_22[] = { + /* CheckingRule for ControlBlockConnect */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter Padding" }, + { 6, "Error in Parameter SessionKey" }, + { 7, "Error in Parameter Padding" }, + { 8, "Error in Parameter ControlCommand" }, + { 9, "Error in Parameter ControlBlockProperties" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_23[] = { + /* CheckingRules for ControlBlockPlug */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter Padding" }, + { 6, "Error in Parameter SessionKey" }, + { 7, "Error in Parameter AlarmSequenceNumber" }, + { 8, "Error in Parameter ControlCommand" }, + { 9, "Error in Parameter ControlBlockProperties" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_40[] = { + /* CheckingRules for ReleaseBlock */ + { 0, "Error in Parameter BlockType" }, + { 1, "Error in Parameter BlockLength" }, + { 2, "Error in Parameter BlockVersionHigh" }, + { 3, "Error in Parameter BlockVersionLow" }, + { 4, "Error in Parameter Padding" }, + { 6, "Error in Parameter SessionKey" }, + { 7, "Error in Parameter Padding" }, + { 8, "Error in Parameter ControlCommand" }, + { 9, "Error in Parameter ControlBlockProperties" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_60[] = { + /* AlarmAck Error Codes */ + { 0, "Alarm Type Not Supported" }, + { 1, "Wrong Submodule State" }, + { 2, "IOCARSR Backup - Alarm not executed" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_61[] = { + /* CMDEV */ + { 0, "State Conflict" }, + { 1, "Resources" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_62[] = { + /* CMCTL */ + { 0, "State Conflict" }, + { 1, "Timeout" }, + { 2, "No data send" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_63[] = { + /* NRPM */ + { 0, "No DCP active" }, + { 1, "DNS Unknown_RealStationName" }, + { 2, "DCP No_RealStationName" }, + { 3, "DCP Multiple_RealStationName" }, + { 4, "DCP No_StationName" }, + { 5, "No_IP_Addr" }, + { 6, "DCP_Set_Error" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_64[] = { + /* RMPM */ + { 0, "ArgsLength invalid" }, + { 1, "Unknown Blocks" }, + { 2, "IOCR Missing" }, + { 3, "Wrong AlarmCRBlock count" }, + { 4, "Out of AR Resources" }, + { 5, "AR UUID unknown" }, + { 6, "State conflict" }, + { 7, "Out of Provider, Consumer or Alarm Resources" }, + { 8, "Out of Memory" }, + { 9, "Pdev already owned" }, + { 10, "ARset State conflict during connection establishment" }, + { 11, "ARset Parameter conflict during connection establishment" }, + { 12, "Pdev, port(s) without interface" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_65[] = { + /* ALPMI */ + { 0, "Invalid State" }, + { 1, "Wrong ACK-PDU" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_66[] = { + /* ALPMR */ + { 0, "Invalid State" }, + { 1, "Wrong Notification PDU" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_70[] = { + /* APMR */ + { 0, "Invalid State" }, + { 1, "LMPM signaled error" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_71[] = { + /* APMS */ + { 0, "Invalid State" }, + { 1, "LMPM signaled error" }, + { 2, "Timeout" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_72[] = { + /* CPM */ + { 1, "Invalid State" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_73[] = { + /* PPM */ + { 1, "Invalid State" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_74[] = { + /* DCPUCS */ + { 0, "Invalid State" }, + { 1, "LMPM signaled an error" }, + { 2, "Timeout" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_75[] = { + /* DCPUCR */ + { 0, "Invalid State" }, + { 1, "LMPM signaled an error" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_76[] = { + /* DCPMCS */ + { 0, "Invalid State" }, + { 1, "LMPM signaled an error" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_77[] = { + /* DCPMCR */ + { 0, "Invalid State" }, + { 1, "LMPM signaled an error" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_253[] = { + { 0, "reserved" }, + { 1, "Error within the coordination of sequence numbers (RTA_ERR_CODE_SEQ) error" }, + { 2, "Instance closed (RTA_ERR_ABORT)" }, + { 3, "AR out of memory (RTA_ERR_ABORT)" }, + { 4, "AR add provider or consumer failed (RTA_ERR_ABORT)" }, + { 5, "AR consumer DHT/WDT expired (RTA_ERR_ABORT)" }, + { 6, "AR cmi timeout (RTA_ERR_ABORT)" }, + { 7, "AR alarm-open failed (RTA_ERR_ABORT)" }, + { 8, "AR alarm-send.cnf(-) (RTA_ERR_ABORT)" }, + { 9, "AR alarm-ack-send.cnf(-) (RTA_ERR_ABORT)" }, + { 10, "AR alarm data too long (RTA_ERR_ABORT)" }, + { 11, "AR alarm.ind(err) (RTA_ERR_ABORT)" }, + { 12, "AR rpc-client call.cnf(-) (RTA_ERR_ABORT)" }, + { 13, "AR abort.req (RTA_ERR_ABORT)" }, + { 14, "AR re-run aborts existing (RTA_ERR_ABORT)" }, + { 15, "AR release.ind received (RTA_ERR_ABORT)" }, + { 16, "AR device deactivated (RTA_ERR_ABORT)" }, + { 17, "AR removed (RTA_ERR_ABORT)" }, + { 18, "AR protocol violation (RTA_ERR_ABORT)" }, + { 19, "AR name resolution error (RTA_ERR_ABORT)" }, + { 20, "AR RPC-Bind error (RTA_ERR_ABORT)" }, + { 21, "AR RPC-Connect error (RTA_ERR_ABORT)" }, + { 22, "AR RPC-Read error (RTA_ERR_ABORT)" }, + { 23, "AR RPC-Write error (RTA_ERR_ABORT)" }, + { 24, "AR RPC-Control error (RTA_ERR_ABORT)" }, + { 25, "AR forbidden pull or plug after check.rsp and before in-data.ind (RTA_ERR_ABORT)" }, + { 26, "AR AP removed (RTA_ERR_ABORT)" }, + { 27, "AR link down (RTA_ERR_ABORT)" }, + { 28, "AR could not register multicast-mac address (RTA_ERR_ABORT)" }, + { 29, "not synchronized (cannot start companion-ar) (RTA_ERR_ABORT)" }, + { 30, "wrong topology (cannot start companion-ar) (RTA_ERR_ABORT)" }, + { 31, "dcp, station-name changed (RTA_ERR_ABORT)" }, + { 32, "dcp, reset to factory-settings (RTA_ERR_ABORT)" }, + { 33, "cannot start companion-AR because a 0x8ipp submodule in the first AR... (RTA_ERR_ABORT)" }, + { 34, "no irdata record yet (RTA_ERR_ABORT)" }, + { 35, "PDEV (RTA_ERROR_ABORT)" }, + { 36, "PDEV, no port offers required speed/duplexity (RTA_ERROR_ABORT)" }, + { 37, "IP-Suite [of the IOC] changed by means of DCP_Set(IPParameter) or local engineering (RTA_ERROR_ABORT)" }, + { 38, "IOCARSR, RDHT expired" }, + { 39, "IOCARSR, Pdev, parameterization impossible" }, + { 40, "Remote application ready timeout expired" }, + { 41, "IOCARSR, Redundant interface list or access to the peripherals impossible" }, + { 42, "IOCARSR, MTOT expired" }, + { 43, "IOCARSR, AR protocol violation" }, + { 44, "PDEV, plug port without CombinedObjectContainer" }, + { 45, "NME, no or wrong configuration" }, + { 0, NULL } +}; + +static const value_string pn_io_error_code2_pnio_255[] = { + /* User specific */ + { 255, "User abort" }, + { 0, NULL } +}; + + +/* Initialize PNIO RTC1 stationInfo memory */ +void +init_pnio_rtc1_station(stationInfo *station_info) { + station_info->iocs_data_in = wmem_list_new(wmem_file_scope()); + station_info->iocs_data_out = wmem_list_new(wmem_file_scope()); + station_info->ioobject_data_in = wmem_list_new(wmem_file_scope()); + station_info->ioobject_data_out = wmem_list_new(wmem_file_scope()); + station_info->diff_module = wmem_list_new(wmem_file_scope()); +} + +/* dissect an 8 bit unsigned integer */ +int +dissect_pn_uint8(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, guint8 *pdata) +{ + guint8 data; + + data = tvb_get_guint8 (tvb, offset); + proto_tree_add_uint(tree, hfindex, tvb, offset, 1, data); + if (pdata) + *pdata = data; + return offset + 1; +} + +/* dissect a 16 bit unsigned integer; return the item through a pointer as well */ +int +dissect_pn_uint16_ret_item(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, guint16 *pdata, proto_item ** new_item) +{ + guint16 data; + proto_item *item = NULL; + + data = tvb_get_ntohs (tvb, offset); + + item = proto_tree_add_uint(tree, hfindex, tvb, offset, 2, data); + if (pdata) + *pdata = data; + if (new_item) + *new_item = item; + return offset + 2; +} + +/* dissect a 16 bit unsigned integer */ +int +dissect_pn_uint16(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, guint16 *pdata) +{ + guint16 data; + + data = tvb_get_ntohs (tvb, offset); + + proto_tree_add_uint(tree, hfindex, tvb, offset, 2, data); + if (pdata) + *pdata = data; + return offset + 2; +} + +/* dissect a 16 bit signed integer */ +int +dissect_pn_int16(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, gint16 *pdata) +{ + gint16 data; + + data = tvb_get_ntohs (tvb, offset); + + proto_tree_add_int(tree, hfindex, tvb, offset, 2, data); + if (pdata) + *pdata = data; + return offset + 2; +} + +/* dissect a 24bit OUI (IEC organizational unique id) */ +int +dissect_pn_oid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, guint32 *pdata) +{ + guint32 data; + + data = tvb_get_ntoh24(tvb, offset); + + proto_tree_add_uint(tree, hfindex, tvb, offset, 3, data); + if (pdata) + *pdata = data; + return offset + 3; +} + +/* dissect a 6 byte MAC address */ +int +dissect_pn_mac(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, guint8 *pdata) +{ + guint8 data[6]; + + tvb_memcpy(tvb, data, offset, 6); + proto_tree_add_ether(tree, hfindex, tvb, offset, 6, data); + + if (pdata) + memcpy(pdata, data, 6); + + return offset + 6; +} + +/* dissect an IPv4 address */ +int +dissect_pn_ipv4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, guint32 *pdata) +{ + guint32 data; + + data = tvb_get_ipv4(tvb, offset); + proto_tree_add_ipv4(tree, hfindex, tvb, offset, 4, data); + + if (pdata) + *pdata = data; + + return offset + 4; +} + +/* dissect a 16 byte UUID address */ +int +dissect_pn_uuid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, e_guid_t *uuid) +{ + guint8 drep[2] = { 0,0 }; + + offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep, + hfindex, uuid); + + return offset; +} + +/* "dissect" some bytes still undecoded (with Expert warning) */ +int +dissect_pn_undecoded(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 length) +{ + proto_item *item; + + + item = proto_tree_add_string_format(tree, hf_pn_undecoded_data, tvb, offset, length, "data", + "Undecoded Data: %d bytes", length); + + expert_add_info_format(pinfo, item, &ei_pn_undecoded_data, + "Undecoded Data, %u bytes", length); + + return offset + length; +} + +/* "dissect" some user bytes */ +int +dissect_pn_user_data_bytes(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 length, int iSelect) +{ + if(iSelect == FRAG_DATA) + proto_tree_add_item(tree, hf_pn_frag_bytes, tvb, offset, length, ENC_NA); + else + proto_tree_add_item(tree, hf_pn_user_bytes, tvb, offset, length, ENC_NA); + + return offset + length; +} + +int +dissect_pn_user_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 length, const char *text) +{ + if (length != 0) { + proto_tree_add_string_format(tree, hf_pn_user_data, tvb, offset, length, "data", + "%s: %d byte", text, length); + } + return offset + length; +} + +/* packet is malformed, mark it as such */ +int +dissect_pn_malformed(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 length) +{ + proto_tree_add_item(tree, hf_pn_malformed, tvb, 0, 10000, ENC_NA); + + return offset + length; +} + + +/* dissect some padding data (with the given length) */ +int +dissect_pn_padding(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, int length) +{ + proto_tree_add_string_format(tree, hf_pn_padding, tvb, offset, length, "data", + "Padding: %u byte", length); + + return offset + length; +} + +/* align offset to 4 */ +int +dissect_pn_align4(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tree) +{ + guint padding = 0; + + + if (offset % 4) { + padding = 4 - (offset % 4); + + proto_tree_add_string_format(tree, hf_pn_padding, tvb, offset, padding, "data", + "Padding: %u byte", padding); + } + + return offset + padding; +} + +/* dissect the four status (error) fields */ +int +dissect_PNIO_status(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep) +{ + guint8 u8ErrorCode; + guint8 u8ErrorDecode; + guint8 u8ErrorCode1; + guint8 u8ErrorCode2; + + proto_item *sub_item; + proto_tree *sub_tree; + guint32 u32SubStart; + int bytemask = (drep[0] & DREP_LITTLE_ENDIAN) ? 3 : 0; + + const value_string *error_code1_vals; + const value_string *error_code2_vals = pn_io_error_code2; /* defaults */ + + + + /* status */ + sub_item = proto_tree_add_item(tree, hf_pn_io_status, tvb, offset, 0, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn_io_status); + u32SubStart = offset; + + /* the PNIOStatus field is existing in both the RPC and the application data, + * depending on the current PDU. + * As the byte representation of these layers are different, this has to be handled + * in a somewhat different way than elsewhere. */ + + dissect_dcerpc_uint8(tvb, offset + (0 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code, &u8ErrorCode); + dissect_dcerpc_uint8(tvb, offset + (1 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_decode, &u8ErrorDecode); + + switch (u8ErrorDecode) { + case(0x80): /* PNIORW */ + dissect_dcerpc_uint8(tvb, offset + (2 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code1_pniorw, &u8ErrorCode1); + error_code1_vals = pn_io_error_code1_pniorw; + + /* u8ErrorCode2 for PNIORW is always user specific */ + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pniorw, &u8ErrorCode2); + + error_code2_vals = pn_io_error_code2_pniorw; + + break; + case(0x81): /* PNIO */ + dissect_dcerpc_uint8(tvb, offset + (2 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code1_pnio, &u8ErrorCode1); + error_code1_vals = pn_io_error_code1_pnio; + + switch (u8ErrorCode1) { + case(1): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_1, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_1; + break; + case(2): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_2, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_2; + break; + case(3): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_3, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_3; + break; + case(4): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_4, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_4; + break; + case(5): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_5, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_5; + break; + case(6): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_6, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_6; + break; + case(7): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_7, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_7; + break; + case(8): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_8, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_8; + break; + case(13): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_13, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_13; + break; + case(20): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_20, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_20; + break; + case(21): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_21, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_21; + break; + case(22): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_22, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_22; + break; + case(23): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_23, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_23; + break; + case(40): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_40, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_40; + break; + case(60): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_60, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_60; + break; + case(61): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_61, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_61; + break; + case(62): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_62, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_62; + break; + case(63): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_63, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_63; + break; + case(64): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_64, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_64; + break; + case(65): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_65, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_65; + break; + case(66): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_66, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_66; + break; + case(70): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_70, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_70; + break; + case(71): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_71, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_71; + break; + case(72): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_72, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_72; + break; + case(73): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_73, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_73; + break; + case(74): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_74, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_74; + break; + case(75): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_75, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_75; + break; + case(76): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_76, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_76; + break; + case(77): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_77, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_77; + break; + case(253): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_253, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_253; + break; + case(255): + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2_pnio_255, &u8ErrorCode2); + error_code2_vals = pn_io_error_code2_pnio_255; + break; + default: + /* don't know this u8ErrorCode1 for PNIO, use defaults */ + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2, &u8ErrorCode2); + expert_add_info_format(pinfo, sub_item, &ei_pn_io_error_code1, "Unknown ErrorCode1 0x%x (for ErrorDecode==PNIO)", u8ErrorCode1); + break; + } + break; + default: + dissect_dcerpc_uint8(tvb, offset + (2 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code1, &u8ErrorCode1); + if (u8ErrorDecode != 0) { + expert_add_info_format(pinfo, sub_item, &ei_pn_io_error_code1, "Unknown ErrorDecode 0x%x", u8ErrorDecode); + } + error_code1_vals = pn_io_error_code1; + + /* don't know this u8ErrorDecode, use defaults */ + dissect_dcerpc_uint8(tvb, offset + (3 ^ bytemask), pinfo, sub_tree, drep, + hf_pn_io_error_code2, &u8ErrorCode2); + if (u8ErrorDecode != 0) { + expert_add_info_format(pinfo, sub_item, &ei_pn_io_error_code2, "Unknown ErrorDecode 0x%x", u8ErrorDecode); + } + } + + offset += 4; + + if ((u8ErrorCode == 0) && (u8ErrorDecode == 0) && (u8ErrorCode1 == 0) && (u8ErrorCode2 == 0)) { + proto_item_append_text(sub_item, ": OK"); + col_append_str(pinfo->cinfo, COL_INFO, ", OK"); + } + else { + proto_item_append_text(sub_item, ": Error: \"%s\", \"%s\", \"%s\", \"%s\"", + val_to_str(u8ErrorCode, pn_io_error_code, "(0x%x)"), + val_to_str(u8ErrorDecode, pn_io_error_decode, "(0x%x)"), + val_to_str(u8ErrorCode1, error_code1_vals, "(0x%x)"), + val_to_str(u8ErrorCode2, error_code2_vals, "(0x%x)")); + col_append_fstr(pinfo->cinfo, COL_INFO, ", Error: \"%s\", \"%s\", \"%s\", \"%s\"", + val_to_str(u8ErrorCode, pn_io_error_code, "(0x%x)"), + val_to_str(u8ErrorDecode, pn_io_error_decode, "(0x%x)"), + val_to_str(u8ErrorCode1, error_code1_vals, "(0x%x)"), + val_to_str(u8ErrorCode2, error_code2_vals, "(0x%x)")); + } + proto_item_set_len(sub_item, offset - u32SubStart); + + return offset; +} + + + +/* append the given info text to item and column */ +void +pn_append_info(packet_info *pinfo, proto_item *dcp_item, const char *text) +{ + col_append_str(pinfo->cinfo, COL_INFO, text); + + proto_item_append_text(dcp_item, "%s", text); +} + +void pn_init_append_aruuid_frame_setup_list(e_guid_t aruuid, guint32 setup) { + + ARUUIDFrame* aruuid_frame; + + aruuid_frame = wmem_new0(wmem_file_scope(), ARUUIDFrame); + aruuid_frame->aruuid = aruuid; + aruuid_frame->setupframe = setup; + aruuid_frame->releaseframe = 0; + aruuid_frame->inputframe = 0; + aruuid_frame->outputframe = 0; + + wmem_list_append(aruuid_frame_setup_list, aruuid_frame); +} + +ARUUIDFrame* pn_find_aruuid_frame_setup(packet_info* pinfo) { + + wmem_list_frame_t* aruuid_frame; + ARUUIDFrame* current_aruuid_frame = NULL; + + if (aruuid_frame_setup_list != NULL) { + for (aruuid_frame = wmem_list_head(aruuid_frame_setup_list); aruuid_frame != NULL; aruuid_frame = wmem_list_frame_next(aruuid_frame)) { + current_aruuid_frame = (ARUUIDFrame*)wmem_list_frame_data(aruuid_frame); + if (current_aruuid_frame->setupframe == pinfo->num) { + break; + } + } + } + + return current_aruuid_frame; +} + +void pn_find_dcp_station_info(stationInfo* station_info, conversation_t* conversation) { + stationInfo* dcp_station_info = NULL; + /* search for DCP Station Info */ + dcp_station_info = (stationInfo*)conversation_get_proto_data(conversation, proto_pn_dcp); + if (dcp_station_info != NULL) { + if (dcp_station_info->typeofstation != NULL) { + if (station_info->typeofstation == NULL || strcmp(dcp_station_info->typeofstation, station_info->typeofstation) != 0) { + station_info->typeofstation = wmem_strdup(wmem_file_scope(), dcp_station_info->typeofstation); + } + } + if (dcp_station_info->nameofstation != NULL) { + if (station_info->nameofstation == NULL || strcmp(dcp_station_info->nameofstation, station_info->nameofstation) != 0) { + station_info->nameofstation = wmem_strdup(wmem_file_scope(), dcp_station_info->nameofstation); + } + } + if (dcp_station_info->u16Vendor_id != station_info->u16Vendor_id || dcp_station_info->u16Device_id != station_info->u16Device_id) { + station_info->u16Vendor_id = dcp_station_info->u16Vendor_id; + station_info->u16Device_id = dcp_station_info->u16Device_id; + } + } +} + + +void +init_pn (int proto) +{ + static hf_register_info hf[] = { + { &hf_pn_padding, + { "Padding", "pn.padding", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_undecoded_data, + { "Undecoded Data", "pn.undecoded", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_user_data, + { "User Data", "pn.user_data", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_user_bytes, + { "Substitute Data", "pn.user_bytes", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_frag_bytes, + { "Fragment Data", "pn.frag_bytes", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_malformed, + { "Malformed", "pn_rt.malformed", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_status, + { "Status", "pn_io.status", + FT_NONE, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code, + { "ErrorCode", "pn_io.error_code", + FT_UINT8, BASE_HEX, VALS(pn_io_error_code), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_decode, + { "ErrorDecode", "pn_io.error_decode", + FT_UINT8, BASE_HEX, VALS(pn_io_error_decode), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code1, + { "ErrorCode1", "pn_io.error_code1", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code1), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code1_pniorw, + { "ErrorCode1", "pn_io.error_code1", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code1_pniorw), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pniorw, + { "ErrorCode2 for PNIORW is user specified!", "pn_io.error_code2", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code1_pnio, + { "ErrorCode1", "pn_io.error_code1", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code1_pnio), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_1, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_1), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_2, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_2), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_3, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_3), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_4, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_4), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_5, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_5), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_6, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_6), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_7, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_7), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_8, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_8), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_13, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_13), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_20, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_20), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_21, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_21), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_22, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_22), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_23, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_23), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_40, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_40), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_60, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_60), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_61, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_61), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_62, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_62), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_63, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_63), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_64, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_64), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_65, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_65), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_66, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_66), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_70, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_70), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_71, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_71), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_72, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_72), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_73, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_73), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_74, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_74), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_75, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_75), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_76, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_76), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_77, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_77), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_253, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_253), 0x0, + NULL, HFILL } + }, + { &hf_pn_io_error_code2_pnio_255, + { "ErrorCode2", "pn_io.error_code2", + FT_UINT8, BASE_DEC, VALS(pn_io_error_code2_pnio_255), 0x0, + NULL, HFILL } + }, + + }; + + static gint *ett[] = { + &ett_pn_io_status + }; + + static ei_register_info ei[] = { + { &ei_pn_undecoded_data, { "pn.undecoded_data", PI_UNDECODED, PI_WARN, "Undecoded Data", EXPFILL }}, + { &ei_pn_io_error_code1, { "pn_io.error_code1.expert", PI_UNDECODED, PI_WARN, "Unknown ErrorCode1", EXPFILL }}, + { &ei_pn_io_error_code2, { "pn_io.error_code2.expert", PI_UNDECODED, PI_WARN, "Unknown ErrorDecode", EXPFILL } }, + + }; + + expert_module_t* expert_pn; + + + proto_register_field_array (proto, hf, array_length (hf)); + proto_register_subtree_array (ett, array_length (ett)); + expert_pn = expert_register_protocol(proto); + expert_register_field_array(expert_pn, ei, array_length(ei)); +} + +/* Read a string from an "xml" file, dropping xml comment blocks */ +char *pn_fgets(char *str, int n, FILE *stream, wmem_allocator_t *scope) +{ + const char XML_COMMENT_START[] = ""; + + char *retVal = fgets(str, n, stream); + if (retVal == NULL) { + /* No input, we're done */ + return retVal; + } + + /* Search for the XML begin comment marker */ + char *comment_start = strstr(str, XML_COMMENT_START); + char *common_start_end = comment_start + sizeof(XML_COMMENT_START) - 1; + if(comment_start == NULL) { + /* No comment start, we're done */ + return retVal; + } + + /* Terminate the input buffer at the comment start */ + *comment_start = '\0'; + size_t used_space = comment_start - str; + size_t remaining_space = n - used_space; + + /* Read more data looking for the comment end */ + char *comment_end = strstr(common_start_end, XML_COMMENT_END); + if (comment_end == NULL) { + // Not found in this line, read more lines until we do find it */ + char *temp = (char*)wmem_alloc(scope, MAX_LINE_LENGTH); + char *next_line = temp; + while((comment_end == NULL) && (next_line != NULL)) { + next_line = fgets(temp, MAX_LINE_LENGTH, stream); + if (next_line == NULL) { + /* No more data, exit now */ + break; + } + comment_end = strstr(next_line, XML_COMMENT_END); + } + } + + if (comment_end == NULL) { + /* We didn't find the comment end, return what we have */ + return retVal; + } + + /* We did find a comment end, skip past the comment */ + char *comment_end_end = comment_end + sizeof(XML_COMMENT_END) - 1; + + /* Check we have space left in the buffer to move the trailing bytes after the comment end */ + size_t remaining_bytes = strlen(comment_end_end) + 1; + if (remaining_bytes < remaining_space) { + (void) g_strlcat(str, comment_end_end, n); + } + else { + /* Seek the file back to the comment end so the next read picks it up */ + fseek(stream, -(long)(remaining_bytes), SEEK_CUR); + } + + return retVal; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/profinet/packet-pn.h b/plugins/epan/profinet/packet-pn.h new file mode 100644 index 00000000..f2c0743d --- /dev/null +++ b/plugins/epan/profinet/packet-pn.h @@ -0,0 +1,204 @@ +/* packet-pn.h + * Common functions for other PROFINET protocols like DCP, MRP, ... + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * Cyclic PNIO RTC1 Data Dissection: + * + * Added new structures to packet-pn.h to transfer the gained data of + * packet-pn-dcp.c and packet-dcerpc-pn-io.c to packet-pn-rtc-one.c for + * detailled dissection of cyclic PNIO RTC1 dataframes. + * + */ + +#define FRAME_ID_DCP_HELLO 0xfefc +#define FRAME_ID_DCP_GETORSET 0xfefd +#define FRAME_ID_DCP_IDENT_REQ 0xfefe +#define FRAME_ID_DCP_IDENT_RES 0xfeff + + +/* ---- Structures for pnio_rtc1 ---- */ +extern int proto_pn_dcp; +extern int proto_pn_io_apdu_status; +extern int proto_pn_io_time_aware_status; + +extern gboolean pnio_ps_selection; /* given by pnio preferences */ + +/* Structure for general station information */ +typedef struct tagStationInfo { + /* general information */ + gchar *typeofstation; + gchar *nameofstation; + guint16 u16Vendor_id; + guint16 u16Device_id; + /* frame structure */ + guint16 ioDataObjectNr_in; + guint16 ioDataObjectNr_out; + guint16 iocsNr_in; + guint16 iocsNr_out; + /* GSDfile station information */ + gboolean gsdFound; + gboolean gsdPathLength; + gchar *gsdLocation; + /* IOCS object data */ + wmem_list_t *iocs_data_in; + wmem_list_t *iocs_data_out; + /* IOData object data */ + wmem_list_t *ioobject_data_in; + wmem_list_t *ioobject_data_out; + /* Different ModuleIdentnumber */ + wmem_list_t *diff_module; +} stationInfo; + +typedef struct tagApduStatusSwitch +{ + gboolean isRedundancyActive; + address dl_dst; + address dl_src; +}apduStatusSwitch; + +/* Structure for IOCS Frames */ +typedef struct tagIocsObject { + guint16 slotNr; + guint16 subSlotNr; + guint16 frameOffset; +} iocsObject; + +/* Structure for IO Data Objects */ +typedef struct tagIoDataObject { + guint16 slotNr; + guint16 subSlotNr; + guint32 api; + guint32 moduleIdentNr; + guint32 subModuleIdentNr; + guint16 frameOffset; + guint16 length; + guint16 amountInGSDML; + guint32 fParameterIndexNr; + guint16 f_par_crc1; + guint16 f_src_adr; + guint16 f_dest_adr; + gboolean f_crc_seed; + guint8 f_crc_len; + address srcAddr; + address dstAddr; + gboolean profisafeSupported; + gboolean discardIOXS; + gchar *moduleNameStr; + tvbuff_t *tvb_slot; + tvbuff_t *tvb_subslot; + /* Status- or Controlbyte data*/ + guint8 last_sb_cb; + guint8 lastToggleBit; +} ioDataObject; + +/* Structure for Modules with different ModuleIdentnumber */ +typedef struct tagModuleDiffInfo { + guint16 slotNr; + guint32 modulID; +} moduleDiffInfo; + +typedef struct tagARUUIDFrame { + e_guid_t aruuid; + guint32 setupframe; + guint32 releaseframe; + guint16 outputframe; + guint16 inputframe; +} ARUUIDFrame; + +extern wmem_list_t *aruuid_frame_setup_list; + +extern void init_pn(int proto); +extern void init_pn_io_rtc1(int proto); +extern void init_pn_rsi(int proto); +extern void pn_rsi_reassemble_init(void); + +extern void init_pnio_rtc1_station(stationInfo *station_info); + +extern int dissect_pn_uint8(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, int hfindex, guint8 *pdata); + +extern int dissect_pn_uint16_ret_item(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_, + proto_tree *tree, int hfindex, guint16 *pdata, proto_item ** new_item); +extern int dissect_pn_uint16(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, int hfindex, guint16 *pdata); + +extern int dissect_pn_int16(tvbuff_t *tvb, gint offset, packet_info *pinfo, + proto_tree *tree, int hfindex, gint16 *pdata); + +extern int dissect_pn_oid(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int hfindex, guint32 *pdata); + +extern int dissect_pn_mac(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int hfindex, guint8 *pdata); + +extern int dissect_pn_ipv4(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int hfindex, guint32 *pdata); + +extern int dissect_pn_uuid(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int hfindex, e_guid_t *uuid); + +extern int dissect_pn_undecoded(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint32 length); + +extern int dissect_pn_user_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 length, const char *text); + +extern int dissect_pn_pa_profile_data(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 length, const char *text); + +extern int dissect_blocks(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, guint8 *drep); + +#define PDU_TYPE_REQ 0x05 +#define PDU_TYPE_RSP 0x06 + +extern int dissect_rsi_blocks(tvbuff_t* tvb, int offset, packet_info* pinfo, proto_tree* tree, guint8* drep, guint32 u32FOpnumOffsetOpnum, int type); + +#define SUBST_DATA 1 +#define FRAG_DATA 2 + +extern int dissect_pn_user_data_bytes(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, + proto_tree *tree, guint32 length, int iSelect); + +extern int dissect_pn_malformed(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint32 length); + +extern int dissect_pn_padding(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, int length); + +extern int dissect_pn_align4(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree); + +extern int dissect_PNIO_status(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep); + +extern int dissect_PNIO_C_SDU_RTC1(tvbuff_t* tvb, int offset, packet_info* pinfo, + proto_tree* tree, guint8* drep _U_, guint16 frameid); + +extern int dissect_PNIO_RSI(tvbuff_t *tvb, int offset, packet_info *pinfo, + proto_tree *tree, guint8 *drep); + +extern int dissect_PDRsiInstances_block(tvbuff_t *tvb, int offset, + packet_info *pinfo, proto_tree *tree, proto_item *item _U_, guint8 *drep, guint8 u8BlockVersionHigh, guint8 u8BlockVersionLow); + +extern void pn_append_info(packet_info *pinfo, proto_item *dcp_item, const char *text); + +extern void pn_init_append_aruuid_frame_setup_list(e_guid_t aruuid, guint32 setup); + +extern ARUUIDFrame* pn_find_aruuid_frame_setup(packet_info* pinfo); + +extern void pn_find_dcp_station_info(stationInfo* station_info, conversation_t* conversation); + +extern gboolean dissect_CSF_SDU_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data); + +#define MAX_LINE_LENGTH 1024 /* used for fgets() */ + +/* Read a string from an "xml" file, dropping xml comment blocks */ +#include +extern char *pn_fgets(char *str, int n, FILE *stream, wmem_allocator_t *scope); diff --git a/plugins/epan/stats_tree/AUTHORS b/plugins/epan/stats_tree/AUTHORS new file mode 100644 index 00000000..e37df0dd --- /dev/null +++ b/plugins/epan/stats_tree/AUTHORS @@ -0,0 +1,3 @@ +Author: +Luis E. Garcia Ontanon + diff --git a/plugins/epan/stats_tree/CMakeLists.txt b/plugins/epan/stats_tree/CMakeLists.txt new file mode 100644 index 00000000..7986d870 --- /dev/null +++ b/plugins/epan/stats_tree/CMakeLists.txt @@ -0,0 +1,62 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(stats_tree 0 0 1 0) + +set(TAP_SRC + pinfo_stats_tree.c +) + +set(PLUGIN_FILES + plugin.c + ${TAP_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_tap + ${TAP_SRC} +) + +add_wireshark_plugin_library(stats_tree epan) + +target_link_libraries(stats_tree epan) + +install_plugin(stats_tree epan) + +file(GLOB TAP_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + stats_tree + SWITCHES + SOURCES + ${TAP_SRC} + ${TAP_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/stats_tree/pinfo_stats_tree.c b/plugins/epan/stats_tree/pinfo_stats_tree.c new file mode 100644 index 00000000..fd2a97d8 --- /dev/null +++ b/plugins/epan/stats_tree/pinfo_stats_tree.c @@ -0,0 +1,371 @@ +/* pinfo_stats_tree.c + * Stats tree for ethernet frames + * + * (c) 2005, Luis E. G. Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "pinfo_stats_tree.h" + +/*------------------------------------- + * UAT for Packet Lengths + *------------------------------------- + */ +typedef struct { + range_t *packet_range; +} uat_plen_record_t; + +static range_t default_range[10] = { + {1, {{0, 19}}}, + {1, {{20, 39}}}, + {1, {{40, 79}}}, + {1, {{80, 159}}}, + {1, {{160, 319}}}, + {1, {{320, 639}}}, + {1, {{640, 1279}}}, + {1, {{1280, 2559}}}, + {1, {{2560, 5119}}}, + {1, {{5120, 0xFFFFFFFF}}} +}; +static uat_plen_record_t *uat_plen_records = NULL; +static uat_t *plen_uat = NULL; +static guint num_plen_uat = 0; + +void register_tap_listener_pinfo_stat_tree(void); + +static void *uat_plen_record_copy_cb(void *n, const void *o, size_t siz _U_) { + const uat_plen_record_t *r = (const uat_plen_record_t *)o; + uat_plen_record_t *rn = (uat_plen_record_t *)n; + + if (r->packet_range) + rn->packet_range = range_copy(NULL, r->packet_range); + + return n; +} + +static bool +uat_plen_record_update_cb(void *r, char **err) +{ + uat_plen_record_t *rec = (uat_plen_record_t*)r; + if (rec->packet_range->nranges < 1) { + *err = g_strdup("Invalid range string"); + return FALSE; + } + + *err = NULL; + return TRUE; +} + +static void uat_plen_record_free_cb(void*r) { + uat_plen_record_t *record = (uat_plen_record_t*)r; + + if (record->packet_range) + wmem_free(NULL, record->packet_range); +} + +static void uat_plen_record_post_update_cb(void) { + guint i, num_default; + uat_plen_record_t rec; + + /* If there are no records, create default list */ + if (num_plen_uat == 0) { + num_default = sizeof(default_range)/sizeof(range_t); + + /* default values for packet lengths */ + for (i = 0; i < num_default; i++) + { + rec.packet_range = &default_range[i]; + uat_add_record(plen_uat, &rec, TRUE); + } + } +} + +UAT_RANGE_CB_DEF(uat_plen_records, packet_range, uat_plen_record_t) + +/* ip host stats_tree -- basic test */ +static int st_node_ipv4 = -1; +static int st_node_ipv6 = -1; +static const gchar *st_str_ipv4 = "IPv4 Statistics/All Addresses"; +static const gchar *st_str_ipv6 = "IPv6 Statistics/All Addresses"; + +static void ipv4_hosts_stats_tree_init(stats_tree *st) { + st_node_ipv4 = stats_tree_create_node(st, st_str_ipv4, 0, STAT_DT_INT, TRUE); +} + +static void ipv6_hosts_stats_tree_init(stats_tree *st) { + st_node_ipv6 = stats_tree_create_node(st, st_str_ipv6, 0, STAT_DT_INT, TRUE); +} + +static tap_packet_status ip_hosts_stats_tree_packet(stats_tree *st, packet_info *pinfo, int st_node, const gchar *st_str) { + tick_stat_node(st, st_str, 0, FALSE); + tick_stat_node(st, address_to_str(pinfo->pool, &pinfo->net_src), st_node, FALSE); + tick_stat_node(st, address_to_str(pinfo->pool, &pinfo->net_dst), st_node, FALSE); + return TAP_PACKET_REDRAW; +} + +static tap_packet_status ipv4_hosts_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + return ip_hosts_stats_tree_packet(st, pinfo, st_node_ipv4, st_str_ipv4); +} + +static tap_packet_status ipv6_hosts_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + return ip_hosts_stats_tree_packet(st, pinfo, st_node_ipv6, st_str_ipv6); +} + +/* ip host stats_tree -- separate source and dest, test stats_tree flags */ +static int st_node_ipv4_src = -1; +static int st_node_ipv4_dst = -1; +static int st_node_ipv6_src = -1; +static int st_node_ipv6_dst = -1; +static const gchar *st_str_ipv4_srcdst = "IPv4 Statistics/Source and Destination Addresses"; +static const gchar *st_str_ipv6_srcdst = "IPv6 Statistics/Source and Destination Addresses"; +static const gchar *st_str_ipv4_src = "Source IPv4 Addresses"; +static const gchar *st_str_ipv4_dst = "Destination IPv4 Addresses"; +static const gchar *st_str_ipv6_src = "Source IPv6 Addresses"; +static const gchar *st_str_ipv6_dst = "Destination IPv6 Addresses"; + +static void ip_srcdst_stats_tree_init(stats_tree *st, + const gchar *st_str_src, int *st_node_src_ptr, + const gchar *st_str_dst, int *st_node_dst_ptr) { + /* create one tree branch for source */ + *st_node_src_ptr = stats_tree_create_node(st, st_str_src, 0, STAT_DT_INT, TRUE); + /* set flag so this branch will always be sorted to top of tree */ + stat_node_set_flags(st, st_str_src, 0, FALSE, ST_FLG_SORT_TOP); + /* creat another top level node for destination branch */ + *st_node_dst_ptr = stats_tree_create_node(st, st_str_dst, 0, STAT_DT_INT, TRUE); + /* set flag so this branch will not be expanded by default */ + stat_node_set_flags(st, st_str_dst, 0, FALSE, ST_FLG_DEF_NOEXPAND); +} + +static void ipv4_srcdst_stats_tree_init(stats_tree *st) { + ip_srcdst_stats_tree_init(st, st_str_ipv4_src, &st_node_ipv4_src, st_str_ipv4_dst, &st_node_ipv4_dst); +} + +static void ipv6_srcdst_stats_tree_init(stats_tree *st) { + ip_srcdst_stats_tree_init(st, st_str_ipv6_src, &st_node_ipv6_src, st_str_ipv6_dst, &st_node_ipv6_dst); +} + +static tap_packet_status ip_srcdst_stats_tree_packet(stats_tree *st, + packet_info *pinfo, + int st_node_src, + const gchar *st_str_src, + int st_node_dst, + const gchar *st_str_dst) { + /* update source branch */ + tick_stat_node(st, st_str_src, 0, FALSE); + tick_stat_node(st, address_to_str(pinfo->pool, &pinfo->net_src), st_node_src, FALSE); + /* update destination branch */ + tick_stat_node(st, st_str_dst, 0, FALSE); + tick_stat_node(st, address_to_str(pinfo->pool, &pinfo->net_dst), st_node_dst, FALSE); + return TAP_PACKET_REDRAW; +} + +static tap_packet_status ipv4_srcdst_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + return ip_srcdst_stats_tree_packet(st, pinfo, st_node_ipv4_src, st_str_ipv4_src, st_node_ipv4_dst, st_str_ipv4_dst); +} + +static tap_packet_status ipv6_srcdst_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + return ip_srcdst_stats_tree_packet(st, pinfo, st_node_ipv6_src, st_str_ipv6_src, st_node_ipv6_dst, st_str_ipv6_dst); +} + +/* packet type stats_tree -- test pivot node */ +static int st_node_ipv4_ptype = -1; +static int st_node_ipv6_ptype = -1; +static const gchar *st_str_ipv4_ptype = "IPv4 Statistics/IP Protocol Types"; +static const gchar *st_str_ipv6_ptype = "IPv6 Statistics/IP Protocol Types"; + +static void ipv4_ptype_stats_tree_init(stats_tree *st) { + st_node_ipv4_ptype = stats_tree_create_pivot(st, st_str_ipv4_ptype, 0); +} + +static void ipv6_ptype_stats_tree_init(stats_tree *st) { + st_node_ipv6_ptype = stats_tree_create_pivot(st, st_str_ipv6_ptype, 0); +} + +static tap_packet_status ipv4_ptype_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + stats_tree_tick_pivot(st, st_node_ipv4_ptype, port_type_to_str(pinfo->ptype)); + return TAP_PACKET_REDRAW; +} + +static tap_packet_status ipv6_ptype_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + stats_tree_tick_pivot(st, st_node_ipv6_ptype, port_type_to_str(pinfo->ptype)); + return TAP_PACKET_REDRAW; +} + +/* a tree example + - IP + - PROTO + - PORT + +*/ +static int st_node_ipv4_dsts = -1; +static int st_node_ipv6_dsts = -1; +static const gchar *st_str_ipv4_dsts = "IPv4 Statistics/Destinations and Ports"; +static const gchar *st_str_ipv6_dsts = "IPv6 Statistics/Destinations and Ports"; + +static void ipv4_dsts_stats_tree_init(stats_tree *st) { + st_node_ipv4_dsts = stats_tree_create_node(st, st_str_ipv4_dsts, 0, STAT_DT_INT, TRUE); +} + +static void ipv6_dsts_stats_tree_init(stats_tree *st) { + st_node_ipv6_dsts = stats_tree_create_node(st, st_str_ipv6_dsts, 0, STAT_DT_INT, TRUE); +} + +static tap_packet_status dsts_stats_tree_packet(stats_tree *st, packet_info *pinfo, int st_node, const gchar *st_str) { + static gchar str[128]; + int ip_dst_node; + int protocol_node; + + tick_stat_node(st, st_str, 0, FALSE); + ip_dst_node = tick_stat_node(st, address_to_str(pinfo->pool, &pinfo->net_dst), st_node, TRUE); + protocol_node = tick_stat_node(st, port_type_to_str(pinfo->ptype), ip_dst_node, TRUE); + snprintf(str, sizeof(str) - 1, "%u", pinfo->destport); + tick_stat_node(st, str, protocol_node, TRUE); + return TAP_PACKET_REDRAW; +} + +static tap_packet_status ipv4_dsts_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + return dsts_stats_tree_packet(st, pinfo, st_node_ipv4_dsts, st_str_ipv4_dsts); +} + +static tap_packet_status ipv6_dsts_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + return dsts_stats_tree_packet(st, pinfo, st_node_ipv6_dsts, st_str_ipv6_dsts); +} + +static int st_node_ipv4_src_ttls = -1; +static int st_node_ipv6_src_ttls = -1; +static const gchar* st_str_ipv4_src_ttls = "IPv4 Statistics/Source TTLs"; +static const gchar* st_str_ipv6_src_ttls = "IPv6 Statistics/Source Hop Limits"; + +static void ipv4_src_ttl_stats_tree_init(stats_tree* st) { + st_node_ipv4_src_ttls = stats_tree_create_node(st, st_str_ipv4_src_ttls, 0, STAT_DT_INT, TRUE); +} + +static void ipv6_src_ttl_stats_tree_init(stats_tree* st) { + st_node_ipv6_src_ttls = stats_tree_create_node(st, st_str_ipv6_src_ttls, 0, STAT_DT_INT, TRUE); +} + +static tap_packet_status src_ttl_stats_tree_packet(stats_tree* st, packet_info* pinfo, int st_node, const char* st_str, uint8_t ttl) { + static gchar str[128]; + int ip_src_node; + int ttl_node; + + tick_stat_node(st, st_str, 0, FALSE); + ip_src_node = tick_stat_node(st, address_to_str(pinfo->pool, &pinfo->net_src), st_node, TRUE); + snprintf(str, sizeof(str) - 1, "%u", ttl); + ttl_node = tick_stat_node(st, str, ip_src_node, TRUE); + tick_stat_node(st, address_to_str(pinfo->pool, &pinfo->net_dst), ttl_node, TRUE); + return TAP_PACKET_REDRAW; +} + +static tap_packet_status ipv4_src_ttl_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_) { + ws_ip4* iph = (ws_ip4*)p; + + return src_ttl_stats_tree_packet(st, pinfo, st_node_ipv4_src_ttls, st_str_ipv4_src_ttls, iph->ip_ttl); +} + +static tap_packet_status ipv6_src_ttl_stats_tree_packet(stats_tree* st, packet_info* pinfo, epan_dissect_t* edt _U_, const void* p, tap_flags_t flags _U_) { + ws_ip6* iph = (ws_ip6*)p; + + return src_ttl_stats_tree_packet(st, pinfo, st_node_ipv6_src_ttls, st_str_ipv6_src_ttls, iph->ip6_hop); +} + +/* packet length stats_tree -- test range node */ +static int st_node_plen = -1; +static const gchar *st_str_plen = "Packet Lengths"; + +static void plen_stats_tree_init(stats_tree *st) { + guint i; + char **str_range_array = (char **)wmem_alloc(NULL, num_plen_uat*sizeof(char*)); + + /* Convert the ranges to strings for the stats tree API */ + for (i = 0; i < num_plen_uat - 1; i++) { + str_range_array[i] = range_convert_range(NULL, uat_plen_records[i].packet_range); + } + str_range_array[num_plen_uat - 1] = ws_strdup_printf("%u and greater", + uat_plen_records[num_plen_uat - 1].packet_range->ranges[0].low); + + st_node_plen = stats_tree_create_range_node_string(st, st_str_plen, 0, num_plen_uat, str_range_array); + for (i = 0; i < num_plen_uat; i++) { + wmem_free(NULL, str_range_array[i]); + } +} + +static tap_packet_status plen_stats_tree_packet(stats_tree *st, packet_info *pinfo, epan_dissect_t *edt _U_, const void *p _U_, tap_flags_t flags _U_) { + tick_stat_node(st, st_str_plen, 0, FALSE); + + stats_tree_tick_range(st, st_str_plen, 0, pinfo->fd->pkt_len); + + return TAP_PACKET_REDRAW; +} + +/* register all pinfo trees */ +void register_tap_listener_pinfo_stat_tree(void) +{ + module_t *stat_module; + + static uat_field_t plen_uat_flds[] = { + UAT_FLD_RANGE(uat_plen_records, packet_range, "Packet Range", 0xFFFFFFFF, "Range of packet sizes to count"), + UAT_END_FIELDS + }; + + stats_tree_register_plugin("ip", "ip_hosts", st_str_ipv4, 0, ipv4_hosts_stats_tree_packet, ipv4_hosts_stats_tree_init, NULL ); + stats_tree_register_plugin("ip", "ip_srcdst", st_str_ipv4_srcdst, 0, ipv4_srcdst_stats_tree_packet, ipv4_srcdst_stats_tree_init, NULL ); + stats_tree_register_plugin("ip", "ptype", st_str_ipv4_ptype, 0, ipv4_ptype_stats_tree_packet, ipv4_ptype_stats_tree_init, NULL ); + stats_tree_register_plugin("ip", "dests", st_str_ipv4_dsts, 0, ipv4_dsts_stats_tree_packet, ipv4_dsts_stats_tree_init, NULL ); + stats_tree_register_plugin("ip", "ip_ttl", st_str_ipv4_src_ttls, 0, ipv4_src_ttl_stats_tree_packet, ipv4_src_ttl_stats_tree_init, NULL); + + stats_tree_register_plugin("ipv6", "ipv6_hosts", st_str_ipv6, 0, ipv6_hosts_stats_tree_packet, ipv6_hosts_stats_tree_init, NULL ); + stats_tree_register_plugin("ipv6", "ipv6_srcdst", st_str_ipv6_srcdst, 0, ipv6_srcdst_stats_tree_packet, ipv6_srcdst_stats_tree_init, NULL ); + stats_tree_register_plugin("ipv6", "ipv6_ptype", st_str_ipv6_ptype, 0, ipv6_ptype_stats_tree_packet, ipv6_ptype_stats_tree_init, NULL ); + stats_tree_register_plugin("ipv6", "ipv6_dests", st_str_ipv6_dsts, 0, ipv6_dsts_stats_tree_packet, ipv6_dsts_stats_tree_init, NULL ); + stats_tree_register_plugin("ipv6", "ipv6_hop", st_str_ipv6_src_ttls, 0, ipv6_src_ttl_stats_tree_packet, ipv6_src_ttl_stats_tree_init, NULL); + + + stats_tree_register_with_group("frame", "plen", st_str_plen, 0, plen_stats_tree_packet, plen_stats_tree_init, NULL, REGISTER_STAT_GROUP_GENERIC); + + stat_module = prefs_register_stat("stat_tree", "Stats Tree", "Stats Tree", NULL); + + plen_uat = uat_new("Packet Lengths", + sizeof(uat_plen_record_t), /* record size */ + "packet_lengths", /* filename */ + TRUE, /* from_profile */ + &uat_plen_records, /* data_ptr */ + &num_plen_uat, /* numitems_ptr */ + 0, /* not a dissector, so affects neither dissection nor fields */ + NULL, /* help */ + uat_plen_record_copy_cb, /* copy callback */ + uat_plen_record_update_cb, /* update callback */ + uat_plen_record_free_cb, /* free callback */ + uat_plen_record_post_update_cb, /* post update callback */ + NULL, /* reset callback */ + plen_uat_flds); /* UAT field definitions */ + + prefs_register_uat_preference(stat_module, "packet_lengths", + "Packet Lengths", "Delineated packet sizes to count", plen_uat); +} + +/* + * 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: + */ diff --git a/plugins/epan/stats_tree/pinfo_stats_tree.h b/plugins/epan/stats_tree/pinfo_stats_tree.h new file mode 100644 index 00000000..48e834e1 --- /dev/null +++ b/plugins/epan/stats_tree/pinfo_stats_tree.h @@ -0,0 +1,13 @@ +/* pinfo_stats_tree.h + * Stats tree for ethernet frames + * + * (c) 2005, Luis E. G. Ontanon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +extern void register_pinfo_stat_trees(void); diff --git a/plugins/epan/transum/AUTHORS b/plugins/epan/transum/AUTHORS new file mode 100644 index 00000000..109c3fcd --- /dev/null +++ b/plugins/epan/transum/AUTHORS @@ -0,0 +1,2 @@ +Author : +Paul Offord diff --git a/plugins/epan/transum/CMakeLists.txt b/plugins/epan/transum/CMakeLists.txt new file mode 100644 index 00000000..d26d4e46 --- /dev/null +++ b/plugins/epan/transum/CMakeLists.txt @@ -0,0 +1,72 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(transum 2 0 4 0) + +set(DISSECTOR_SRC + packet-transum.c +) + +set(DISSECTOR_SUPPORT_SRC + decoders.c + extractors.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +add_wireshark_plugin_library(transum epan) + +target_link_libraries(transum epan) + +install_plugin(transum epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + transum + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/transum/README b/plugins/epan/transum/README new file mode 100644 index 00000000..876f3f70 --- /dev/null +++ b/plugins/epan/transum/README @@ -0,0 +1,6 @@ +Advance7 has released under GPL this plugin +for Wireshark. It produces detailed response +time information based on the RTE model. + +Advance7 can be found at https://www.advance7.com +The author is Paul Offord diff --git a/plugins/epan/transum/decoders.c b/plugins/epan/transum/decoders.c new file mode 100644 index 00000000..c430f588 --- /dev/null +++ b/plugins/epan/transum/decoders.c @@ -0,0 +1,335 @@ +/* decoders.c + * Routines for the TRANSUM response time analyzer post-dissector + * By Paul Offord + * Copyright 2016 Advance Seven Limited + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include +#include +#include +#include "packet-transum.h" +#include "preferences.h" +#include "extractors.h" +#include "decoders.h" + +extern TSUM_PREFERENCES preferences; + + +/* Returns the number of sub-packets of interest */ +int decode_syn(packet_info *pinfo _U_, proto_tree *tree _U_, PKT_INFO* pkt_info) +{ + if (pkt_info->tcp_flags_ack) + pkt_info->rrpd.c2s = FALSE; + else + { + pkt_info->rrpd.c2s = TRUE; + add_detected_tcp_svc(pkt_info->dstport); + } + + pkt_info->rrpd.session_id = 1; /* Fake session ID */ + pkt_info->rrpd.msg_id = 1; /* Fake message ID */ + pkt_info->rrpd.decode_based = TRUE; + pkt_info->rrpd.calculation = RTE_CALC_SYN; + pkt_info->pkt_of_interest = TRUE; + + return 1; +} + +/* + This function sets basic information in the sub_packet entry. + Because we don't expect multiple DCE-RPC messages in a single packet + we only use single PKT_INFO + + Returns the number of sub-packets of interest, which in this case is always 1. + */ +int decode_dcerpc(packet_info *pinfo _U_, proto_tree *tree, PKT_INFO* pkt_info) +{ + guint32 field_uint[MAX_RETURNED_ELEMENTS]; /* An extracted field array for unsigned integers */ + size_t field_value_count; /* How many entries are there in the extracted field array */ + guint32 dcerpc_cn_ctx_id = 0; + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_DCERPC_VER].hf, field_uint, &field_value_count)) + { + if (field_value_count) + pkt_info->dcerpc_ver = field_uint[0]; + } + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_DCERPC_PKT_TYPE].hf, field_uint, &field_value_count)) + { + if (field_value_count) + pkt_info->dcerpc_pkt_type = field_uint[0]; + } + + if (field_value_count) + { + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_DCERPC_CN_CTX_ID].hf, field_uint, &field_value_count)) + { + if (field_value_count) + dcerpc_cn_ctx_id = field_uint[0]; + } + + if (is_dcerpc_context_zero(pkt_info->dcerpc_pkt_type)) + { /* This is needed to overcome an apparent Wireshark bug + found in the Lua code - is this still true in C? */ + pkt_info->rrpd.session_id = 1; + } + else + { + if (dcerpc_cn_ctx_id) + pkt_info->rrpd.session_id = dcerpc_cn_ctx_id; + else + pkt_info->rrpd.session_id = 1; + } + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_DCERPC_CN_CALL_ID].hf, field_uint, &field_value_count)) + { + if (field_value_count) + pkt_info->rrpd.msg_id = field_uint[0]; + } + } + else + { + /* + we don't have header information and so by setting the session_id and msg_id to zero + the rrpd functions will either create a new rrpd_list (or temp_rsp_rrpd_list) entry + or update the last entry for this ip_proto:stream_no. + */ + pkt_info->rrpd.session_id = 0; + pkt_info->rrpd.msg_id = 0; + } + + + if (is_dcerpc_req_pkt_type(pkt_info->dcerpc_pkt_type)) + { + pkt_info->rrpd.c2s = TRUE; + wmem_map_insert(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport), GUINT_TO_POINTER(RTE_CALC_DCERPC)); /* make sure we have this DCE-RPC service port set */ + } + else + { + pkt_info->rrpd.c2s = FALSE; + wmem_map_insert(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->srcport), GUINT_TO_POINTER(RTE_CALC_DCERPC)); /* make sure we have this DCE-RPC service port set */ + } + + pkt_info->rrpd.decode_based = TRUE; + pkt_info->rrpd.calculation = RTE_CALC_DCERPC; + pkt_info->pkt_of_interest = TRUE; + + return 1; +} + +/* Returns the number of sub-packets of interest */ +int decode_smb(packet_info *pinfo _U_, proto_tree *tree, PKT_INFO* pkt_info, PKT_INFO* subpackets) +{ + guint32 field_uint[MAX_RETURNED_ELEMENTS]; /* An extracted field array for unsigned integers */ + size_t field_value_count; /* How many entries are there in the extracted field array */ + + guint64 ses_id[MAX_RETURNED_ELEMENTS]; + size_t ses_id_count; + guint64 msg_id[MAX_RETURNED_ELEMENTS]; + size_t msg_id_count; + + /* set the direction information */ + if (pkt_info->dstport == 445) + pkt_info->rrpd.c2s = TRUE; + else + pkt_info->rrpd.c2s = FALSE; + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_SMB_MID].hf, field_uint, &field_value_count)) + { + if (field_value_count) + { + pkt_info->rrpd.calculation = RTE_CALC_SMB1; + pkt_info->pkt_of_interest = FALSE; /* can't process SMB1 at the moment */ + return 0; + } + } + /* Default in case we don't have header information */ + pkt_info->rrpd.session_id = 0; + pkt_info->rrpd.msg_id = 0; + pkt_info->rrpd.decode_based = TRUE; + pkt_info->rrpd.calculation = RTE_CALC_SMB2; + pkt_info->pkt_of_interest = TRUE; + + extract_ui64(tree, hf_of_interest[HF_INTEREST_SMB2_MSG_ID].hf, msg_id, &msg_id_count); + if (msg_id_count) /* test for header information */ + { + extract_ui64(tree, hf_of_interest[HF_INTEREST_SMB2_SES_ID].hf, ses_id, &ses_id_count); + + for (size_t i = 0; (i < msg_id_count) && (i < MAX_SUBPKTS_PER_PACKET); i++) + { + subpackets[i].rrpd.c2s = pkt_info->rrpd.c2s; + subpackets[i].rrpd.ip_proto = pkt_info->rrpd.ip_proto; + subpackets[i].rrpd.stream_no = pkt_info->rrpd.stream_no; + + subpackets[i].rrpd.session_id = ses_id[i]; + subpackets[i].rrpd.msg_id = msg_id[i]; + + subpackets[i].rrpd.decode_based = TRUE; + subpackets[i].rrpd.calculation = RTE_CALC_SMB2; + subpackets[i].pkt_of_interest = TRUE; + } + return (int)msg_id_count; + } + + return 1; +} + +/* Returns the number of sub-packets of interest */ +int decode_gtcp(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info) +{ + guint32 field_uint[MAX_RETURNED_ELEMENTS]; /* An extracted field array for unsigned integers */ + gboolean field_bool[MAX_RETURNED_ELEMENTS]; /* An extracted field array for unsigned integers */ + size_t field_value_count; /* How many entries are there in the extracted field array */ + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_TCP_STREAM].hf, field_uint, &field_value_count)) { + if (field_value_count) + pkt_info->rrpd.stream_no = field_uint[0]; + } + + pkt_info->srcport = pinfo->srcport; + pkt_info->dstport = pinfo->destport; + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_TCP_LEN].hf, field_uint, &field_value_count)) { + if (field_value_count) + pkt_info->len = field_uint[0]; + } + + if (!extract_bool(tree, hf_of_interest[HF_INTEREST_TCP_FLAGS_SYN].hf, field_bool, &field_value_count)) { + if (field_value_count) + pkt_info->tcp_flags_syn = field_bool[0]; + } + + if (!extract_bool(tree, hf_of_interest[HF_INTEREST_TCP_FLAGS_ACK].hf, field_bool, &field_value_count)) { + if (field_value_count) + pkt_info->tcp_flags_ack = field_bool[0]; + } + + if (!extract_bool(tree, hf_of_interest[HF_INTEREST_TCP_FLAGS_RESET].hf, field_bool, &field_value_count)) { + if (field_value_count) + pkt_info->tcp_flags_reset = field_bool[0]; + } + + /* + * This is an expert info, not a field with a value, so it's either + * present or not; if present, it's a retransmission. + */ + if (!extract_instance_count(tree, hf_of_interest[HF_INTEREST_TCP_RETRAN].hf, &field_value_count)) { + if (field_value_count) + pkt_info->tcp_retran = TRUE; + else + pkt_info->tcp_retran = FALSE; + } + + /* + * Another expert info. + */ + if (!extract_instance_count(tree, hf_of_interest[HF_INTEREST_TCP_KEEP_ALIVE].hf, &field_value_count)) { + if (field_value_count) + pkt_info->tcp_retran = TRUE; + else + pkt_info->tcp_retran = FALSE; + } + + /* we use the SSL Content Type to detect SSL Alerts */ + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_SSL_CONTENT_TYPE].hf, field_uint, &field_value_count)) + { + if (field_value_count) + pkt_info->ssl_content_type = field_uint[0]; + else + pkt_info->ssl_content_type = 0; + } + + if (wmem_map_lookup(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport)) != NULL || + wmem_map_lookup(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->srcport)) != NULL) + { + if (wmem_map_lookup(preferences.tcp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport)) != NULL) + pkt_info->rrpd.c2s = TRUE; + + pkt_info->rrpd.is_retrans = pkt_info->tcp_retran; + pkt_info->rrpd.session_id = 0; + pkt_info->rrpd.msg_id = 0; + pkt_info->rrpd.calculation = RTE_CALC_GTCP; + pkt_info->rrpd.decode_based = FALSE; + if (pkt_info->len > 0) + pkt_info->pkt_of_interest = TRUE; + + return 1; + } + + return 0; +} + +/* Returns the number of sub-packets of interest */ +int decode_dns(packet_info *pinfo _U_, proto_tree *tree, PKT_INFO* pkt_info) +{ + guint32 field_uint[MAX_RETURNED_ELEMENTS]; /* An extracted field array for unsigned integers */ + size_t field_value_count; /* How many entries are there in the extracted field array */ + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_DNS_ID].hf, field_uint, &field_value_count)) { + if (field_value_count) + pkt_info->rrpd.msg_id = field_uint[0]; + } + + pkt_info->rrpd.session_id = 1; + pkt_info->rrpd.decode_based = TRUE; + pkt_info->rrpd.calculation = RTE_CALC_DNS; + pkt_info->pkt_of_interest = TRUE; + + return 1; +} + +/* Returns the number of sub-packets of interest */ +int decode_gudp(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info) +{ + guint32 field_uint[MAX_RETURNED_ELEMENTS]; /* An extracted field array for unsigned integers */ + size_t field_value_count; /* How many entries are there in the extracted field array */ + + pkt_info->srcport = pinfo->srcport; + pkt_info->dstport = pinfo->destport; + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_UDP_STREAM].hf, field_uint, &field_value_count)) { + if (field_value_count) + pkt_info->rrpd.stream_no = field_uint[0]; + } + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_UDP_LENGTH].hf, field_uint, &field_value_count)) { + if (field_value_count) + pkt_info->len = field_uint[0]; + } + + if ((wmem_map_lookup(preferences.udp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport)) != NULL) || + (wmem_map_lookup(preferences.udp_svc_ports, GUINT_TO_POINTER(pkt_info->srcport)) != NULL)) + { + if (wmem_map_lookup(preferences.udp_svc_ports, GUINT_TO_POINTER(pkt_info->dstport)) != NULL) + pkt_info->rrpd.c2s = TRUE; + + pkt_info->rrpd.session_id = 0; + pkt_info->rrpd.msg_id = 0; + pkt_info->rrpd.decode_based = FALSE; + pkt_info->rrpd.calculation = RTE_CALC_GUDP; + pkt_info->pkt_of_interest = TRUE; + } + + return 1; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/transum/decoders.h b/plugins/epan/transum/decoders.h new file mode 100644 index 00000000..6d95d207 --- /dev/null +++ b/plugins/epan/transum/decoders.h @@ -0,0 +1,31 @@ +/* decoders.h + * Header file for the TRANSUM response time analyzer post-dissector + * By Paul Offord + * Copyright 2016 Advance Seven Limited + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +int decode_syn(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info); +int decode_dcerpc(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info); +int decode_smb(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info, PKT_INFO* subpackets); +int decode_gtcp(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info); +int decode_dns(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info); +int decode_gudp(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info); + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/transum/extractors.c b/plugins/epan/transum/extractors.c new file mode 100644 index 00000000..80475ae3 --- /dev/null +++ b/plugins/epan/transum/extractors.c @@ -0,0 +1,165 @@ +/* extractors.c + * Routines for the TRANSUM response time analyzer post-dissector + * By Paul Offord + * Copyright 2016 Advance Seven Limited + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "config.h" +#include +#include +#include "extractors.h" + +/* + This function extracts a field value (e.g. tcp.len) from a tree. Because a packet may contain + multiple values for the field, the extracted values are returned in a result_array. The + number of array entries is returned in element_count. + + Return is 0 if all went well. If this function return -1 it is probably because the tree did not + include the field defined by the field_id. + */ +int extract_uint(proto_tree *tree, int field_id, guint32 *result_array, size_t *element_count) +{ + GPtrArray *finfo_array; + + *element_count = 0; + if (tree == NULL) { + return -1; + } + + finfo_array = proto_get_finfo_ptr_array(tree, field_id); + + if (finfo_array == NULL) { + return -1; + } + + *element_count = g_ptr_array_len(finfo_array); + + for (size_t i = 0; i < *element_count && i < MAX_RETURNED_ELEMENTS; i++) + { + result_array[i] = fvalue_get_uinteger(((field_info*)finfo_array->pdata[i])->value); + } + + return 0; +} + +int extract_ui64(proto_tree *tree, int field_id, guint64 *result_array, size_t *element_count) +{ + GPtrArray *finfo_array; + + *element_count = 0; + if (tree == NULL) { + return -1; + } + + finfo_array = proto_get_finfo_ptr_array(tree, field_id); + + if (finfo_array == NULL) { + return -1; + } + + *element_count = g_ptr_array_len(finfo_array); + + for (size_t i = 0; i < *element_count && i < MAX_RETURNED_ELEMENTS; i++) + { + result_array[i] = fvalue_get_uinteger64(((field_info*)finfo_array->pdata[i])->value); + } + + return 0; +} + +int extract_si64(proto_tree *tree, int field_id, guint64 *result_array, size_t *element_count) +{ + GPtrArray *finfo_array; + + *element_count = 0; + if (tree == NULL) { + return -1; + } + + finfo_array = proto_get_finfo_ptr_array(tree, field_id); + + if (finfo_array == NULL) { + return -1; + } + + *element_count = g_ptr_array_len(finfo_array); + + for (size_t i = 0; i < *element_count && i < MAX_RETURNED_ELEMENTS; i++) + { + result_array[i] = fvalue_get_sinteger64(((field_info*)finfo_array->pdata[i])->value); + } + + return 0; +} + +int extract_bool(proto_tree *tree, int field_id, gboolean *result_array, size_t *element_count) +{ + GPtrArray *finfo_array; + + *element_count = 0; + if (tree == NULL) { + return -1; + } + + finfo_array = proto_get_finfo_ptr_array(tree, field_id); + + if (finfo_array == NULL) { + return -1; + } + + *element_count = g_ptr_array_len(finfo_array); + + for (size_t i = 0; i < *element_count && i < MAX_RETURNED_ELEMENTS; i++) + { + fvalue_t *fv = ((field_info*)finfo_array->pdata[i])->value; + + ws_assert(fvalue_type_ftenum(fv) == FT_BOOLEAN); + if (fvalue_get_uinteger64(fv)) + result_array[i] = TRUE; + else + result_array[i] = FALSE; + } + + return 0; +} + +/* + * Extract a count of the number of instances of a given field. + */ +int extract_instance_count(proto_tree *tree, int field_id, size_t *element_count) +{ + GPtrArray *finfo_array; + + *element_count = 0; + if (tree == NULL) { + return -1; + } + + finfo_array = proto_get_finfo_ptr_array(tree, field_id); + + if (finfo_array == NULL) { + return -1; + } + + *element_count = g_ptr_array_len(finfo_array); + + return 0; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/transum/extractors.h b/plugins/epan/transum/extractors.h new file mode 100644 index 00000000..d56134a6 --- /dev/null +++ b/plugins/epan/transum/extractors.h @@ -0,0 +1,21 @@ +/* extractors.h + * Header file for the TRANSUM response time analyzer post-dissector + * By Paul Offord + * Copyright 2016 Advance Seven Limited + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include +#include + +#define MAX_RETURNED_ELEMENTS 16 + +int extract_uint(proto_tree *tree, int field_id, guint32 *result_array, size_t *element_count); +int extract_ui64(proto_tree *tree, int field_id, guint64 *result_array, size_t *element_count); +int extract_si64(proto_tree *tree, int field_id, guint64 *result_array, size_t *element_count); +int extract_bool(proto_tree *tree, int field_id, gboolean *result_array, size_t *element_count); +int extract_instance_count(proto_tree *tree, int field_id, size_t *element_count); diff --git a/plugins/epan/transum/packet-transum.c b/plugins/epan/transum/packet-transum.c new file mode 100644 index 00000000..1022423a --- /dev/null +++ b/plugins/epan/transum/packet-transum.c @@ -0,0 +1,1366 @@ +/* packet-transum.c + * Routines for the TRANSUM response time analyzer post-dissector + * By Paul Offord + * Copyright 2016 Advance Seven Limited + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* ToDo: Test handling of multiple SMB2 messages within a packet */ +/* ToDo: Rework the Summarizer code (future release) */ + +#include "config.h" +#define WS_LOG_DOMAIN "transum" + +#include +#include +#include +#include +#include "packet-transum.h" +#include "preferences.h" +#include "extractors.h" +#include "decoders.h" +#include + +void proto_register_transum(void); +void proto_reg_handoff_transum(void); + +static dissector_handle_t transum_handle; + +#define CAPTURE_CLIENT 0 +#define CAPTURE_INTERMEDIATE 1 +#define CAPTURE_SERVICE 2 + +#define RTE_TIME_SEC 1 +#define RTE_TIME_MSEC 1000 +#define RTE_TIME_USEC 1000000 + +/* The following are the field ids for the protocol values used by TRANSUM. + Make sure they line up with ehf_of_interest order */ +HF_OF_INTEREST_INFO hf_of_interest[HF_INTEREST_END_OF_LIST] = { + { -1, "ip.proto" }, + { -1, "ipv6.nxt" }, + + { -1, "tcp.analysis.retransmission" }, + { -1, "tcp.analysis.keep_alive" }, + { -1, "tcp.flags.syn" }, + { -1, "tcp.flags.ack" }, + { -1, "tcp.flags.reset" }, + { -1, "tcp.flags.urg" }, + { -1, "tcp.seq" }, + { -1, "tcp.srcport" }, + { -1, "tcp.dstport" }, + { -1, "tcp.stream" }, + { -1, "tcp.len" }, + + { -1, "udp.srcport" }, + { -1, "udp.dstport" }, + { -1, "udp.stream" }, + { -1, "udp.length" }, + + { -1, "tls.record.content_type" }, + + { -1, "tds.type" }, + { -1, "tds.length" }, + + { -1, "smb.mid" }, + + { -1, "smb2.sesid" }, + { -1, "smb2.msg_id" }, + { -1, "smb2.cmd" }, + + { -1, "dcerpc.ver" }, + { -1, "dcerpc.pkt_type" }, + { -1, "dcerpc.cn_call_id" }, + { -1, "dcerpc.cn_ctx_id" }, + + { -1, "dns.id"}, +}; + + +static range_t *tcp_svc_port_range_values; + +static range_t *udp_svc_port_range_values; + +TSUM_PREFERENCES preferences; + + +static wmem_map_t *detected_tcp_svc; /* this array is used to track services detected during the syn/syn-ack process */ + +static wmem_map_t *dcerpc_req_pkt_type; /* used to indicate if a DCE-RPC pkt_type is a request */ + +static wmem_map_t *dcerpc_streams = NULL; /* used to record TCP stream numbers that are carrying DCE-RPC data */ + +/* +This array contains calls and returns that have no TRUE context_id +This is needed to overcome an apparent bug in Wireshark where +the field name of context id in parameters is the same as context id +in a message header +*/ +static wmem_map_t *dcerpc_context_zero; + +/* + The rrpd_list holds information about all of the APDU Request-Response Pairs seen in the trace. + */ +static wmem_list_t *rrpd_list = NULL; + +/* + output_rrpd is a hash of pointers to RRPDs on the rrpd_list. The index is the frame number. This hash is + used during Wireshark's second scan. As each packet is processed, TRANSUM uses the packet's frame number to index into + this hash to determine if we have RTE data for this particular packet, and if so the write_rte function is called. + */ +static wmem_map_t *output_rrpd; + +/* + The temp_rsp_rrpd_list holds RRPDs for APDUs where we have not yet seen the header information and so we can't + fully qualify the identification of the RRPD (the identification being ip_proto:stream_no:session_id:msg_id). + This only occurs when a) we are using one of the decode_based calculations (such as SMB2), and b) when we have + TCP Reassembly enabled. Once we receive a header packet for an APDU we migrate the entry from this array to the + main rrpd_list. + */ +static wmem_list_t *temp_rsp_rrpd_list = NULL; /* Reuse these for speed and efficient memory use - issue a warning if we run out */ + +/* Optimisation data - the following is used for various optimisation measures */ +static int highest_tcp_stream_no; +static int highest_udp_stream_no; +wmem_map_t *tcp_stream_exceptions; + + +static gint ett_transum = -1; +static gint ett_transum_header = -1; +static gint ett_transum_data = -1; + +static int proto_transum = -1; + +static int hf_tsum_status = -1; +//static int hf_tsum_time_units = -1; +static int hf_tsum_req_first_seg = -1; +static int hf_tsum_req_last_seg = -1; +static int hf_tsum_rsp_first_seg = -1; +static int hf_tsum_rsp_last_seg = -1; +static int hf_tsum_apdu_rsp_time = -1; +static int hf_tsum_service_time = -1; +static int hf_tsum_req_spread = -1; +static int hf_tsum_rsp_spread = -1; +static int hf_tsum_clip_filter = -1; +static int hf_tsum_calculation = -1; +static int hf_tsum_summary = -1; +static int hf_tsum_req_search = -1; +static int hf_tsum_rsp_search = -1; + +static const enum_val_t capture_position_vals[] = { + { "TRACE_CAP_CLIENT", "Client", TRACE_CAP_CLIENT }, + { "TRACE_CAP_INTERMEDIATE", "Intermediate", TRACE_CAP_INTERMEDIATE }, + { "TRACE_CAP_SERVICE", "Service", TRACE_CAP_SERVICE }, + { NULL, NULL, 0} +}; + +static const value_string rrdp_calculation_vals[] = { + { RTE_CALC_GTCP, "Generic TCP" }, + { RTE_CALC_SYN, "SYN and SYN/ACK" }, + { RTE_CALC_DCERPC, "DCE-RPC" }, + { RTE_CALC_SMB2, "SMB2" }, + { RTE_CALC_GUDP, "Generic UDP" }, + { RTE_CALC_DNS, "DNS" }, + + { 0, NULL } +}; + +/*static const enum_val_t time_multiplier_vals[] = { + { "RTE_TIME_SEC", "seconds", RTE_TIME_SEC }, + { "RTE_TIME_MSEC", "milliseconds", RTE_TIME_MSEC }, + { "RTE_TIME_USEC", "microseconds", RTE_TIME_USEC }, + { NULL, NULL, 0} +};*/ + +void add_detected_tcp_svc(guint16 port) +{ + wmem_map_insert(detected_tcp_svc, GUINT_TO_POINTER(port), GUINT_TO_POINTER(port)); +} + + +static void init_dcerpc_data(void) +{ + wmem_map_insert(dcerpc_req_pkt_type, GUINT_TO_POINTER(0), GUINT_TO_POINTER(1)); + wmem_map_insert(dcerpc_req_pkt_type, GUINT_TO_POINTER(11), GUINT_TO_POINTER(1)); + wmem_map_insert(dcerpc_req_pkt_type, GUINT_TO_POINTER(14), GUINT_TO_POINTER(1)); + + wmem_map_insert(dcerpc_context_zero, GUINT_TO_POINTER(11), GUINT_TO_POINTER(11)); + wmem_map_insert(dcerpc_context_zero, GUINT_TO_POINTER(12), GUINT_TO_POINTER(12)); + wmem_map_insert(dcerpc_context_zero, GUINT_TO_POINTER(14), GUINT_TO_POINTER(14)); + wmem_map_insert(dcerpc_context_zero, GUINT_TO_POINTER(15), GUINT_TO_POINTER(15)); +} + +static void register_dcerpc_stream(guint32 stream_no) +{ + wmem_map_insert(dcerpc_streams, GUINT_TO_POINTER(stream_no), GUINT_TO_POINTER(1)); +} + +/* This function should be called before any change to RTE data. */ +static void null_output_rrpd_entries(RRPD *in_rrpd) +{ + wmem_map_remove(output_rrpd, GUINT_TO_POINTER(in_rrpd->req_first_frame)); + wmem_map_remove(output_rrpd, GUINT_TO_POINTER(in_rrpd->req_last_frame)); + wmem_map_remove(output_rrpd, GUINT_TO_POINTER(in_rrpd->rsp_first_frame)); + wmem_map_remove(output_rrpd, GUINT_TO_POINTER(in_rrpd->rsp_last_frame)); +} + +/* This function should be called after any change to RTE data. */ +static void update_output_rrpd(RRPD *in_rrpd) +{ + if (preferences.rte_on_first_req) + wmem_map_insert(output_rrpd, GUINT_TO_POINTER(in_rrpd->req_first_frame), in_rrpd); + + if (preferences.rte_on_last_req) + wmem_map_insert(output_rrpd, GUINT_TO_POINTER(in_rrpd->req_last_frame), in_rrpd); + + if (preferences.rte_on_first_rsp) + wmem_map_insert(output_rrpd, GUINT_TO_POINTER(in_rrpd->rsp_first_frame), in_rrpd); + + if (preferences.rte_on_last_rsp) + wmem_map_insert(output_rrpd, GUINT_TO_POINTER(in_rrpd->rsp_last_frame), in_rrpd); +} + +/* Return the index of the RRPD that has been appended */ +static RRPD* append_to_rrpd_list(RRPD *in_rrpd) +{ + RRPD *next_rrpd = (RRPD*)wmem_memdup(wmem_file_scope(), in_rrpd, sizeof(RRPD)); + + update_output_rrpd(next_rrpd); + + wmem_list_append(rrpd_list, next_rrpd); + + return next_rrpd; +} + +static RRPD *find_latest_rrpd_dcerpc(RRPD *in_rrpd) +{ + RRPD *rrpd; + wmem_list_frame_t* i; + + for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i)) + { + rrpd = (RRPD*)wmem_list_frame_data(i); + + if (rrpd->calculation != RTE_CALC_DCERPC && rrpd->calculation != RTE_CALC_SYN) + continue; + + /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */ + if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no) + { + /* if we can match on session_id and msg_id must be a retransmission of the last request packet or the response */ + /* this logic works whether or not we are using reassembly */ + if (rrpd->session_id == in_rrpd->session_id && rrpd->msg_id == in_rrpd->msg_id) + return rrpd; + + /* If this is a retransmission, we assume it relates to this rrpd_list entry. + This is a bit of a kludge and not ideal but a compromise.*/ + /* ToDo: look at using TCP sequence number to allocate a retransmission to the correct APDU */ + if (in_rrpd->is_retrans) + return rrpd; + + if (preferences.reassembly) + { + if (in_rrpd->c2s) + { + /* if the input rrpd is for c2s and the one we have found already has response information, then the + in_rrpd represents a new RR Pair. */ + if (rrpd->rsp_first_frame) + return NULL; + + /* If the current rrpd_list entry doesn't have a msg_id then we assume we are mid Request APDU and so we have a match. */ + if (!rrpd->msg_id) + return rrpd; + } + else /* The in_rrpd relates to a packet going s2c */ + { + /* When reassembly is enabled, multi-packet response information is actually migrated from the temp_rsp_rrpd_list + to the rrpd_list and so we won't come through here. */ + ; + } + } + else /* we are not using reassembly */ + { + if (in_rrpd->c2s) + { + if (in_rrpd->msg_id) + /* if we have a message id this is a new Request APDU */ + return NULL; + else /* No msg_id */ + { + return rrpd; /* add this packet to the matching stream */ + } + } + else /* this packet is going s2c */ + { + if (!in_rrpd->msg_id && rrpd->rsp_first_frame) + /* we need to add this frame to the response APDU of the most recent rrpd_list entry that has already had response packets */ + return rrpd; + } + } + } /* this is the end of the 5-tuple check */ + + if (in_rrpd->c2s) + in_rrpd->req_search_total++; + else + in_rrpd->rsp_search_total++; + } /* end of the for loop */ + + return NULL; +} + +static RRPD *find_latest_rrpd_dns(RRPD *in_rrpd) +{ + RRPD *rrpd; + wmem_list_frame_t* i; + + for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i)) + { + rrpd = (RRPD*)wmem_list_frame_data(i); + + if (rrpd->calculation != RTE_CALC_DNS) + continue; + + /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */ + if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no) + { + if (rrpd->session_id == in_rrpd->session_id && rrpd->msg_id == in_rrpd->msg_id) + { + if (in_rrpd->c2s && rrpd->rsp_first_frame) + return NULL; /* this is new */ + else + return rrpd; + } + } /* this is the end of the 5-tuple check */ + + if (in_rrpd->c2s) + in_rrpd->req_search_total++; + else + in_rrpd->rsp_search_total++; + } /* this is the end of the for loop */ + + return NULL; +} + +static RRPD *find_latest_rrpd_gtcp(RRPD *in_rrpd) +{ + RRPD *rrpd; + wmem_list_frame_t* i; + + for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i)) + { + rrpd = (RRPD*)wmem_list_frame_data(i); + + if (rrpd->calculation != RTE_CALC_GTCP && rrpd->calculation != RTE_CALC_SYN) + continue; + + /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */ + if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no) + { + if (in_rrpd->c2s && rrpd->rsp_first_frame) + return NULL; /* this is new */ + else + return rrpd; + } /* this is the end of the 5-tuple check */ + + if (in_rrpd->c2s) + in_rrpd->req_search_total++; + else + in_rrpd->rsp_search_total++; + } /* this is the end of the for loop */ + + return NULL; +} + +static RRPD *find_latest_rrpd_gudp(RRPD *in_rrpd) +{ + RRPD *rrpd; + wmem_list_frame_t* i; + + for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i)) + { + rrpd = (RRPD*)wmem_list_frame_data(i); + + if (rrpd->calculation != RTE_CALC_GUDP) + continue; + + /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */ + if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no) + { + if (in_rrpd->c2s && rrpd->rsp_first_frame) + return NULL; /* this is new */ + else + return rrpd; + } /* this is the end of the 5-tuple check */ + + if (in_rrpd->c2s) + in_rrpd->req_search_total++; + else + in_rrpd->rsp_search_total++; + } /* this is the end of the for loop */ + + return NULL; +} + +static RRPD *find_latest_rrpd_smb2(RRPD *in_rrpd) +{ + RRPD *rrpd; + wmem_list_frame_t* i; + + for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i)) + { + rrpd = (RRPD*)wmem_list_frame_data(i); + + if (rrpd->calculation != RTE_CALC_SMB2 && rrpd->calculation != RTE_CALC_SYN) + continue; + + /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */ + if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no) + { + /* if we can match on session_id and msg_id must be a retransmission of the last request packet or the response */ + /* this logic works whether or not we are using reassembly */ + if (rrpd->session_id == in_rrpd->session_id && rrpd->msg_id == in_rrpd->msg_id) + return rrpd; + + /* If this is a retransmission, we assume it relates to this rrpd_list entry. + This is a bit of a kludge and not ideal but a compromise.*/ + /* ToDo: look at using TCP sequence number to allocate a retransmission to the correct APDU */ + if (in_rrpd->is_retrans) + return rrpd; + + if (preferences.reassembly) + { + if (in_rrpd->c2s) + { + /* if the input rrpd is for c2s and the one we have found already has response information, then the + in_rrpd represents a new RR Pair. */ + if (rrpd->rsp_first_frame) + return NULL; + + /* If the current rrpd_list entry doesn't have a msg_id then we assume we are mid Request APDU and so we have a match. */ + if (!rrpd->msg_id) + return rrpd; + } + else /* The in_rrpd relates to a packet going s2c */ + { + /* When reassembly is enabled, multi-packet response information is actually migrated from the temp_rsp_rrpd_list + to the rrpd_list and so we won't come through here. */ + ; + } + } + else /* we are not using reassembly */ + { + if (in_rrpd->c2s) + { + if (in_rrpd->msg_id) + /* if we have a message id this is a new Request APDU */ + return NULL; + else /* No msg_id */ + { + return rrpd; /* add this packet to the matching stream */ + } + } + else /* this packet is going s2c */ + { + if (!in_rrpd->msg_id && rrpd->rsp_first_frame) + /* we need to add this frame to the response APDU of the most recent rrpd_list entry that has already had response packets */ + return rrpd; + } + } + } /* this is the end of the 5-tuple check */ + + if (in_rrpd->c2s) + in_rrpd->req_search_total++; + else + in_rrpd->rsp_search_total++; + } /* end of the for loop */ + + return NULL; +} + +static RRPD *find_latest_rrpd_syn(RRPD *in_rrpd) +{ + RRPD *rrpd; + wmem_list_frame_t* i; + + for (i = wmem_list_tail(rrpd_list); i != NULL; i = wmem_list_frame_prev(i)) + { + rrpd = (RRPD*)wmem_list_frame_data(i); + + if (rrpd->calculation != RTE_CALC_SYN) + continue; + + /* if the input 5-tuple doesn't match the rrpd_list_entry 5-tuple -> go find the next list entry */ + if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no) + { + return rrpd; + } /* this is the end of the 5-tuple check */ + + if (in_rrpd->c2s) + in_rrpd->req_search_total++; + else + in_rrpd->rsp_search_total++; + } /* this is the end of the for loop */ + + return NULL; +} + +static RRPD *find_latest_rrpd(RRPD *in_rrpd) +{ + /* Optimisation Code */ + if (in_rrpd->ip_proto == IP_PROTO_TCP && (int)in_rrpd->stream_no > highest_tcp_stream_no) + { + highest_tcp_stream_no = in_rrpd->stream_no; + return NULL; + } + else if (in_rrpd->ip_proto == IP_PROTO_UDP && (int)in_rrpd->stream_no > highest_udp_stream_no) + { + highest_udp_stream_no = in_rrpd->stream_no; + return NULL; + } + /* End of Optimisation Code */ + + switch (in_rrpd->calculation) + { + case RTE_CALC_DCERPC: + return find_latest_rrpd_dcerpc(in_rrpd); + break; + + case RTE_CALC_DNS: + return find_latest_rrpd_dns(in_rrpd); + break; + + case RTE_CALC_GTCP: + return find_latest_rrpd_gtcp(in_rrpd); + break; + + case RTE_CALC_GUDP: + return find_latest_rrpd_gudp(in_rrpd); + break; + + case RTE_CALC_SMB2: + return find_latest_rrpd_smb2(in_rrpd); + break; + + case RTE_CALC_SYN: + return find_latest_rrpd_syn(in_rrpd); + break; + } + + return NULL; +} + +static void update_rrpd_list_entry(RRPD *match, RRPD *in_rrpd) +{ + null_output_rrpd_entries(match); + + if (preferences.debug_enabled) + { + match->req_search_total += in_rrpd->req_search_total; + match->rsp_search_total += in_rrpd->rsp_search_total; + } + + if (in_rrpd->c2s) + { + match->req_last_frame = in_rrpd->req_last_frame; + match->req_last_rtime = in_rrpd->req_last_rtime; + if (in_rrpd->msg_id) + { + match->session_id = in_rrpd->session_id; + match->msg_id = in_rrpd->msg_id; + } + } + else + { + if (!match->rsp_first_frame) + { + match->rsp_first_frame = in_rrpd->rsp_first_frame; + match->rsp_first_rtime = in_rrpd->rsp_first_rtime; + } + match->rsp_last_frame = in_rrpd->rsp_last_frame; + match->rsp_last_rtime = in_rrpd->rsp_last_rtime; + } + + update_output_rrpd(match); +} + +/* + This function processes a sub-packet that is going from client-to-service. + */ +static void update_rrpd_list_entry_req(RRPD *in_rrpd) +{ + RRPD *match; + + match = find_latest_rrpd(in_rrpd); + + if (match != NULL) + update_rrpd_list_entry(match, in_rrpd); + else + append_to_rrpd_list(in_rrpd); +} + +/* + This function inserts an RRPD into the temp_rsp_rrpd_list. If this is + successful return a pointer to the entry, else return NULL. + */ +static RRPD* insert_into_temp_rsp_rrpd_list(RRPD *in_rrpd) +{ + RRPD *rrpd = (RRPD*)wmem_memdup(wmem_file_scope(), in_rrpd, sizeof(RRPD)); + + wmem_list_append(temp_rsp_rrpd_list, rrpd); + + return rrpd; +} + +static RRPD* find_temp_rsp_rrpd(RRPD *in_rrpd) +{ + wmem_list_frame_t *i; + RRPD* rrpd; + + for (i = wmem_list_head(temp_rsp_rrpd_list); i; i = wmem_list_frame_next(i)) + { + rrpd = (RRPD*)wmem_list_frame_data(i); + if (rrpd->ip_proto == in_rrpd->ip_proto && rrpd->stream_no == in_rrpd->stream_no) + return rrpd; + } + + return NULL; +} + +static void update_temp_rsp_rrpd(RRPD *temp_list, RRPD *in_rrpd) +{ + temp_list->rsp_last_frame = in_rrpd->rsp_last_frame; + temp_list->rsp_last_rtime = in_rrpd->rsp_last_rtime; +} + +/* This function migrates an entry from the temp_rsp_rrpd_list to the main rrpd_list. */ +static void migrate_temp_rsp_rrpd(RRPD *main_list, RRPD *temp_list) +{ + update_rrpd_list_entry(main_list, temp_list); + + wmem_list_remove(temp_rsp_rrpd_list, temp_list); +} + +static void update_rrpd_list_entry_rsp(RRPD *in_rrpd) +{ + RRPD *match, *temp_list; + + if (in_rrpd->decode_based) + { + if (preferences.reassembly) + { + if (in_rrpd->msg_id) + { + /* If we have a msg_id in the input RRPD we must have header information. */ + temp_list = find_temp_rsp_rrpd(in_rrpd); + + if (temp_list != NULL) + { + update_temp_rsp_rrpd(temp_list, in_rrpd); + + /* Migrate the temp_rsp_rrpd_list entry to the main rrpd_list */ + match = find_latest_rrpd(in_rrpd); + if (match != NULL) + migrate_temp_rsp_rrpd(match, temp_list); + } + else + { + match = find_latest_rrpd(in_rrpd); + /* There isn't an entry in the temp_rsp_rrpd_list so update the master rrpd_list entry */ + if (match != NULL) + update_rrpd_list_entry(match, in_rrpd); + } + } + else + { + /* Update an existing entry to the temp_rsp_rrpd_list or add a new one. */ + temp_list = find_temp_rsp_rrpd(in_rrpd); + + if (temp_list != NULL) + update_temp_rsp_rrpd(temp_list, in_rrpd); + else + { + /* If this is a retransmission we need to add it to the last completed rrpd_list entry for this stream */ + if (in_rrpd->is_retrans) + { + match = find_latest_rrpd(in_rrpd); + + if (match != NULL) + update_rrpd_list_entry(match, in_rrpd); + else + insert_into_temp_rsp_rrpd_list(in_rrpd); + } + else + /* As it's not a retransmission, just create a new entry on the temp list */ + insert_into_temp_rsp_rrpd_list(in_rrpd); + } + } + } + else + { + /* Reassembly isn't set and so just go ahead and use the list function */ + match = find_latest_rrpd(in_rrpd); + if (match != NULL) + update_rrpd_list_entry(match, in_rrpd); + } + } + else + { + /* if this isn't decode_based then just go ahead and update the RTE data */ + match = find_latest_rrpd(in_rrpd); + if (match != NULL) + update_rrpd_list_entry(match, in_rrpd); + } + + return; +} + + +/* + This function updates the RTE data of an RRPD on the rrpd_list. The + frame_no values in the input RRPD double up as a mask. If the frame_no + is > 0 then the frame_no value and rtime values are updated. If the + frame_no is 0 then that particular frame_no and rtime value is not updated. + */ +static void update_rrpd_rte_data(RRPD *in_rrpd) +{ + if (in_rrpd->c2s) + update_rrpd_list_entry_req(in_rrpd); + else + update_rrpd_list_entry_rsp(in_rrpd); +} + +gboolean is_dcerpc_context_zero(guint32 pkt_type) +{ + return (wmem_map_lookup(dcerpc_context_zero, GUINT_TO_POINTER(pkt_type)) != NULL); +} + +gboolean is_dcerpc_req_pkt_type(guint32 pkt_type) +{ + return (wmem_map_lookup(dcerpc_req_pkt_type, GUINT_TO_POINTER(pkt_type)) != NULL); +} + +static gboolean is_dcerpc_stream(guint32 stream_no) +{ + return (wmem_map_lookup(dcerpc_streams, GUINT_TO_POINTER(stream_no)) != NULL); +} + +/* + This function initialises the global variables and populates the + [tcp|udp]_svc_ports tables with information from the preference settings + */ +static void init_globals(void) +{ + if (!proto_is_protocol_enabled(find_protocol_by_id(proto_transum))) + return; + + highest_tcp_stream_no = -1; + highest_udp_stream_no = -1; + + /* Create and initialise some dynamic memory areas */ + tcp_stream_exceptions = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); + detected_tcp_svc = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); + rrpd_list = wmem_list_new(wmem_file_scope()); + temp_rsp_rrpd_list = wmem_list_new(wmem_file_scope()); + + /* Indicate what fields we're interested in. */ + GArray *wanted_fields = g_array_sized_new(FALSE, FALSE, (guint)sizeof(int), HF_INTEREST_END_OF_LIST); + for (int i = 0; i < HF_INTEREST_END_OF_LIST; i++) + { + if (hf_of_interest[i].hf != -1) + g_array_append_val(wanted_fields, hf_of_interest[i].hf); + else + ws_warning("TRANSUM: unknown field %s", hf_of_interest[i].proto_name); + } + set_postdissector_wanted_hfids(transum_handle, wanted_fields); + + preferences.tcp_svc_ports = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); + preferences.udp_svc_ports = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); + + /* use the range values to populate the tcp_svc_ports list*/ + for (guint i = 0; i < tcp_svc_port_range_values->nranges; i++) + { + for (guint32 j = tcp_svc_port_range_values->ranges[i].low; j <= tcp_svc_port_range_values->ranges[i].high; j++) + { + wmem_map_insert(preferences.tcp_svc_ports, GUINT_TO_POINTER(j), GUINT_TO_POINTER(RTE_CALC_GTCP)); + } + } + + /* use the range values to populate the udp_svc_ports list*/ + for (guint i = 0; i < udp_svc_port_range_values->nranges; i++) + { + for (guint32 j = udp_svc_port_range_values->ranges[i].low; j <= udp_svc_port_range_values->ranges[i].high; j++) + { + wmem_map_insert(preferences.udp_svc_ports, GUINT_TO_POINTER(j), GUINT_TO_POINTER(RTE_CALC_GUDP)); + } + } + + /* create arrays to hold some DCE-RPC values */ + dcerpc_context_zero = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); + dcerpc_req_pkt_type = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); + dcerpc_streams = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal); + init_dcerpc_data(); + + wmem_map_insert(preferences.tcp_svc_ports, GUINT_TO_POINTER(445), GUINT_TO_POINTER(RTE_CALC_SMB2)); + wmem_map_insert(preferences.udp_svc_ports, GUINT_TO_POINTER(53), GUINT_TO_POINTER(RTE_CALC_DNS)); +} + +/* Undo capture file-specific initializations. */ +static void cleanup_globals(void) +{ + /* Clear the list of wanted fields as it will be reinitialized. */ + set_postdissector_wanted_hfids(transum_handle, NULL); +} + +/* This function adds the RTE data to the tree. The summary ptr is currently + not used but will be used for summariser information once this feature has + been ported from the Lua code. */ +static void write_rte(RRPD *in_rrpd, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, char *summary) +{ + nstime_t rte_art; + nstime_t rte_st; + nstime_t rte_reqspread; + nstime_t rte_rspspread; + proto_tree *rte_tree; + proto_item *pi; + wmem_strbuf_t *temp_string = wmem_strbuf_new(pinfo->pool, ""); + + if (in_rrpd->req_first_frame) + { + pi = proto_tree_add_item(tree, proto_transum, tvb, 0, 0, ENC_NA); + rte_tree = proto_item_add_subtree(pi, ett_transum); + + nstime_delta(&rte_reqspread, &(in_rrpd->req_last_rtime), &(in_rrpd->req_first_rtime)); + if (in_rrpd->rsp_first_frame) + { + /* calculate the RTE times */ + nstime_delta(&rte_art, &(in_rrpd->rsp_last_rtime), &(in_rrpd->req_first_rtime)); + nstime_delta(&rte_st, &(in_rrpd->rsp_first_rtime), &(in_rrpd->req_last_rtime)); + nstime_delta(&rte_rspspread, &(in_rrpd->rsp_last_rtime), &(in_rrpd->rsp_first_rtime)); + + pi = proto_tree_add_string(rte_tree, hf_tsum_status, tvb, 0, 0, "OK"); + } + else + { + pi = proto_tree_add_string(rte_tree, hf_tsum_status, tvb, 0, 0, "Response missing"); + } + proto_item_set_generated(pi); + + + pi = proto_tree_add_uint(rte_tree, hf_tsum_req_first_seg, tvb, 0, 0, in_rrpd->req_first_frame); + proto_item_set_generated(pi); + pi = proto_tree_add_uint(rte_tree, hf_tsum_req_last_seg, tvb, 0, 0, in_rrpd->req_last_frame); + proto_item_set_generated(pi); + + if (in_rrpd->rsp_first_frame) + { + pi = proto_tree_add_uint(rte_tree, hf_tsum_rsp_first_seg, tvb, 0, 0, in_rrpd->rsp_first_frame); + proto_item_set_generated(pi); + pi = proto_tree_add_uint(rte_tree, hf_tsum_rsp_last_seg, tvb, 0, 0, in_rrpd->rsp_last_frame); + proto_item_set_generated(pi); + + pi = proto_tree_add_time(rte_tree, hf_tsum_apdu_rsp_time, tvb, 0, 0, &rte_art); + proto_item_set_generated(pi); + pi = proto_tree_add_time(rte_tree, hf_tsum_service_time, tvb, 0, 0, &rte_st); + proto_item_set_generated(pi); + } + + pi = proto_tree_add_time(rte_tree, hf_tsum_req_spread, tvb, 0, 0, &rte_reqspread); + proto_item_set_generated(pi); + + if (in_rrpd->rsp_first_frame) + { + pi = proto_tree_add_time(rte_tree, hf_tsum_rsp_spread, tvb, 0, 0, &rte_rspspread); + proto_item_set_generated(pi); + } + + if (in_rrpd->ip_proto == IP_PROTO_TCP) + wmem_strbuf_append_printf(temp_string, "tcp.stream==%d", in_rrpd->stream_no); + else if (in_rrpd->ip_proto == IP_PROTO_UDP) + wmem_strbuf_append_printf(temp_string, "udp.stream==%d", in_rrpd->stream_no); + + if (in_rrpd->rsp_first_frame) + wmem_strbuf_append_printf(temp_string, " && frame.number>=%d && frame.number<=%d", in_rrpd->req_first_frame, in_rrpd->rsp_last_frame); + else + wmem_strbuf_append_printf(temp_string, " && frame.number>=%d && frame.number<=%d", in_rrpd->req_first_frame, in_rrpd->req_last_frame); + + if (in_rrpd->calculation == RTE_CALC_GTCP) + wmem_strbuf_append_printf(temp_string, " && tcp.len>0"); + + pi = proto_tree_add_string(rte_tree, hf_tsum_clip_filter, tvb, 0, 0, wmem_strbuf_get_str(temp_string)); + proto_item_set_generated(pi); + + pi = proto_tree_add_string(rte_tree, hf_tsum_calculation, tvb, 0, 0, val_to_str(in_rrpd->calculation, rrdp_calculation_vals, "Unknown calculation type: %d")); + proto_item_set_generated(pi); + + if (in_rrpd->rsp_first_frame) + { + if (preferences.summarisers_enabled) + { + if (summary) + { + pi = proto_tree_add_string(tree, hf_tsum_summary, tvb, 0, 0, summary); + proto_item_set_generated(pi); + } + } + } + + if (preferences.debug_enabled) + { + pi = proto_tree_add_uint(rte_tree, hf_tsum_req_search, tvb, 0, 0, in_rrpd->req_search_total); + proto_item_set_generated(pi); + pi = proto_tree_add_uint(rte_tree, hf_tsum_rsp_search, tvb, 0, 0, in_rrpd->rsp_search_total); + proto_item_set_generated(pi); + } + } +} + +/* + This function sets initial values in the current_pkt structure and checks + the xxx_svc_port arrays to see if they contain a match for the source or + destination port. This function also adds tcp_svc_ports entries when it + discovers DCE-RPC traffic. + + Returns the number of sub-packets to be processed. +*/ +static void set_proto_values(packet_info *pinfo, proto_tree *tree, PKT_INFO* pkt_info, PKT_INFO* subpackets) +{ + guint32 field_uint[MAX_RETURNED_ELEMENTS]; /* An extracted field array for unsigned integers */ + size_t field_value_count; /* How many entries are there in the extracted field array */ + + pkt_info->frame_number = pinfo->fd->num; /* easy access to frame number */ + pkt_info->relative_time = pinfo->rel_ts; + + int number_sub_pkts_of_interest = 0; /* default */ + + if (pinfo->ptype == PT_TCP) + pkt_info->rrpd.ip_proto = IP_PROTO_TCP; + else if (pinfo->ptype == PT_UDP) + pkt_info->rrpd.ip_proto = IP_PROTO_UDP; + + if (pkt_info->rrpd.ip_proto == IP_PROTO_TCP) + { + number_sub_pkts_of_interest = decode_gtcp(pinfo, tree, pkt_info); + /* decode_gtcp may return 0 but we need to keep processing because we + calculate RTE figures for all SYNs and also we may detect DCE-RPC later + (even though we don't currently have an entry in the tcp_svc_ports list). */ + + /* Optimisation code */ + if (pkt_info->len || pkt_info->tcp_flags_syn) + { + if (pkt_info->ssl_content_type == 21) /* this is an SSL Alert */ + { + pkt_info->pkt_of_interest = FALSE; + return; + } + + if ((int)pkt_info->rrpd.stream_no > highest_tcp_stream_no && !pkt_info->rrpd.c2s) + { + /* first packet on the stream is s2c and so add to exception list */ + if (wmem_map_lookup(tcp_stream_exceptions, GUINT_TO_POINTER(pkt_info->rrpd.stream_no)) == NULL) + wmem_map_insert(tcp_stream_exceptions, GUINT_TO_POINTER(pkt_info->rrpd.stream_no), GUINT_TO_POINTER(1)); + } + + if (wmem_map_lookup(tcp_stream_exceptions, GUINT_TO_POINTER(pkt_info->rrpd.stream_no)) != NULL) + { + if (pkt_info->rrpd.c2s) + wmem_map_remove(tcp_stream_exceptions, GUINT_TO_POINTER(pkt_info->rrpd.stream_no)); + else + pkt_info->pkt_of_interest = FALSE; + } + } + /* End of Optimisation Code */ + + if (pkt_info->tcp_retran) + { + /* we may not want to continue with this packet if it's a retransmission */ + + /* If this is a server-side trace we need to ignore client-to-service TCP retransmissions + the rationale being that if we saw the original in the trace the service process saw it too */ + if (pkt_info->rrpd.c2s && preferences.capture_position == CAPTURE_SERVICE) + { + pkt_info->pkt_of_interest = FALSE; + return; + } + + /* If this is a client-side trace we need to ignore service-to-client TCP retransmissions + the rationale being that if we saw the original in the trace the client process saw it too */ + else if (!pkt_info->rrpd.c2s && preferences.capture_position == CAPTURE_CLIENT) + { + pkt_info->pkt_of_interest = FALSE; + return; + } + } + + /* We are not interested in TCP Keep-Alive */ + if (pkt_info->tcp_keep_alive) + { + pkt_info->pkt_of_interest = FALSE; + return; + } + + if (pkt_info->len == 1) + { + if (preferences.orphan_ka_discard && pkt_info->tcp_flags_ack && pkt_info->rrpd.c2s) + { + pkt_info->pkt_of_interest = FALSE; + return; /* It's a KEEP-ALIVE -> stop processing this packet */ + } + } + + /* check if SYN */ + if (pkt_info->tcp_flags_syn) + number_sub_pkts_of_interest = decode_syn(pinfo, tree, pkt_info); + + if (pkt_info->len > 0) + { + /* check if SMB2 */ + if (pkt_info->dstport == 445 || pkt_info->srcport == 445) + number_sub_pkts_of_interest = decode_smb(pinfo, tree, pkt_info, subpackets); + + else + { + /* check if DCE-RPC */ + /* We need to set RTE_CALC_DCERPC even when we don't have header info. */ + if (is_dcerpc_stream(pkt_info->rrpd.stream_no)) + { + pkt_info->rrpd.calculation = RTE_CALC_DCERPC; + pkt_info->rrpd.decode_based = TRUE; + pkt_info->pkt_of_interest = TRUE; + } + + if (!extract_uint(tree, hf_of_interest[HF_INTEREST_DCERPC_VER].hf, field_uint, &field_value_count)) + { + if (field_value_count) + { + if (pkt_info->rrpd.calculation != RTE_CALC_DCERPC) + register_dcerpc_stream(pkt_info->rrpd.stream_no); + + number_sub_pkts_of_interest = decode_dcerpc(pinfo, tree, pkt_info); + } + } + } + } + + } + else if (pkt_info->rrpd.ip_proto == IP_PROTO_UDP) + { + /* It's UDP */ + number_sub_pkts_of_interest = decode_gudp(pinfo, tree, pkt_info); + + if (pkt_info->srcport == 53 || pkt_info->dstport == 53) + number_sub_pkts_of_interest = decode_dns(pinfo, tree, pkt_info); + } + + /* Set appropriate RTE values in the sub-packets */ + for (int i = 0; (i < number_sub_pkts_of_interest) && (i < MAX_SUBPKTS_PER_PACKET); i++) + { + if (pkt_info->rrpd.c2s) + { + subpackets[i].rrpd.req_first_frame = pkt_info->frame_number; + subpackets[i].rrpd.req_first_rtime = pkt_info->relative_time; + subpackets[i].rrpd.req_last_frame = pkt_info->frame_number; + subpackets[i].rrpd.req_last_rtime = pkt_info->relative_time; + + subpackets[i].frame_number = pkt_info->frame_number; /* this acts as a switch later */ + } + else + { + subpackets[i].rrpd.rsp_first_frame = pkt_info->frame_number; + subpackets[i].rrpd.rsp_first_rtime = pkt_info->relative_time; + subpackets[i].rrpd.rsp_last_frame = pkt_info->frame_number; + subpackets[i].rrpd.rsp_last_rtime = pkt_info->relative_time; + + subpackets[i].frame_number = pkt_info->frame_number; /* this acts as a switch later */ + } + } +} + + +/* + * This function is called for each packet + * Wireshark scans all the packets once and then once again as they are displayed + * The pinfo.visited boolean is set to FALSE; on the first scan +*/ +static int dissect_transum(tvbuff_t *buffer, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + /* if (there is RTE info associated with this packet we need to output it */ + if (PINFO_FD_VISITED(pinfo)) + { + RRPD *rrpd = (RRPD*)wmem_map_lookup(output_rrpd, GUINT_TO_POINTER(pinfo->num)); + + if (rrpd) + { + if (tree) + { + /* Add the RTE data to the protocol decode tree if we output_flag is set */ + write_rte(rrpd, buffer, pinfo, tree, NULL); + } + } + } + else + { + PKT_INFO *sub_packet = wmem_alloc0_array(pinfo->pool, PKT_INFO, MAX_SUBPKTS_PER_PACKET); + + set_proto_values(pinfo, tree, &sub_packet[0], sub_packet); + + if (sub_packet[0].pkt_of_interest) + { + /* Loop to process each sub_packet and update the related RTE data */ + for (int i = 0; i < MAX_SUBPKTS_PER_PACKET; i++) + { + if (!sub_packet[i].frame_number) + break; + + update_rrpd_rte_data(&(sub_packet[i].rrpd)); + } + } + } + + return 0; +} + +void +proto_register_transum(void) +{ + module_t *transum_module; + + static hf_register_info hf[] = { + { &hf_tsum_status, + { "RTE Status", "transum.status", + FT_STRING, BASE_NONE, NULL, 0x0, + "Indication of completeness of the RTE information", HFILL } }, +#if 0 + { &hf_tsum_time_units, + { "RTE Time Units", "transum.time_units", + FT_STRING, BASE_NONE, NULL, 0x0, + "Time units used (s, ms or us) for the RTE values", HFILL } + }, +#endif + { &hf_tsum_req_first_seg, + { "Req First Seg", "transum.firstreq", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "First Segment of an APDU Request", HFILL } + }, + + { &hf_tsum_req_last_seg, + { "Req Last Seg", "transum.lastreq", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "Last Segment of an APDU Request", HFILL } + }, + + { &hf_tsum_rsp_first_seg, + { "Rsp First Seg", "transum.firstrsp", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "First Segment of an APDU Response", HFILL } + }, + + { &hf_tsum_rsp_last_seg, + { "Rsp Last Seg", "transum.lastrsp", + FT_FRAMENUM, BASE_NONE, NULL, 0x0, + "Last Segment of an APDU Response", HFILL } + }, + + { &hf_tsum_apdu_rsp_time, + { "APDU Rsp Time", "transum.art", + FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + "RTE APDU Response Time", HFILL } + }, + + { &hf_tsum_service_time, + { "Service Time", "transum.st", + FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + "RTE Service Time", HFILL } + }, + + { &hf_tsum_req_spread, + { "Req Spread", "transum.reqspread", + FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + "RTE Request Spread", HFILL } + }, + + { &hf_tsum_rsp_spread, + { "Rsp Spread", "transum.rspspread", + FT_RELATIVE_TIME, BASE_NONE, NULL, 0x0, + "RTE Response Spread", HFILL } + }, + + { &hf_tsum_clip_filter, + { "Trace clip filter", "transum.clip_filter", + FT_STRING, BASE_NONE, NULL, 0x0, + "Filter expression to select the APDU Request-Response pair", HFILL } + }, + + { &hf_tsum_calculation, + { "Calculation", "transum.calculation", + FT_STRING, BASE_NONE, NULL, 0x0, + "Basis of the RTE calculation", HFILL } + }, + + { &hf_tsum_summary, + { "Summary", "transum.summary", + FT_STRING, BASE_NONE, NULL, 0x0, + "Summarizer information", HFILL } + }, + + { &hf_tsum_req_search, + { "Req Search Count", "transum.req_search", + FT_UINT32, BASE_DEC, NULL, 0x0, + "rrpd_list search total for the request packets", HFILL } + }, + + { &hf_tsum_rsp_search, + { "Rsp Search Counts", "transum.rsp_search", + FT_UINT32, BASE_DEC, NULL, 0x0, + "rrpd_list search total for the response packets", HFILL } + } + + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + &ett_transum, + &ett_transum_header, + &ett_transum_data + }; + + proto_transum = proto_register_protocol("TRANSUM RTE Data", "TRANSUM", "transum"); + + /* Due to performance concerns of the dissector, it's disabled by default */ + proto_disable_by_default(proto_transum); + + + /* Set User Preferences defaults */ + preferences.capture_position = TRACE_CAP_CLIENT; + preferences.reassembly = TRUE; + + range_convert_str(wmem_epan_scope(), &tcp_svc_port_range_values, "25, 80, 443, 1433", MAX_TCP_PORT); + range_convert_str(wmem_epan_scope(), &udp_svc_port_range_values, "137-139", MAX_UDP_PORT); + + preferences.orphan_ka_discard = FALSE; + preferences.time_multiplier = RTE_TIME_SEC; + preferences.rte_on_first_req = FALSE; + preferences.rte_on_last_req = TRUE; + preferences.rte_on_first_rsp = FALSE; + preferences.rte_on_last_rsp = FALSE; + + preferences.debug_enabled = FALSE; + + /* no start registering stuff */ + proto_register_field_array(proto_transum, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + transum_module = prefs_register_protocol(proto_transum, NULL); /* ToDo: We need to rethink the NULL pointer so that a preference change causes a rescan */ + + /* Register the preferences */ + prefs_register_obsolete_preference(transum_module, "tsumenabled"); + + prefs_register_enum_preference(transum_module, + "capture_position", + "Capture position", + "Position of the capture unit that produced this trace. This setting affects the way TRANSUM handles TCP Retransmissions. See the manual for details.", + &preferences.capture_position, + capture_position_vals, + FALSE); + + prefs_register_bool_preference(transum_module, + "reassembly", + "Subdissector reassembly enabled", + "Set this to match to the TCP subdissector reassembly setting", + &preferences.reassembly); + + prefs_register_range_preference(transum_module, + "tcp_port_ranges", + "Output RTE data for these TCP service ports", + "Add and remove ports numbers separated by commas\nRanges are supported e.g. 25,80,2000-3000,5432", + &tcp_svc_port_range_values, + 65536); + + prefs_register_range_preference(transum_module, + "udp_port_ranges", + "Output RTE data for these UDP service ports", + "Add and remove ports numbers separated by commas\nRanges are supported e.g. 123,137-139,520-521,2049", + &udp_svc_port_range_values, + 65536); + + prefs_register_bool_preference(transum_module, + "orphan_ka_discard", + "Discard orphaned TCP Keep-Alives", + "Set this to discard any packet in the direction client to service,\nwith a 1-byte payload of 0x00 and the ACK flag set", + &preferences.orphan_ka_discard); + + /* removed from this release + prefs_register_enum_preference(transum_module, + "time_multiplier", + "Time units for RTE values", + "Unit of time used for APDU Response Time, Service Time and Spread Time values.", + &preferences.time_multiplier, + time_multiplier_vals, + FALSE); + */ + + prefs_register_bool_preference(transum_module, + "rte_on_first_req", + "Add RTE data to the first request segment", + "RTE data will be added to the first request packet", + &preferences.rte_on_first_req); + + prefs_register_bool_preference(transum_module, + "rte_on_last_req", + "Add RTE data to the last request segment", + "RTE data will be added to the last request packet", + &preferences.rte_on_last_req); + + prefs_register_bool_preference(transum_module, + "rte_on_first_rsp", + "Add RTE data to the first response segment", + "RTE data will be added to the first response packet", + &preferences.rte_on_first_rsp); + + prefs_register_bool_preference(transum_module, + "rte_on_last_rsp", + "Add RTE data to the last response segment", + "RTE data will be added to the last response packet", + &preferences.rte_on_last_rsp); + + prefs_register_bool_preference(transum_module, + "debug_enabled", + "Enable debug info", + "Set this only to troubleshoot problems", + &preferences.debug_enabled); + + transum_handle = register_dissector("transum", dissect_transum, proto_transum); + + register_init_routine(init_globals); + register_cleanup_routine(cleanup_globals); + + register_postdissector(transum_handle); + + output_rrpd = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal); +} + +void proto_reg_handoff_transum(void) +{ + /* Get the field id for each field we will need */ + for (int i = 0; i < HF_INTEREST_END_OF_LIST; i++) + { + hf_of_interest[i].hf = proto_registrar_get_id_byname(hf_of_interest[i].proto_name); + } +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/transum/packet-transum.h b/plugins/epan/transum/packet-transum.h new file mode 100644 index 00000000..c8915e14 --- /dev/null +++ b/plugins/epan/transum/packet-transum.h @@ -0,0 +1,189 @@ +/* packet-transum.h + * Header file for the TRANSUM response time analyzer post-dissector + * By Paul Offord + * Copyright 2016 Advance Seven Limited + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#define ETH_TYPE_IPV4 0x0800 +#define ETH_TYPE_IPV6 0x86dd + +#define IP_PROTO_TCP 6 +#define IP_PROTO_UDP 17 + +#define RTE_CALC_SYN 1 +#define RTE_CALC_GTCP 2 +#define RTE_CALC_GUDP 3 +#define RTE_CALC_SMB1 4 +#define RTE_CALC_SMB2 5 +#define RTE_CALC_DCERPC 6 +#define RTE_CALC_DNS 7 + +#define MAX_SUBPKTS_PER_PACKET 16 + +/* + An RR pair is identified by a Fully Qualified Message ID (RRPD) +*/ + +typedef struct _RRPD +{ + /* + When a c2s is set TRUE it means that the associated packet is going from + client-to-service. If this value is false the associated packet is going + from service-to-client. + + This value is only valid for RRPDs imbedded in subpacket structures. + */ + gboolean c2s; + + guint8 ip_proto; + guint32 stream_no; + guint64 session_id; + guint64 msg_id; + + /* + Some request-response pairs are demarked simple by a change in direction on a + TCP or UDP stream from s2c to c2s. This is true for the GTCP and GUDP + calculations. Other calculations (such as DCERPC) use application protocol + values to detect the start and end of APDUs. In this latter case decode_based + is set to true. + */ + gboolean decode_based; + + gboolean is_retrans; + + guint32 req_first_frame; + nstime_t req_first_rtime; + guint32 req_last_frame; + nstime_t req_last_rtime; + + guint32 rsp_first_frame; + nstime_t rsp_first_rtime; + guint32 rsp_last_frame; + nstime_t rsp_last_rtime; + + guint calculation; + + /* The following numbers are for tuning purposes */ + guint32 req_search_total; /* The total number of steps back through the rrpd_list when matching requests to this entry */ + guint32 rsp_search_total; /* The total number of steps back through the rrpd_list when matching responses to this entry */ +} RRPD; + +typedef struct _PKT_INFO +{ + int frame_number; + nstime_t relative_time; + + gboolean tcp_retran; /* tcp.analysis.retransmission */ + gboolean tcp_keep_alive; /* tcp.analysis.keep_alive */ + gboolean tcp_flags_syn; /* tcp.flags.syn */ + gboolean tcp_flags_ack; /* tcp.flags.ack */ + gboolean tcp_flags_reset; /* tcp.flags.reset */ + guint32 tcp_flags_urg; /* tcp.urgent_pointer */ + guint32 tcp_seq; /* tcp.seq */ + + /* Generic transport values */ + guint16 srcport; /* tcp.srcport or udp.srcport*/ + guint16 dstport; /* tcp.dstport or udp.dstport*/ + guint16 len; /* tcp.len or udp.len */ + + guint8 ssl_content_type; /*tls.record.content_type */ + + guint8 tds_type; /*tds.type */ + guint16 tds_length; /* tds.length */ + + guint16 smb_mid; /* smb.mid */ + + guint64 smb2_sesid; /* smb2.sesid */ + guint64 smb2_msg_id; /* smb2.msg_id */ + guint16 smb2_cmd; /* smb2.cmd */ + + guint8 dcerpc_ver; /* dcerpc.ver */ + guint8 dcerpc_pkt_type; /* dcerpc.pkt_type */ + guint32 dcerpc_cn_call_id; /* dcerpc.cn_call_id */ + guint16 dcerpc_cn_ctx_id; /* dcerpc.cn_ctx_id */ + + guint16 dns_id; /* dns.id */ + + /* The following values are calculated */ + gboolean pkt_of_interest; + + /* RRPD data for this packet */ + /* Complete this based on the detected protocol */ + RRPD rrpd; + +} PKT_INFO; + +typedef enum { + HF_INTEREST_IP_PROTO = 0, + HF_INTEREST_IPV6_NXT, + + HF_INTEREST_TCP_RETRAN, + HF_INTEREST_TCP_KEEP_ALIVE, + HF_INTEREST_TCP_FLAGS_SYN, + HF_INTEREST_TCP_FLAGS_ACK, + HF_INTEREST_TCP_FLAGS_RESET, + HF_INTEREST_TCP_FLAGS_URG, + HF_INTEREST_TCP_SEQ, + HF_INTEREST_TCP_SRCPORT, + HF_INTEREST_TCP_DSTPORT, + HF_INTEREST_TCP_STREAM, + HF_INTEREST_TCP_LEN, + + HF_INTEREST_UDP_SRCPORT, + HF_INTEREST_UDP_DSTPORT, + HF_INTEREST_UDP_STREAM, + HF_INTEREST_UDP_LENGTH, + + HF_INTEREST_SSL_CONTENT_TYPE, + + HF_INTEREST_TDS_TYPE, + HF_INTEREST_TDS_LENGTH, + + HF_INTEREST_SMB_MID, + + HF_INTEREST_SMB2_SES_ID, + HF_INTEREST_SMB2_MSG_ID, + HF_INTEREST_SMB2_CMD, + + HF_INTEREST_DCERPC_VER, + HF_INTEREST_DCERPC_PKT_TYPE, + HF_INTEREST_DCERPC_CN_CALL_ID, + HF_INTEREST_DCERPC_CN_CTX_ID, + + HF_INTEREST_DNS_ID, + + HF_INTEREST_END_OF_LIST +} ehf_of_interest; + +typedef struct _HF_OF_INTEREST_INFO +{ + int hf; + const char* proto_name; + +} HF_OF_INTEREST_INFO; + +extern HF_OF_INTEREST_INFO hf_of_interest[HF_INTEREST_END_OF_LIST]; + +void add_detected_tcp_svc(guint16 port); +extern gboolean is_dcerpc_context_zero(guint32 pkt_type); +extern gboolean is_dcerpc_req_pkt_type(guint32 pkt_type); + + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/transum/preferences.h b/plugins/epan/transum/preferences.h new file mode 100644 index 00000000..96eea06a --- /dev/null +++ b/plugins/epan/transum/preferences.h @@ -0,0 +1,41 @@ +/* preferences.h + * Header file for the TRANSUM response time analyzer post-dissector + * By Paul Offord + * Copyright 2016 Advance Seven Limited + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include +#include + +#define RTE_TIME_SEC 1 +#define RTE_TIME_MSEC 1000 +#define RTE_TIME_USEC 1000000 + +#define TRACE_CAP_CLIENT 1 +#define TRACE_CAP_INTERMEDIATE 2 +#define TRACE_CAP_SERVICE 3 + +/* Add entries to the service port table for packets to be treated as services +* This is populated with preferences "service ports" data */ +typedef struct _TSUM_PREFERENCES +{ + int capture_position; + gboolean reassembly; + wmem_map_t *tcp_svc_ports; + wmem_map_t *udp_svc_ports; + gboolean orphan_ka_discard; + int time_multiplier; + gboolean rte_on_first_req; + gboolean rte_on_last_req; + gboolean rte_on_first_rsp; + gboolean rte_on_last_rsp; + gboolean summarisers_enabled; + gboolean summarise_tds; + gboolean summarisers_escape_quotes; + gboolean debug_enabled; +} TSUM_PREFERENCES; diff --git a/plugins/epan/unistim/AUTHORS b/plugins/epan/unistim/AUTHORS new file mode 100644 index 00000000..d71dd290 --- /dev/null +++ b/plugins/epan/unistim/AUTHORS @@ -0,0 +1,4 @@ +Author: +Don Newton +Chad Singer + diff --git a/plugins/epan/unistim/CMakeLists.txt b/plugins/epan/unistim/CMakeLists.txt new file mode 100644 index 00000000..b44ca8bc --- /dev/null +++ b/plugins/epan/unistim/CMakeLists.txt @@ -0,0 +1,64 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(unistim 0 0 2 0) + +set(DISSECTOR_SRC + packet-unistim.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_wireshark_plugin_library(unistim epan) + +target_link_libraries(unistim epan) + +install_plugin(unistim epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + unistim + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/unistim/ChangeLog b/plugins/epan/unistim/ChangeLog new file mode 100644 index 00000000..ddacecff --- /dev/null +++ b/plugins/epan/unistim/ChangeLog @@ -0,0 +1,5 @@ +2004-04-14 Don Newton + + * initial version + + diff --git a/plugins/epan/unistim/TODO b/plugins/epan/unistim/TODO new file mode 100644 index 00000000..7c86c58e --- /dev/null +++ b/plugins/epan/unistim/TODO @@ -0,0 +1,7 @@ + + * Add addr/cmd decoding to the summary line and info column + + * Handle msg_len consistently + + * Split up ett_unistim for various purposes + diff --git a/plugins/epan/unistim/audio.h b/plugins/epan/unistim/audio.h new file mode 100644 index 00000000..bc062cd4 --- /dev/null +++ b/plugins/epan/unistim/audio.h @@ -0,0 +1,560 @@ +/* audio.h + * header field declarations, value_string definitions and true_false_string + * definitions for audio manager messages + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef UNISTIM_AUDIO_H +#define UNISTIM_AUDIO_H + +static int hf_audio_mgr_attr=-1; +static int hf_audio_mgr_opts=-1; +static int hf_audio_mgr_alert=-1; +static int hf_audio_mgr_adj_rx_vol=-1; +static int hf_audio_mgr_def_rx_vol=-1; +static int hf_audio_mgr_handset=-1; +static int hf_audio_mgr_headset=-1; +static int hf_audio_default_rx_vol_id=-1; + +static int hf_audio_mgr_opt_max_vol=-1; +static int hf_audio_mgr_opt_adj_vol=-1; +static int hf_audio_mgr_opt_aa_rx_vol_rpt=-1; +static int hf_audio_mgr_opt_hs_on_air=-1; +static int hf_audio_mgr_opt_hd_on_air=-1; +static int hf_audio_mgr_opt_noise_squelch=-1; + +static int hf_audio_mgr_mute=-1; +static int hf_audio_mgr_tx_rx=-1; +static int hf_audio_mgr_stream_id=-1; + +static int hf_audio_mgr_transducer_based_tone_id=-1; +static int hf_audio_mgr_attenuated=-1; +static int hf_audio_mgr_warbler_select=-1; +static int hf_audio_mgr_transducer_routing=-1; +static int hf_audio_mgr_tone_vol_range=-1; +static int hf_audio_mgr_cadence_select=-1; +static int hf_audio_special_tone=-1; +static int hf_audio_tone_level=-1; +static int hf_audio_visual_tones=-1; + +static int hf_audio_stream_based_tone_id=-1; +static int hf_audio_stream_based_tone_rx_tx=-1; +static int hf_audio_stream_based_tone_mute=-1; +static int hf_audio_stream_id=-1; +static int hf_audio_stream_based_volume=-1; + +static int hf_audio_apb_number=-1; +static int hf_audio_apb_op_code=-1; +static int hf_audio_apb_param_len=-1; +static int hf_audio_apb_data=-1; +static int hf_audio_vocoder_id=-1; +static int hf_audio_vocoder_param=-1; +static int hf_audio_vocoder_entity=-1; +static int hf_audio_vocoder_annexa=-1; +static int hf_audio_vocoder_annexb=-1; +static int hf_audio_sample_rate=-1; +static int hf_audio_rtp_type=-1; +static int hf_audio_bytes_per_frame=-1; + +static int hf_audio_rx_stream_id=-1; +static int hf_audio_tx_stream_id=-1; +static int hf_rx_vocoder_type=-1; +static int hf_tx_vocoder_type=-1; +static int hf_frames_per_packet=-1; +static int hf_audio_tos=-1; +static int hf_audio_precedence=-1; +static int hf_audio_frf_11=-1; +static int hf_rtcp_bucket_id=-1; +static int hf_audio_lcl_rtp_port=-1; +static int hf_audio_lcl_rtcp_port=-1; +static int hf_audio_far_rtp_port=-1; +static int hf_audio_far_rtcp_port=-1; +static int hf_audio_far_ip_add=-1; +static int hf_audio_rtcp_bucket_id=-1; +static int hf_audio_clear_bucket=-1; + +static int hf_audio_transducer_pair=-1; +static int hf_audio_rx_enable=-1; +static int hf_audio_tx_enable=-1; +static int hf_audio_sidetone_disable=-1; +static int hf_audio_destruct_additive=-1; +static int hf_audio_dont_force_active=-1; +static int hf_audio_source_descr=-1; +static int hf_audio_sdes_rtcp_bucket=-1; +static int hf_audio_desired_jitter=-1; +static int hf_audio_high_water_mark=-1; +static int hf_audio_early_packet_resync_thresh=-1; +static int hf_audio_late_packet_resync_thresh=-1; +static int hf_audio_resolve_phone_port=-1; +static int hf_audio_far_end_echo_port=-1; +static int hf_audio_far_end_ip_address=-1; +static int hf_audio_nat_port=-1; +static int hf_audio_nat_ip_address=-1; +static int hf_audio_direction_code=-1; +static int hf_audio_hf_support=-1; +static int hf_audio_opt_rpt_max=-1; +static int hf_audio_opt_rpt_adj_vol=-1; +static int hf_audio_opt_rpt_auto_adj_vol=-1; +static int hf_audio_opt_rpt_hs_on_air=-1; +static int hf_audio_opt_rpt_hd_on_air=-1; +static int hf_audio_opt_rpt_noise_squelch=-1; +static int hf_audio_rx_vol_apb_rpt=-1; +static int hf_audio_rx_vol_vol_up=-1; +static int hf_audio_rx_vol_vol_floor=-1; +static int hf_audio_rx_vol_vol_ceiling=-1; +static int hf_audio_current_adj_vol_id=-1; +static int hf_audio_current_rx_level=-1; +static int hf_audio_current_rx_range=-1; +static int hf_audio_cadence_select=-1; +static int hf_audio_warbler_select=-1; +static int hf_audio_open_stream_rpt=-1; +static int hf_audio_sdes_rpt_source_desc=-1; +static int hf_audio_sdes_rpt_buk_id=-1; +static int hf_audio_phone_port=-1; +static int hf_audio_phone_ip=-1; + +static int hf_audio_phone_add_len=-1; +static int hf_audio_nat_listen_port=-1; +static int hf_audio_nat_ip=-1; +static int hf_audio_nat_add_len=-1; +static int hf_audio_stream_direction_code=-1; +static int hf_audio_stream_state=-1; +static int hf_audio_transducer_list_length=-1; + + +static const value_string audio_switch_msgs[]={ + {0x00,"Query Audio Manager"}, + {0x01,"Query Supervisor Headset Status"}, + {0x02,"Audio Manager Options"}, + {0x04,"Mute/Unmute"}, + {0x10,"Transducer Based Tone On"}, + {0x11,"Transducer Based Tone Off"}, + {0x12,"Alerting Tone Configuration"}, + {0x13,"Special Tone Configuration"}, + {0x14,"Paging Tone Configuration"}, + {0x15,"Alerting Tone Cadence Download"}, + {0x17,"Paging Tone Cadence Download"}, + {0x18,"Transducer Based Tone Volume Level"}, + {0x1a,"Visual Transducer Based Tone Enable"}, + {0x1b,"Stream Based Tone On"}, + {0x1c,"Stream Based Tone Off"}, + {0x1d,"Stream Based Tone Frequency Component List Download"}, + {0x1e,"Stream Based Tone Cadence Download"}, + {0x20,"Select Adjustable Rx Volume"}, + {0x21,"Set APB's Rx Volume Level"}, + {0x22,"Change Adjustable Rx Volume (quieter)"}, + {0x23,"Change Adjustable Rx Volume (louder)"}, + {0x24,"Adjust Default Rx Volume (quieter)"}, + {0x25,"Adjust Default Rx Volume (louder)"}, + {0x28,"APB Download"}, + {0x30,"Open Audio Stream"}, + {0x31,"Close Audio Stream"}, + {0x32,"Connect Transducer"}, + {0x34,"Filter Block Download"}, + {0x37,"Query RTCP Statistics"}, + {0x38,"Configure Vocoder Parameters"}, + {0x39,"Query RTCP Bucket's SDES Information"}, + {0x3a,"Jitter Buffer Parameters Configuration"}, + {0x3b,"Resolve Port Mapping"}, + {0x3c,"Port Mapping Discovery"}, + {0x3d,"Query Audio Stream Status"}, + {0xff,"Reserved"}, + {0,NULL} +}; +static const value_string audio_phone_msgs[]={ + {0x00,"Handset Connected"}, + {0x01,"Handset Disconnected"}, + {0x02,"Headset Connected"}, + {0x03,"Headset Disconnected"}, + {0x04,"Supervisor Headset Connected"}, + {0x05,"Supervisor Headset Disconnected"}, + {0x07,"Audio Manager Attributes Info"}, + {0x08,"Audio Manager Options Report"}, + {0x09,"Adjustable Rx Volume Report"}, + {0x0a,"Adjustable Rx Volume Information"}, + {0x0b,"APB's Default Rx Volume Value"}, + {0x0c,"Alerting Tone Select"}, + {0x0e,"RTCP Statistics Report"}, + {0x0f,"Open Audio Stream Report"}, + {0x10,"RTCP Bucket SDES Information Report"}, + {0x11,"Port Mapping Discovery"}, + {0x12,"Resolve Port Mapping"}, + {0x13,"Audio Stream Status Report"}, + {0x14,"Query APB Response"}, + {0xff,"Reserved"}, + {0,NULL} +}; + + +static const true_false_string stream_states={ + "Stream in use.", + "Stream not in use." +}; + +static const value_string stream_direction_codes[]={ + {0x00,"Invalid"}, + {0x01,"Command contains information about an Rx Audio stream"}, + {0x02,"Command contains information about a Tx Audio stream"}, + {0x03,"Invalid"}, + {0,NULL} +}; + + + +static const value_string source_descipts[]={ + {0x00,"Information Not Available"}, + {0x01,"Canonical End-Point Identifier associated with the IT"}, + {0x02,"Name used to describe the IT e.g. Homer Does IT "}, + {0x03,"E-mail address associated with the IT"}, + {0x04,"Phone number of the IT"}, + {0x05,"Geographic location of the IT"}, + {0x06,"IT software version"}, + {0x07,"Notice/Status information"}, + {0,NULL} +}; + +static const value_string stream_result[]={ + {0x00,"Stream opened successfully"}, + {0x01,"Operation failed: Invalid Stream ID"}, + {0x02,"Operation failed: Unsupported Vocoder"}, + {0x03,"Operation failed: Stream already in use"}, + {0x04,"Operation failed: Local port already in use"}, + {0x05,"Operation failed: No streams specified"}, + {0x06,"Operation failed: Audio packet size too large based on frames per packets"}, + {0x07,"Operation failed: Invalid Frames Per Packet value"}, + {0x08,"Operation failed: Invalid Bucket ID"}, + {0x09,"Operation failed: RTP and RTCP ports Identical"}, + {0x0a,"Operation failed: Inconsistent Parameters on full duplex promotion"}, + {0x0b,"Operation failed: No Empty Vocoder Bins"}, + {0x0c,"Operation failed: Vocoders Not Identical"}, + {0,NULL} +}; + + +static const value_string volume_rpt_apbs[]={ + {0x01,"Audio Param Bank 1"}, + {0x02,"Audio Param Bank 2"}, + {0x03,"Audio Param Bank 3"}, + {0x04,"Audio Param Bank 4"}, + {0x05,"Audio Param Bank 5"}, + {0x06,"Audio Param Bank 6"}, + {0x07,"Audio Param Bank 7"}, + {0x08,"Audio Param Bank 8"}, + {0x09,"Audio Param Bank 9"}, + {0x0a,"Audio Param Bank 10"}, + {0x0b,"Audio Param Bank 11"}, + {0x0c,"Audio Param Bank 12"}, + {0x0d,"Audio Param Bank 13"}, + {0x0e,"Audio Param Bank 14"}, + {0x0f,"Audio Param Bank 15"}, + {0x10,"Special Tones"}, + {0x11,"Paging Tones"}, + {0,NULL} +}; +static const true_false_string opt_rpt_adjust_volume={ + "Volume level adjustments are performed locally in the IT", + "Volume level adjustments are not performed locally in the IT" +}; +static const true_false_string opt_rpt_automatic_adjustable_rx_volume_report={ + "Adjustable Rx volume reports sent to the NI when volume keys are pressed", + "Adjustable Rx volume reports not sent to the NI when volume keys are pressed" +}; +static const true_false_string opt_rpt_enable_max_tone_vol={ + "Maximum tone volume is set equal to the physical maximum", + "Maximum tone volume is one level lower than physical maximum" +}; +static const true_false_string opt_rpths_on_air_feature={ + "Single tone frequency sent to HS port while call in progress", + "Single tone frequency NOT sent to HS port while call in progress" +}; +static const true_false_string opt_rpt_hd_on_air_feature={ + "Single tone frequency sent to HD port while call in progress", + "Single tone frequency NOT sent to HD port while call in progress" +}; +static const true_false_string opt_rpt_noise_sqlch_disable={ + "Automatic noise squelching enabled", + "Automatic noise squelching disabled" +}; + +static const value_string direction_codes[]={ + {0x00,"Invalid"}, + {0x01,"Rx Audio stream is queried"}, + {0x02,"Tx Audio stream is queried"}, + {0x03,"Rx and Tx Audio streams are queried"}, + {0,NULL} +}; + +static const value_string source_descriptions[]={ + {0x01,"Canonical End-Point Identifier associated with the Phone"}, + {0x02,"Name used to describe the Phone e.g. Homer Does Phone"}, + {0x03,"E-mail address associated with the Phone"}, + {0x04,"Phone number of the Phone"}, + {0x05,"Geographic location of the Phone"}, + {0x06,"Phone software version"}, + {0x07,"Notice/Status information"}, + {0,NULL} +}; + +static const true_false_string dont_force_active={ + "The APB specified will NOT be the active one", + "The APB specified will be the active one" +}; + + +static const true_false_string destruct_additive={ + "This will not affect the connections that were established prior", + "All transducers that were connected prior will be disconnected" +}; + + + +static const value_string transducer_pairs[]={ + {0x00,"Handset"}, + {0x01,"Headset"}, + {0x02,"Handsfree Speaker/Microphone"}, + {0x3F,"All Transducer Pairs"}, + {0,NULL} +}; + +static const value_string types_of_service[]={ + {0x08,"Minimize Delay"}, + {0x04,"Maximize Throughput"}, + {0x02,"Maximize Reliability"}, + {0x01,"Minimize Monetary Cost"}, + {0x00,"Normal Service"}, + {0,NULL} +}; +static const value_string precedences[]={ + {0x00,"Routine"}, + {0x01,"Priority"}, + {0x02,"Immediate"}, + {0x03,"Flash"}, + {0x04,"Flash Override"}, + {0x05,"Critical"}, + {0x06,"Internetwork Control"}, + {0x07,"Network Control"}, + {0,NULL} +}; +static const value_string sample_rates[]={ + {0x00,"8 kbit/sec"}, + {0x01,"16 kbit/sec"}, + {0x02,"44.1 kbit/sec"}, + {0,NULL} +}; + +static const value_string config_param_entities[]={ + {0x01,"Configuration Parameter in byte only affects the encoder"}, + {0x02,"Configuration Parameter in byte only affects decoder"}, + {0x03," Configuration Parameter in byte affects the whole vocoder"}, + {0,NULL} +}; +static const value_string vocoder_config_params[]={ + {0x00,"Turn Off Voice Activity Detection"}, + {0x01,"Turn On Voice Activity Detection"}, + {0x02,"Turn Off Bad Frame Interpolation Algorithm"}, + {0x03,"Turn On Bad Frame Interpolation Algorithm"}, + {0x04,"Disable Post Filter"}, + {0x05,"Enable Post Filter"}, + {0x06,"Disable High Pass Filter"}, + {0x07,"Enable High Pass Filter"}, + {0x08,"G.723 6.3kbps Working Rate "}, + {0x09,"G.723 5.3kbps Working Rate "}, + {0x0A,"G.729 Annexes Selection "}, + {0x0B,"Set the sampling Rate of the vocoder "}, + {0x0C,"Set RTP Payload Type "}, + {0x20,"Set number of bytes per frame "}, + {0,NULL} +}; +static const value_string vocoder_ids[]={ + {0x00,"G.711, Mu-Law"}, + {0x04,"G.723"}, + {0x08,"G.711, A-Law"}, + {0x0A,"16-bit Linear"}, + {0x12,"G.729"}, + {0x60,"8-bit Linear"}, + {0x61,"G.711, Mu-Law with PLP"}, + {0x62,"G.711, A-Law with PLP"}, + {0,NULL} +}; + + +static const value_string apb_op_codes[]={ + {0x00,"Enable Return To Default Option"}, + {0x01,"Disable Return To Default Option"}, + {0x02,"Enable Automatic Gain Control Option"}, + {0x03,"Disable Automatic Gain Control Option"}, + {0x04,"Select APB for Volume Control Option"}, + {0x05,"Deselect APB for Volume Control Option"}, + {0x06,"Enable Listener Sidetone Option"}, + {0x07,"Disable Listener Sidetone Option"}, + {0x08,"Enable Acoustic Echo Canceller (AEC) Option"}, + {0x09,"Disable Acoustic Echo Canceller (AEC) Option"}, + {0x10,"Enable Hearing Impaired (HIP) Option"}, + {0x11,"Disable Hearing Impaired (HIP) Option"}, + {0x0A,"Enable Rx Squelch Option"}, + {0x0B,"Disable Rx Squelch Option"}, + {0x0C,"Enable Rx Compressor Option"}, + {0x0D,"Disable Rx Compressor Option"}, + {0x0E,"Enable Tx Echo Squelch Option"}, + {0x0F,"Disable Tx Echo Squelch Option"}, + {0x40,"Query Audio Parameters"}, + {0x41,"Step Size setting"}, + {0x42,"Maximum Volume setting"}, + {0x43,"Minimum Volume setting"}, + {0x44,"Rx CODEC Gain Value"}, + {0x45,"Tx CODEC Gain Value"}, + {0x46,"Rx DSP Gain Value"}, + {0x47,"Tx DSP Gain Value"}, + {0x48,"Sidetone Gain Value"}, + {0x49,"Switched Loss Depth"}, + {0x4A,"Length of AEC"}, + {0x4B,"MCS_NOISE_THR"}, + {0x4C,"LineDelayLength"}, + {0x4D,"MaxReturnLossTG"}, + {0x4E,"SWL_AEC_OFF"}, + {0x4F,"NormDelta"}, + {0x50,"TxLevelCompHD"}, + {0x51,"TxRL_BOOT"}, + {0x52,"NoiseWaitCounter" }, + {0x53,"Whole APS" }, + {0x54,"Change Default Volume setting"}, + {0x55,"Change Current Volume setting"}, + {0x56,"Sampling Rate setting"}, + {0x57,"The filter(s) to be used when the HIP is enabled"}, + {0x58,"The threshold that should be used when AGC is enabled"}, + {0x59,"The threshold that should be used when Listener Sidetone (LST) is enabled"}, + {0,NULL} +}; +static const true_false_string stream_based_tone_rx_tx_yn={ + "Stream ID specified in last byte is in the tx direction", + "Stream ID specified in last byte is in the rx direction" +}; +static const true_false_string stream_based_tone_mute_yn={ + "Stream Based Tone will replace Stream Data", + "Stream Based tone will be summed with Stream Data" +}; +static const value_string stream_based_tone_vals[]={ + {0x00,"Dial Tone F1=0x0B33 - 350 Hz F2=0x0E14 - 440 Hz F3=0x00 - not present F4=0x00 - not present"}, + {0x01,"Recall Dial Tone F1=0x0B33 - 350 Hz F2=0x0E14 - 440 Hz F3=0x00 - not present F4=0x00 - not present"}, + {0x02,"Line Busy F1 = 0x0F5C - 480 Hz F2 = 0x13D7 - 620 Hz F3 = 0x00 - not present F4 = 0x00 - not present"}, + {0x03,"Reorder F1 = 0x0F5C - 480 Hz F2 = 0x13D7 - 620 Hz F3 = 0x00 - not present F4 = 0x00 - not present"}, + {0x04,"Audible Ringing F1=0x0E14 - 440 Hz F2=0x0F5C - 480 Hz F3=0x00 - not present F4=0x00 - not present"}, + {0x05,"Receiver Off Hook (ROH) F1=0x2CCC-1400 Hz F2=0x4851-2260 Hz F3=0x4E66-2450 Hz F4=0x5333 - 2600 Hz"}, + {0x06,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x07,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x08,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x09,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x0a,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x0b,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x0c,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x0d,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x0e,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0x0f,"No Tone F1=0x00-0 Hz F2=0x00-0 Hz F3=0x00-0 Hz F4=0x00-0 Hz 0x00 C1=0x00 C2=0x00 C3=0x0 c4=0x0"}, + {0,NULL} +}; +static const value_string stream_base_vol_level[]={ + /*{0x6F,"C1=0xFF00 C2=0x00 C3=0x00 c4=0x00 Steady on. -13 dBmO per frequency."},*/ + {0x6F,"C1=0x0505 C2=0x0505 C3=0x0505 c4=0xFF00 3 burst(0.1 sec on,0.1 sec off),Then steady on.-13 dBmO per frequency."}, + {0x60,"C1=0x1919 C2=0x00 C3=0x00 c4=0x00 0.5 sec on, 0.5 sec off, repeating. -24 dBmO per frequency."}, + {0x67,"C1=0x64C8 C2=0x00 C3=0x00 c4=0x00 2 sec on, 4 sec off, repeating. -19 dBmO per frequency."}, + {0x80,"C1=0xFF00 C2=0x00 C3=0x00 c4=0x00 0.1 sec on, 0.1 sec off, repeating. +3 to -6 dBmO/frequency."}, + {0,NULL} +}; +static const value_string special_tones_vals[]={ + {0x01,"250Hz"}, + {0x02,"333Hz"}, + {0x04,"500Hz"}, + {0x08,"667Hz"}, + {0x10,"1000Hz"}, + {0,NULL} +}; + + +static const value_string transducer_routing_vals[]={ + {0x00,"Handset Speaker"}, + {0x01,"Headset Speaker"}, + {0x02,"Handsfree Speaker"}, + {0,NULL} +}; +static const value_string cadence_select_vals[]={ + {0x00,"cadence 0 (2 secs on, 4 secs off, cyclic)"}, + {0x01,"cadence 1 (0.5 secs on, 0.3 secs off, 1.2 secs on, 4 secs off, cyclic)"}, + {0x02,"cadence 2 (0.7 secs on, 0.5 secs off, 0.7 secs on, 4 secs off, cyclic)"}, + {0x03,"cadence 3 (0.5 secs on then off, one-shot)"}, + {0x04,"cadence 4 (test cadence)"}, + {0x05,"cadence 5 (test cadence)"}, + {0x06," cadence 6 (test cadence)"}, + {0x07,"downloadable alerter tone cadence"}, + {0,NULL} +}; + +static const true_false_string audio_mgr_mute_val={ + "Following Stream will be Muted", + "Following Stream will be UnMuted" +}; +static const true_false_string audio_mgr_tx_rx_val={ + "Next Byte specifies an RX Stream ID", + "Next Byte specifies an TX Stream ID" +}; + +static const true_false_string audio_opts_enable_max_tone_vol={ + "Maximum tone volume is set equal to the physical maximum", + "Maximum tone volume is one level lower than physical maximum" +}; +static const true_false_string audio_opts_adjust_volume={ + "Volume level adjustments are performed locally in the phone", + "Volume level adjustments are not performed locally in the phone" +}; +static const true_false_string audio_opts_automatic_adjustable={ + "Adjustable Rx volume reports sent to the switch when volume keys are pressed", + "Adjustable Rx volume reports not sent to the switch when volume keys are pressed Rx Volume Report" +}; +static const true_false_string audio_opts_hs_on_air_feature={ + "Single tone frequency sent to Handset port while call in progress", + "Single tone frequency NOT sent to Handset (HS) port while call in progress" +}; +static const true_false_string audio_opts_hd_on_air_feature={ + "Single tone frequency sent to Headset (HD) port while call in progress", + "Single tone frequency NOT sent to Headset (HD) port while call in progress" +}; +static const true_false_string noise_sqlch_disable={ + "Automatic noise squelching enabled", + "Automatic noise squelching disabled" +}; + +static const value_string default_rx_vol_id[]={ + {0x00,"none"}, + {0x01,"Audio Param Bank 1"}, + {0x02,"Audio Param Bank 2"}, + {0x03,"Audio Param Bank 3"}, + {0x04,"Audio Param Bank 4"}, + {0x05,"Audio Param Bank 5"}, + {0x06,"Audio Param Bank 6"}, + {0x07,"Audio Param Bank 7"}, + {0x08,"Audio Param Bank 8"}, + {0x09,"Audio Param Bank 9"}, + {0x0a,"Audio Param Bank a"}, + {0x0b,"Audio Param Bank b"}, + {0x0c,"Audio Param Bank c"}, + {0x0d,"Audio Param Bank d"}, + {0x0e,"Audio Param Bank e"}, + {0x0f,"Audio Param Bank f"}, + {0x10,"Alerting"}, + {0x11,"Special Tones"}, + {0x12,"Paging Tones"}, + {0,NULL} +}; + +static const value_string trans_base_tone_ids[]={ + {0x00,"Alerting"}, + {0x01,"Special Tones"}, + {0x02,"Paging Tones"}, + {0,NULL} +}; +#endif diff --git a/plugins/epan/unistim/basic.h b/plugins/epan/unistim/basic.h new file mode 100644 index 00000000..9429ce98 --- /dev/null +++ b/plugins/epan/unistim/basic.h @@ -0,0 +1,71 @@ +/* basic.h + * header field declarations, value_string def and true_false_string + * definitions for basic manager messages + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef UNISTIM_BASIC_H +#define UNISTIM_BASIC_H + +static int hf_basic_switch_query_flags=-1; +static int hf_basic_switch_query_attr=-1; +static int hf_basic_switch_query_opts=-1; +static int hf_basic_switch_query_fw=-1; +static int hf_basic_switch_query_hw_id=-1; +static int hf_basic_switch_query_it_type=-1; +static int hf_basic_switch_query_prod_eng_code=-1; +static int hf_basic_switch_query_gray_mkt_info=-1; +static int hf_basic_switch_options_secure=-1; +static int hf_basic_switch_element_id=-1; +static int hf_basic_switch_eeprom_data=-1; +static int hf_basic_switch_terminal_id=-1; + +static int hf_basic_phone_eeprom_stat_cksum=-1; +static int hf_basic_phone_eeprom_dynam=-1; +static int hf_basic_phone_eeprom_net_config_cksum=-1; +static int hf_basic_phone_hw_id=-1; +static int hf_basic_phone_fw_ver=-1; +static int hf_basic_it_type=-1; +static int hf_basic_prod_eng_code=-1; +static int hf_basic_ether_address=-1; + +static const value_string it_types[]={ + {0x02,"i2004"}, + {0x03,"i2002 Basic Etherset"}, + {0x04,"Nortel Conference phone 2033 (polycom)"}, + {0x10,"Juniper 7308"}, + {0x11,"i2050 Softphone"}, + {0x30,"Meridian M6350"}, + {0,NULL} +}; +static const value_string basic_switch_msgs[]={ + {0x01,"Query Basic Manager"}, + {0x02,"Basic Manager Options"}, + {0x06,"EEprom Write"}, + {0x07,"Assign Terminal ID"}, + {0x08,"Encapsulate Command"}, + {0xff,"Reserved"}, + {0,NULL} +}; +static const value_string basic_phone_msgs[]={ + {0x00,"Basic Manager Attributes Info"}, + {0x01,"Basic Manager Options Report"}, + {0x02,"Firmware Version"}, + {0x03,"IT Type"}, + {0x07,"Hardware ID"}, + {0x08,"Product Engineering Code"}, + {0x09,"Grey Market Info"}, + {0x0a,"Encapsulate Command"}, + {0x11,"Phone Ethernet Address"}, + {0x0b,"Startup reason"}, + {0xff,"Reserved"}, + {0,NULL} +}; + +#endif diff --git a/plugins/epan/unistim/broadcast.h b/plugins/epan/unistim/broadcast.h new file mode 100644 index 00000000..4c85afc4 --- /dev/null +++ b/plugins/epan/unistim/broadcast.h @@ -0,0 +1,88 @@ +/* broadcast.h + * header field declarations, value_string def and true_false_string + * definitions for broadcast manager messages + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef UNISTIM_BROADCAST_H +#define UNISTIM_BROADCAST_H + +static int hf_broadcast_year=-1; +static int hf_broadcast_month=-1; +static int hf_broadcast_day=-1; +static int hf_broadcast_hour=-1; +static int hf_broadcast_minute=-1; +static int hf_broadcast_second=-1; +static int hf_broadcast_icon_state=-1; +static int hf_broadcast_icon_cadence=-1; + + +static const value_string broadcast_switch_msgs[]={ + {0x00,"Accessory Sync Update"}, + {0x01,"Logical Icon Update"}, + {0x02,"Time and Date Download"}, + {0x03,"Set Default Character Table Config"}, + {0xff,"Reserved"}, + {0,NULL} +}; +#if 0 +static const value_string broadcast_phone_msgs[]={ + {0xff,"Reserved"}, + {0,NULL} +}; +#endif + +static const value_string bcast_icon_states[]={ + {0x00,"I-Idle"}, + {0x01,"U-Idle"}, + {0x02,"I-Ring"}, + {0x03,"U-Ring"}, + {0x04,"I-Active"}, + {0x05,"U-Active"}, + {0x06,"I-Hold"}, + {0x07,"U-Hold"}, + {0x08,"I-Group Listen"}, + {0x09,"U-Group Listen"}, + {0x0A,"Feature Active"}, + {0x0B,"Feature Inactive"}, + {0x0C,"I-Hold Ringing"}, + {0x0D,"U-Hold Ringing"}, + {0x0E,"Active Audio"}, + {0x0F,"Hold Audio"}, + {0x10,"Home"}, + {0x11,"Business"}, + {0x12,"Extension Number"}, + {0x13,"Pager"}, + {0x14,"Voice"}, + {0x15,"Fax"}, + {0x16,"Email"}, + {0x17,"Wireless"}, + {0x18,"Internet Address"}, + {0x19,"Set-to-Set command"}, + {0x1A,"Secured"}, + {0x1B,"Trash Can"}, + {0x1C,"In Box"}, + {0x1D,"Out box"}, + {0x1E,"Video"}, + {0x1F,"Other/Misc"}, + {0,NULL} +}; + +static const value_string bcast_icon_cadence[]={ + {0x00,"Cadence off, On continuously"}, + {0x01,"Cadence on, Off continuously"}, + {0x02,"Flash, [1Hz]/[1/2]"}, + {0x03,"Flicker, [0.5Hz]/[13/16]"}, + {0x04,"Wink, [2Hz]/[3/4]"}, + {0x07,"Downloaded Cadence"}, + {0,NULL} +}; + +#endif + diff --git a/plugins/epan/unistim/defines.h b/plugins/epan/unistim/defines.h new file mode 100644 index 00000000..b7a06092 --- /dev/null +++ b/plugins/epan/unistim/defines.h @@ -0,0 +1,228 @@ +/* defines.h + * Contains all bitmask defines for unistim dissecting + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef UNISTIM_DEFINES +#define UNISTIM_DEFINES + + + +#define QUERY_AUDIO_MGR_ATTRIBUTES 0x01 +#define QUERY_AUDIO_MGR_OPTIONS 0x02 +#define QUERY_AUDIO_MGR_ALERTING 0x04 +#define QUERY_AUDIO_MGR_ADJ_RX_VOL 0x08 +#define QUERY_AUDIO_MGR_DEF_RX_VOL 0x10 +#define QUERY_AUDIO_MGR_HANDSET 0x40 +#define QUERY_AUDIO_MGR_HEADSET 0x80 +#define AUDIO_MGR_OPTS_MAX_VOL 0x01 +#define AUDIO_MGR_ADJ_VOL 0x02 +#define AUDIO_MGR_AUTO_RX_VOL_RPT 0x04 +#define AUDIO_MGR_HS_ON_AIR 0x08 +#define AUDIO_MGR_HD_ON_AIR 0x10 +#define AUDIO_MGR_NOISE_SQUELCH 0x20 +#define AUDIO_MGR_MUTE 0x01 +#define AUDIO_MGR_TX_RX 0x02 +#define AUDIO_MGR_ATTENUATED 0x08 +#define AUDIO_MGR_VISUAL_TONE 0x01 +#define AUDIO_STREAM_BASED_TONE_RX_TX 0x40 +#define AUDIO_STREAM_BASED_TONE_MUTE 0x80 +#define AUDIO_VOCODER_CONFIG_PARAM 0x3f +#define AUDIO_VOCODER_CONFIG_ENTITY 0xc0 +#define AUDIO_VOCODER_ANNEXA 0x01 +#define AUDIO_VOCODER_ANNEXB 0x02 +#define AUDIO_TYPE_OF_SERVICE 0x0f +#define AUDIO_PRECENDENCE 0x70 +#define AUDIO_FRF_11 0x80 +#define AUDIO_RTCP_BUCKET_ID 0x0f +#define AUDIO_CLEAR_BUCKET 0x10 +#define AUDIO_TRANSDUCER_PAIR_ID 0x3f +#define AUDIO_RX_ENABLE 0x40 +#define AUDIO_TX_ENABLE 0x80 +#define AUDIO_APB_NUMBER 0x0f +#define AUDIO_SIDETONE_DISABLE 0x10 +#define AUDIO_DESTRUCT_ADD 0x20 +#define AUDIO_DONT_FORCE_ACTIVE 0x40 +#define AUDIO_SOURCE_DESCRIPTION 0x0f +#define AUDIO_SDES_RTCP_BUCKET 0xf0 +#define AUDIO_DIRECTION_CODE 0x03 +#define AUDIO_HF_SUPPORT 0x01 +#define AUDIO_ENABLED_MAX_TONE 0x01 +#define AUDIO_ENABLED_ADJ_VOL 0x02 +#define AUDIO_AUTO_ADJ_RX_REP 0x04 +#define AUDIO_HS_ON_AIR_FEATURE 0x08 +#define AUDIO_HD_ON_AIR_FEATURE 0x10 +#define AUDIO_NOISE_SQUELCH_DIS 0x20 +#define AUDIO_APB_VOL_RPT 0x1f +#define AUDIO_VOL_UP_RPT 0x20 +#define AUDIO_VOL_FLR_RPT 0x40 +#define AUDIO_VOL_CEIL_RPT 0x80 +#define AUDIO_ALERT_CADENCE_SEL 0x07 +#define AUDIO_ALERT_WARBLER_SEL 0x38 +#define AUDIO_SDES_INFO_RPT_DESC 0x0f +#define AUDIO_SDES_INFO_RPT_BUK 0xf0 +#define AUDIO_STREAM_DIRECTION 0x03 +#define AUDIO_STREAM_DIRECTION_RX 0x01 +#define AUDIO_STREAM_DIRECTION_TX 0x02 +#define AUDIO_STREAM_STATE 0x01 + + +#define BASIC_QUERY_ATTRIBUTES 0x01 +#define BASIC_QUERY_OPTIONS 0x02 +#define BASIC_QUERY_FW 0x04 +#define BASIC_QUERY_HW_ID 0x08 +#define BASIC_QUERY_IT_TYPE 0x10 +#define BASIC_QUERY_PROD_ENG_CODE 0x40 +#define BASIC_QUERY_GRAY_MKT_INFO 0x80 +#define BASIC_OPTION_SECURE 0x01 + + + + +#define QUERY_NETWORK_MANAGER_DIAGNOSTIC 0x01 +#define QUERY_NETWORK_MANAGER_MANAGERS 0x02 +#define QUERY_NETWORK_MANAGER_ATTRIBUTES 0x04 +#define QUERY_NETWORK_MANAGER_SERVER_INFO 0x08 +#define QUERY_NETWORK_MANAGER_OPTIONS 0x10 +#define QUERY_NETWORK_MANAGER_SANITY 0x80 +#define NETWORK_MANAGER_ENABLE_DIAG 0x01 +#define NETWORK_MANAGER_ENABLE_RUDP 0x02 +#define RX_BUFFER_OVERFLOW 0x01 +#define TX_BUFFER_OVERFLOW 0x02 +#define RX_UNEXPECT_EMPTY 0x08 +#define INVALID_MSG 0x20 +#define EEPROM_INSANE 0x40 +#define EEPROM_UNSAFE 0x80 +#define NETWORK_MGR_REPORT_DIAG 0x01 +#define NETWORK_MGR_REPORT_RUDP 0x02 + + + + +#define DISPLAY_WRITE_ADDRESS_NUMERIC_FLAG 0x01 +#define DISPLAY_WRITE_ADDRESS_CONTEXT_FLAG 0x02 +#define DISPLAY_WRITE_ADDRESS_LINE_FLAG 0x04 +#define DISPLAY_WRITE_ADDRESS_SOFT_KEY_FLAG 0x08 +#define DISPLAY_WRITE_ADDRESS_SOFT_LABEL_FLAG 0x10 +#define DISPLAY_WRITE_ADDRESS_SOFT_KEY_ID 0xe0 +#define DISPLAY_WRITE_ADDRESS_CHAR_POS 0x1f +#define DISPLAY_WRITE_ADDRESS_LINE_NUM 0xe0 +#define DISPLAY_WRITE_CURSOR_MOVE 0x01 +#define DISPLAY_WRITE_CLEAR_LEFT 0x02 +#define DISPLAY_WRITE_CLEAR_RIGHT 0x04 +#define DISPLAY_WRITE_SHIFT_LEFT 0x08 +#define DISPLAY_WRITE_SHIFT_RIGHT 0x10 +#define DISPLAY_WRITE_HIGHLIGHT 0x20 +#define DISPLAY_CURSOR_BLINK 0x80 +#define DISPLAY_CURSOR_MOVE_CMD 0x0f + +#define DISPLAY_CLEAR_NUMERIC 0x01 +#define DISPLAY_CLEAR_CONTEXT 0x02 +#define DISPLAY_CLEAR_DATE 0x04 +#define DISPLAY_CLEAR_TIME 0x08 +#define DISPLAY_CLEAR_LINE 0x10 +#define DISPLAY_CLEAR_STATUS_BAR_ICON 0x20 +#define DISPLAY_CLEAR_SOFTKEY 0x40 +#define DISPLAY_CLEAR_SOFTKEY_LABEL 0x80 + +#define DISPLAY_CLEAR_LINE_1 0x01 +#define DISPLAY_CLEAR_LINE_2 0x02 +#define DISPLAY_CLEAR_LINE_3 0x04 +#define DISPLAY_CLEAR_LINE_4 0x08 +#define DISPLAY_CLEAR_LINE_5 0x10 +#define DISPLAY_CLEAR_LINE_6 0x20 +#define DISPLAY_CLEAR_LINE_7 0x40 +#define DISPLAY_CLEAR_LINE_8 0x80 + +#define DISPLAY_STATUS_BAR_ICON_1 0x01 +#define DISPLAY_STATUS_BAR_ICON_2 0x02 +#define DISPLAY_STATUS_BAR_ICON_3 0x04 +#define DISPLAY_STATUS_BAR_ICON_4 0x08 +#define DISPLAY_STATUS_BAR_ICON_5 0x10 +#define DISPLAY_STATUS_BAR_ICON_6 0x20 +#define DISPLAY_STATUS_BAR_ICON_7 0x40 +#define DISPLAY_STATUS_BAR_ICON_8 0x80 +#define DISPLAY_ICON_ID 0x1f + +#define DISPLAY_SOFT_KEY_1 0x01 +#define DISPLAY_SOFT_KEY_2 0x02 +#define DISPLAY_SOFT_KEY_3 0x04 +#define DISPLAY_SOFT_KEY_4 0x08 +#define DISPLAY_SOFT_KEY_5 0x10 +#define DISPLAY_SOFT_KEY_6 0x20 +#define DISPLAY_SOFT_KEY_7 0x40 +#define DISPLAY_SOFT_KEY_8 0x80 + +#define DISPLAY_CLEAR_SK_LABEL_KEY_ID 0x1f +#define DISPLAY_CLEAR_ALL_SLKS 0x20 + +#define KEY_LED_CADENCE 0x07 +#define KEY_LED_ID 0x18 + +#define DISPLAY_LINE_WIDTH 0x1f +#define DISPLAY_LINES 0xe0 +#define DISPLAY_SKEY_WIDTH 0x0f +#define DISPLAY_SKEYS 0x70 +#define DISPLAY_ICON 0x80 +#define DISPLAY_SOFTLABEL_WIDTH 0x0f +#define DISPLAY_CONTEXT_WIDTH 0xf0 +#define DISPLAY_NUMERIC_WIDTH 0x03 +#define DISPLAY_TIME_WIDTH 0x1c +#define DISPLAY_DATE_WIDTH 0xe0 +#define DISPLAY_CHAR_DLOAD 0x0f +#define DISPLAY_FFORM_ICON_DLOAD 0x70 +#define DISPLAY_ICON_TYPE 0x80 +#define DISPLAY_CHARSET 0x0f +#define DISPLAY_CURSOR_NUMERIC 0x01 +#define DISPLAY_CURSOR_CONTEXT 0x02 +#define DISPLAY_CURSOR_LINE 0x04 +#define DISPLAY_CURSOR_SKEY 0x08 +#define DISPLAY_CURSOR_SKEY_ID 0xe0 +#define DISPLAY_CURSOR_CHAR_POS 0x1f +#define DISPLAY_CURSOR_LINE_NUM 0xe0 +#define DISPLAY_TIME_FORMAT 0x03 +#define DISPLAY_DATE_FORMAT 0x0c +#define DISPLAY_USE_DATE_FORMAT 0x20 +#define DISPLAY_USE_TIME_FORMAT 0x10 +#define DISPLAY_CTX_FORMAT 0x0f +#define DISPLAY_CTX_FIELD 0x30 +#define DISPLAY_LAYER_SKEY_ID 0x07 +#define DISPLAY_LAYER_ALL_SKEYS 0x80 +#define DISPLAY_ONE_OR_CYCLIC 0x80 + +#define DISPLAY_CALL_TIMER_MODE 0x01 +#define DISPLAY_CALL_TIMER_RESET 0x02 +#define DISPLAY_CALL_TIMER_DISPLAY 0x04 +#define DISPLAY_CALL_TIMER_DELAY 0x08 +#define DISPLAY_CALL_TIMER_ID 0x3f + +#define KEY_NUM_PROG_KEYS 0x1f +#define KEY_NUM_SOFT_KEYS 0xe0 +#define KEY_HD_KEY_EXISTS 0x01 +#define KEY_MUTE_KEY_EXISTS 0x02 +#define KEY_QUIT_KEY_EXISTS 0x04 +#define KEY_COPY_KEY_EXISTS 0x08 +#define KEY_MWI_EXISTS 0x10 +#define KEY_NUM_NAV_KEYS 0x03 +#define KEY_NUM_CONSPIC_KEYS 0x1c +#define KEY_SEND_KEY_RELEASE 0x01 +#define KEY_ENABLE_VOL_KEY 0x02 +#define KEY_CONSPIC_PROG_KEY0 0x08 +#define KEY_ACD_SUP_CONTROL 0x10 +#define KEY_LOCAL_DIAL_PAD_FEED 0x60 +#define KEY_ADMIN_CMD 0xe0 + +#define NETWORK_FILE_XFER_MODE 0x1f +#define NETWORK_FORCE_DLOAD 0x20 +#define NETWORK_USE_FSERV_PORT 0x40 +#define NETWORK_USE_LOCAL_PORT 0x80 + + + +#endif diff --git a/plugins/epan/unistim/display.h b/plugins/epan/unistim/display.h new file mode 100644 index 00000000..829441d6 --- /dev/null +++ b/plugins/epan/unistim/display.h @@ -0,0 +1,261 @@ +/*display.h + * header field declarations, value_string def and true_false_string + * definitions for display manager messages + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef UNISTIM_DISPLAY_H +#define UNISTIM_DISPLAY_H + +static int hf_display_write_cursor_move=-1; +static int hf_display_write_clear_left=-1; +static int hf_display_write_clear_right=-1; +static int hf_display_write_shift_left=-1; +static int hf_display_write_shift_right=-1; +static int hf_display_write_highlight=-1; +static int hf_display_write_tag=-1; +static int hf_display_write_address_numeric=-1; +static int hf_display_write_address_context=-1; +static int hf_display_write_address_line=-1; +static int hf_display_write_address_soft_key=-1; +static int hf_display_write_address_soft_label=-1; +static int hf_display_write_address_softkey_id=-1; +static int hf_display_write_address_char_pos=-1; +static int hf_display_write_address_line_number=-1; +static int hf_display_cursor_move_cmd=-1; +static int hf_display_cursor_blink=-1; +static int hf_icon_id=-1; +static int hf_display_arrow=-1; +static int hf_display_clear_numeric =-1; +static int hf_display_clear_context =-1; +static int hf_display_clear_date =-1; +static int hf_display_clear_time =-1; +static int hf_display_clear_line =-1; +static int hf_display_clear_status_bar_icon =-1; +static int hf_display_clear_softkey =-1; +static int hf_display_clear_softkey_label =-1; +static int hf_display_clear_line_1 =-1; +static int hf_display_clear_line_2 =-1; +static int hf_display_clear_line_3 =-1; +static int hf_display_clear_line_4 =-1; +static int hf_display_clear_line_5 =-1; +static int hf_display_clear_line_6 =-1; +static int hf_display_clear_line_7 =-1; +static int hf_display_clear_line_8 =-1; +static int hf_display_clear_status_bar_icon_1 =-1; +static int hf_display_clear_status_bar_icon_2 =-1; +static int hf_display_clear_status_bar_icon_3 =-1; +static int hf_display_clear_status_bar_icon_4 =-1; +static int hf_display_clear_status_bar_icon_5 =-1; +static int hf_display_clear_status_bar_icon_6 =-1; +static int hf_display_clear_status_bar_icon_7 =-1; +static int hf_display_clear_status_bar_icon_8 =-1; +static int hf_display_clear_soft_key_1 =-1; +static int hf_display_clear_soft_key_2 =-1; +static int hf_display_clear_soft_key_3 =-1; +static int hf_display_clear_soft_key_4 =-1; +static int hf_display_clear_soft_key_5 =-1; +static int hf_display_clear_soft_key_6 =-1; +static int hf_display_clear_soft_key_7 =-1; +static int hf_display_clear_soft_key_8 =-1; +static int hf_display_clear_sk_label_key_id=-1; +static int hf_display_clear_all_slks=-1; + + +static int hf_display_line_width=-1; +static int hf_display_lines=-1; +static int hf_display_softkey_width=-1; +static int hf_display_softkeys=-1; +static int hf_display_icon=-1; +static int hf_display_softlabel_key_width=-1; +static int hf_display_context_width=-1; +static int hf_display_numeric_width=-1; +static int hf_display_time_width=-1; +static int hf_display_date_width=-1; +static int hf_display_char_dload=-1; +static int hf_display_freeform_icon_dload=-1; +static int hf_display_icon_type=-1; +static int hf_display_charsets=-1; +static int hf_display_contrast=-1; +static int hf_display_cursor_numeric=-1; +static int hf_display_cursor_context =-1; +static int hf_display_cursor_line =-1; +static int hf_display_cursor_softkey =-1; +static int hf_display_cursor_softkey_id =-1; +static int hf_display_cursor_char_pos =-1; +static int hf_display_cursor_line_number =-1; +static int hf_display_hlight_start=-1; +static int hf_display_hlight_end=-1; +static int hf_display_date_format=-1; +static int hf_display_time_format=-1; +static int hf_display_use_time_format=-1; +static int hf_display_use_date_format=-1; +static int hf_display_context_format=-1; +static int hf_display_context_field=-1; +static int hf_display_char_address=-1; +static int hf_display_layer_number=-1; +static int hf_display_layer_skey_id=-1; +static int hf_display_layer_all_skeys=-1; +static int hf_display_once_or_cyclic=-1; +static int hf_display_layer_duration=-1; +static int hf_display_call_timer_mode=-1; +static int hf_display_call_timer_reset=-1; +static int hf_display_call_timer_display=-1; +static int hf_display_call_timer_delay=-1; +static int hf_display_call_timer_id=-1; + + +static const value_string arrow_dirs[]={ + {0x00,"Down"}, + {0x01,"Up"}, + {0x02,"Right"}, + {0x03,"Left"}, + {0,NULL} +}; + + +static const value_string cursor_move_cmds[]={ + {0x00,"Set cursor at home (first character on the first text line)"}, + {0x01,"Set cursor at the address specified in the following byte"}, + {0x02,"Move the cursor by one to the left"}, + {0x03,"Move the cursor by one to the right"}, + {0x04,"Move the cursor to the left as specified by the Character Position field contained in the last byte"}, + {0x05,"Move the cursor to the right as specified by the Character Position field contained in the last byte"}, + {0x06,"Cursor ON"}, + {0x07,"Cursor OFF"}, + {0xff,"No Movement command"}, + {0,NULL} +}; + +static const value_string display_switch_msgs[]={ + {0x01,"Restore Default Character Table Configuration"}, + {0x04,"Arrow"}, + {0x05,"Query Status Bar Icon"}, + {0x06,"Highlight Off"}, + {0x07,"Highlight On"}, + {0x09,"Restore Time and Date"}, + {0x0a,"Clear Time and Date"}, + {0x0b,"Call Duration Timer"}, + {0x0c,"Query Display Manager"}, + {0x0d,"Download Call Duration Timer Delay"}, + {0x0e,"Disable Display Field"}, + {0x0f,"Clear Field"}, + {0x10,"Cursor Control"}, + {0x12,"Display Scroll with Data (before)"}, + {0x13,"Display Scroll with Data (after)"}, + {0x14,"Status Bar Icon Update"}, + {0x15,"Month Labels Download"}, + {0x16,"Call Duration Timer Label Download"}, + {0x17,"Time and Date Format"}, + {0x18,"Display Data Write address|no control|no tag|no"}, + {0x19,"Display Data Write address|yes control|no tag|no"}, + {0x1a,"Display Data Write address|no control|yes tag|no"}, + {0x1b,"Display Data Write address|yes control|yes tag|no"}, + {0x1c,"Display Data Write address|no control|no tag|yes"}, + {0x1d,"Display Data Write address|yes control|no tag|yes"}, + {0x1e,"Display Data Write address|no control|yes tag|yes"}, + {0x1f,"Display Data Write address|yes control|yes tag|yes"}, + {0x20,"Context Info Bar Format"}, + {0x21,"Set Default Character Table Configuration"}, + {0x22,"Special Character Download"}, + {0x23,"Highlighted Field Definition"}, + {0x24,"Contrast"}, + {0x25,"Caller Log Download"}, + {0x30,"Layered Softkey Text Download"}, + {0x31,"Layered Softkey Clear"}, + {0x32,"Set Visible Softkey Layer"}, + {0x33,"Layered Softkey Cadence Download"}, + {0x34,"Layered Softkey Cadencing On"}, + {0x35,"Layered Softkey Cadencing Off"}, + {0xff,"Reserved"}, + {0,NULL} +}; +static const value_string display_phone_msgs[]={ + {0x00,"Display Manager Attributes Info"}, + {0x01,"Contrast Level Report"}, + {0x02,"Cursor Location Report"}, + {0x03,"Highlight Status On"}, + {0x04,"Current Character Table Configuration Status"}, + {0x05,"Default Character Table Configuration Status"}, + {0x06,"Timer And Date Format Report"}, + {0x07,"Status Bar Icon State Report"}, + {0x0a,"Highlight Status Off"}, + {0xff,"Reserved"}, + {0,NULL} +}; + +static const true_false_string once_or_cyclic={ + "After the full cadence sequence is executed, softkey field will be updated ", + "After the full cadence sequence is executed, it is restarted from the top" +}; + + +static const value_string display_formats[]={ + {0x00,"None"}, + {0x01,"Underline"}, + {0x02,"Overline"}, + {0x03,"Marquee (combination of an overline and an underline)"}, + {0x04,"Border"}, + {0x05,"Reverse-video"}, + {0x06,"Reverse-video with border"}, + {0,NULL} +}; +static const value_string display_format_fields[]={ + {0x00,"Numeric Index field"}, + {0x01,"Context field"}, + {0x02,"Date field"}, + {0x03,"Time field"}, + {0,NULL} +}; + + +static const value_string time_formats[]={ + {0x00,"12-hour clock, e.g. 10:34pm"}, + {0x01,"French clock, e.g. 22h34"}, + {0x02,"24-hour clock, e.g. 22:34"}, + {0x03,"Reserved"}, + {0,NULL} +}; + +static const value_string date_formats[]={ + {0x00,"Day first, e.g. 16Sep"}, + {0x01,"Month first, e.g. Sep16"}, + {0x02," Numeric standard, e.g. 09/16"}, + {0x03,"Numeric inverse, e.g. 16/09"}, + {0,NULL} +}; + +static const value_string icon_types[]={ + {0x00,"Fixed Form Icons"}, + {0x01,"Free Form Icons"}, + {0,NULL} +}; + +static const true_false_string call_duration_timer_mode={ + "Mode = start timer", + "Mode = stop timer" +}; + +static const true_false_string call_duration_timer_reset={ + "Reset time to zero", + "Do not reset timer" +}; + +static const true_false_string call_duration_display_timer={ + "Call Duration timer is shown on the display", + "Call Duration timer is not shown on the display" +}; + +static const true_false_string call_duration_timer_delay={ + "Action occurs after Call Duration Timer Delay", + "Action occurs immediately" +}; + +#endif + diff --git a/plugins/epan/unistim/expansion.h b/plugins/epan/unistim/expansion.h new file mode 100644 index 00000000..4081ca84 --- /dev/null +++ b/plugins/epan/unistim/expansion.h @@ -0,0 +1,27 @@ +/* expansion.h + * header field declarations, value_string def and true_false_string + * definitions for basic manager messages + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef UNISTIM_EXPANSION_H +#define UNISTIM_EXPANSION_H + +static int hf_expansion_softlabel_number=-1; + +static const value_string expansion_switch_msgs[]={ + {0x17,"Next Display/Write command regards expansion module"}, + {0x57,"Display Data Write"}, + {0x59,"Icon Update"}, + {0,NULL} +}; +static const value_string expansion_phone_msgs[]={ + {0x59,"Expansion Key Pressed"}, + {0,NULL} +}; +#endif diff --git a/plugins/epan/unistim/key.h b/plugins/epan/unistim/key.h new file mode 100644 index 00000000..43acba8d --- /dev/null +++ b/plugins/epan/unistim/key.h @@ -0,0 +1,152 @@ +/* key.h + * header field declarations, value_string def and true_false_string + * definitions for key manager messages + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef UNISTIM_KEY_H +#define UNISTIM_KEY_H + + +static int hf_key_icon_id=-1; +static int hf_key_led_cadence=-1; +static int hf_key_led_id=-1; +static int hf_key_programmable_keys=-1; +static int hf_keys_soft_keys=-1; +static int hf_keys_hd_key=-1; +static int hf_keys_mute_key=-1; +static int hf_keys_quit_key=-1; +static int hf_keys_copy_key=-1; +static int hf_keys_mwi_key=-1; +static int hf_keys_num_nav_keys=-1; +static int hf_keys_num_conspic_keys=-1; +static int hf_keys_send_key_rel=-1; +static int hf_keys_enable_vol=-1; +static int hf_keys_conspic_prog_key=-1; +static int hf_keys_acd_super_control=-1; +static int hf_keys_local_dial_feedback=-1; +static int hf_keys_admin_command=-1; +static int hf_keys_logical_icon_id=-1; +static int hf_keys_repeat_timer_one=-1; +static int hf_keys_repeat_timer_two=-1; +static int hf_keys_led_id=-1; +static int hf_keys_phone_icon_id=-1; +static int hf_keys_cadence_on_time=-1; +static int hf_keys_cadence_off_time=-1; +static int hf_keys_user_activity_timeout=-1; + +static const value_string keys_led_ids[]={ + {0x00,"Message Waiting LED"}, + {0x01,"Handsfree or Supervisor Access* LED"}, + {0x02,"Headset LED"}, + {0x03,"Mute LED"}, + {0x07,"Query all LEDs"}, + {0,NULL} +}; + + +static const value_string admin_commands[]={ + {0x00,"Global NIL mapping"}, + {0x01,"One-to-one mapping"}, + {0x02,"Single mapping"}, + {0x03,"RESERVED"}, + {0,NULL} +}; + +static const value_string key_switch_msgs[]={ + {0x00,"LED Update"}, + {0x01,"Query Hookswitch"}, + {0x02,"User Activity Timer Stop"}, + {0x03,"User Activity Timer Start"}, + {0x04,"Downloadable Free Form Icon Access (Hardcoded)"}, + {0x05,"Downloadable Free Form Icon Access (Downloadable)"}, + {0x06,"Query Key/Indicator Manager"}, + {0x07,"Key/Indicator Manager Options"}, + {0x08,"Logical Icon Mapping"}, + {0x09,"Key Repeat Timer Download"}, + {0x0a,"Query LED State"}, + {0x0b,"Query Phone Icon State"}, + {0x0c,"Indicator Cadence Download"}, + {0x0d,"User Activity Timer Download"}, + {0x0e,"Free Form Icon Download"}, + {0x0f,"Phone Icon Update"}, + {0xff,"Reserved"}, + {0,NULL} +}; +static const value_string key_phone_msgs[]={ + {0x00,"Key Event"}, + {0x01,"LED Status Report"}, + {0x03,"On Hook"}, + {0x04,"Off Hook"}, + {0x05,"User Activity Timer Expired"}, + {0x06,"Hookswitch State (on hook)"}, + {0x07,"Hookswitch State (off hook)"}, + {0x08,"Key/Indicator Manager Attributes Info"}, + {0x09,"Key/Indicator Manager Options Report"}, + {0x0a,"Phone Icon Status Report"}, + {0xff,"Reserved"}, + {0,NULL} +}; + + +static const true_false_string key_release={ + "The Key code will be sent when a valid key release occurs", + "No command will be sent when a key is released" +}; +static const true_false_string enable_vol={ + "Volume key depression will be sent", + "Volume Key depression will not be sent" +}; +static const true_false_string conspic_prog={ + "Forces the keycode associated with conspicuous key0 to be the same as progkey0", + "Conspicuous value key 0 and programmable key 0 have different keycodes" +}; +static const true_false_string acd_supervisor={ + "ACD supervisor path and indicator controlled by the Switch", + "ACD supervisor path and indicator controlled by the Phone" +}; + +static const value_string local_dialpad_feedback[]={ + {0x00,"No tone feedback provided when a dial pad key is depressed"}, + {0x01,"Short 'click' provided when a dial pad key is depressed"}, + {0x02,"Corresponding DTMF tone provided when a dial pad key is depressed"}, + {0x03,"Reserved"}, + {0,NULL} +}; + +static const value_string number_nav_keys[]={ + {0x00,"no navigation keys"}, + {0x01,"two navigation keys"}, + {0x02,"four navigation keys"}, + {0x03,"not available"}, + {0,NULL} +}; + +static const value_string led_ids[]={ + {0x00,"Message Waiting LED"}, + {0x01,"Handsfree or Supervisor Access* LED"}, + {0x02,"Headset LED"}, + {0x03,"Mute LED"}, + {0,NULL} +}; + +static const value_string led_cadences[]={ + {0x00,"Off"}, + {0x01,"On"}, + {0x02,"Flash"}, + {0x03,"Flicker"}, + {0x04,""}, + {0x05,""}, + {0x06,"Blink"}, + {0x07,"Downloadable cadence"}, + {0,NULL} +}; + + +#endif diff --git a/plugins/epan/unistim/network.h b/plugins/epan/unistim/network.h new file mode 100644 index 00000000..561ef8dc --- /dev/null +++ b/plugins/epan/unistim/network.h @@ -0,0 +1,221 @@ +/* network.h + * header field declarations, value_string def and true_false_string + * definitions for network manager messages + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef UNISTIM_NETWORK_H +#define UNISTIM_NETWORK_H + + +static int hf_net_diag_flag=-1; +static int hf_net_managers_flag=-1; +static int hf_net_attributes_flag=-1; +static int hf_net_serv_info_flag=-1; +static int hf_net_options_flag=-1; +static int hf_net_sanity_flag=-1; +static int hf_net_enable_diag=-1; +static int hf_net_enable_rudp=-1; +static int hf_net_server_id=-1; +static int hf_net_server_port=-1; +static int hf_net_server_action=-1; +static int hf_net_server_retry_count=-1; +static int hf_net_server_failover_id=-1; +static int hf_net_server_ip_address=-1; +static int hf_net_server_time_out=-1; +static int hf_net_server_config_element=-1; +static int hf_net_server_recovery_time_low=-1; +static int hf_net_server_recovery_time_high=-1; +static int hf_net_phone_rx_ovr_flag=-1; +static int hf_net_phone_tx_ovr_flag=-1; +static int hf_net_phone_rx_empty_flag=-1; +static int hf_net_phone_invalid_msg_flag=-1; +static int hf_net_phone_eeprom_insane_flag=-1; +static int hf_net_phone_eeprom_unsafe_flag=-1; +static int hf_net_phone_diag=-1; +static int hf_net_phone_rudp=-1; + +static int hf_net_phone_primary_server_id=-1; +static int hf_net_phone_server_port=-1; +static int hf_net_phone_server_action=-1; +static int hf_net_phone_server_retry_count=-1; +static int hf_net_phone_server_failover_id=-1; +static int hf_net_phone_server_ip=-1; +static int hf_net_file_xfer_mode =-1; +static int hf_net_force_download =-1; +static int hf_net_use_file_server_port =-1; +static int hf_net_use_local_port=-1; +static int hf_net_file_server_port=-1; +static int hf_net_local_port=-1; +static int hf_net_file_server_address=-1; +static int hf_net_full_pathname=-1; +static int hf_net_file_identifier=-1; + +static const value_string file_xfer_modes[]={ + {0x00,"TFTP"}, + {0x01,"TFTP with active UNIStim channel"}, + {0x02,"UFTP"}, + {0x03,"UFTP with active UNIStim channel"}, + {0x04,"Future Use"}, + {0,NULL} +}; + +static const value_string action_bytes[]={ + {0x00,"Reserved"}, + {0x01,"Establish Unistim connection with Server"}, + {0x02,"Not Assigned"}, + {0,NULL} +}; + +static int hf_key_code=-1; +static int hf_key_command=-1; + +static const value_string key_cmds[]={ + {0x00,"Key Released"}, + {0x01,"Key Depressed"}, + {0x02,"Key Repeated"}, + {0,NULL} +}; + +static const value_string key_names[]={ + + {0x00,"Dial Pad 0"}, + {0x01,"Dial Pad 1"}, + {0x02,"Dial Pad 2"}, + {0x03,"Dial Pad 3"}, + {0x04,"Dial Pad 4"}, + {0x05,"Dial Pad 5"}, + {0x06,"Dial Pad 6"}, + {0x07,"Dial Pad 7"}, + {0x08,"Dial Pad 8"}, + {0x09,"Dial Pad 9"}, + {0x0a,"Dial Pad *"}, + {0x0b,"Dial Pad #"}, + {0x0c,"Navigation Up"}, + {0x0d,"Navigation Down"}, + {0x0e,"Navigation Right"}, + {0x0f,"Navigation Left"}, + {0x10,"Quit"}, + {0x11,"Copy"}, + {0x12,"Volume Up"}, + {0x13,"Volume Down"}, + {0x14,"Soft Key 0"}, + {0x15,"Soft Key 1"}, + {0x16,"Soft Key 2"}, + {0x17,"Soft Key 3"}, + {0x1a,"Supervisor Access Key"}, + {0x1b,"Hold"}, + {0x1c,"Release"}, + {0x1d,"Mute"}, + {0x1e,"Headset"}, + {0x1f,"Handsfree"}, + {0x20,"Prog Key 0"}, + {0x21,"Prog Key 1"}, + {0x22,"Prog Key 2"}, + {0x23,"Prog Key 3"}, + {0x24,"Prog Key 4"}, + {0x25,"Prog Key 5"}, + {0x26,"Prog Key 6"}, + {0x27,"Prog Key 7"}, + {0x28,"Prog Key 8"}, + {0x29,"Prog Key 9"}, + {0x2a,"Prog Key 10"}, + {0x2b,"Prog Key 11"}, + {0x2c,"Prog Key 12"}, + {0x2d,"Prog Key 13"}, + {0x2e,"Prog Key 14"}, + {0x2f,"Prog Key 15"}, + {0x30,"Prog Key 16"}, + {0x31,"Prog Key 17"}, + {0x32,"Prog Key 18"}, + {0x33,"Prog Key 19"}, + {0x34,"Prog Key 20"}, + {0x35,"Prog Key 21"}, + {0x36,"Prog Key 22"}, + {0x37,"Prog Key 23"}, + {0x38,"Prog Key 24"}, + {0x3b,"Conspicuous Key 0"}, + {0x3c,"Conspicuous Key 1"}, + {0x3d,"Conspicuous Key 2"}, + {0x3e,"Conspicuous Key 3"}, + {0x3f,"Conspicuous Key 4"}, + {0,NULL} +}; +static const value_string network_switch_msgs[]={ + {0x02,"Soft Reset"}, + {0x03,"Hard Reset"}, + {0x04,"Query Network Manager"}, + {0x05,"Network Manager Options"}, + {0x06,"QoS Configuration"}, + {0x09,"Set RTCP Source Description Item"}, + {0x0b,"Download Server Information"}, + {0x0c,"Server Switch"}, + {0x0d,"Query Network Configuration Element"}, + {0x0e,"Download Software Upgrade"}, + {0x0f,"Set RTCP Report Interval"}, + {0x10,"Set Primary Server"}, + {0x12,"Reset Watchdog"}, + {0x13,"Set Recovery Procedure Time Interval"}, + {0x14,"Transport Reliability Layer Parameters Download"}, + {0xff,"Reserved"}, + {0,NULL} +}; +static const value_string network_phone_msgs[]={ + {0x00,"Soft Reset Ack"}, + {0x01,"Sanity OK"}, + {0x02,"Network Manager Attributes Info"}, + {0x03,"Network Manager Diagnostic Info"}, + {0x04,"Manager IDs"}, + {0x05,"Network Manager Options Report"}, + {0x08,"Resume Connection with Server"}, + {0x09,"Suspend Connection with Server"}, + {0x0b,"Network Configuration Element Report"}, + {0x0c,"Server Information Report"}, + {0xff,"Reserved"}, + {0,NULL} +}; +static const value_string network_server_id[]={ + {0x00,"First Server"}, + {0x01,"Second Server"}, + {0x02,"Third Server"}, + {0x03,"Fourth Server"}, + {0x04,"Fifth Server"}, + {0x05,"Sixth Server"}, + {0x06,"Seventh Server"}, + {0x07,"Eighth Server"}, + {0x08,"Ninth Server"}, + {0x09,"Tenth Server"}, + {0,NULL} +}; +static const value_string server_action[]={ + {0x00,"Reserved"}, + {0x01,"Establish UNISTIM Connection with Server"}, + {0,NULL} +}; +static const value_string network_elements[]={ + {0x00,"IT IP Address"}, + {0x01,"IT Netmask"}, + {0x02,"Default Gateway IP Address"}, + {0x03,"First Server IP Address"}, + {0x04,"First Server Port Number"}, + {0x05,"Second Server IP Address"}, + {0x06,"Second Server Port Number"}, + {0x07,"First Server Action"}, + {0x08,"First Server Retry Count"}, + {0x09,"Boot Mode"}, + {0x0b,"Second Server Action"}, + {0x0c,"Second Server Retry Count"}, + {0x0e,"8-byte User PIN"}, + {0,NULL} +}; + + + +#endif + diff --git a/plugins/epan/unistim/packet-unistim.c b/plugins/epan/unistim/packet-unistim.c new file mode 100644 index 00000000..861ac763 --- /dev/null +++ b/plugins/epan/unistim/packet-unistim.c @@ -0,0 +1,3866 @@ +/* packet-unistim.c + * Routines for unistim packet dissection + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include "packet-unistim.h" +#include "defines.h" +#include "audio.h" +#include "basic.h" +#include "display.h" +#include "network.h" +#include "key.h" +#include "broadcast.h" +#include "uftp.h" +#include "expansion.h" + +void proto_register_unistim(void); + +static dissector_handle_t unistim_handle; + +static unistim_info_t *uinfo; +static int unistim_tap = -1; + +void proto_reg_handoff_unistim(void); +static void dissect_payload(proto_tree *unistim_tree,tvbuff_t *tvb,gint offset, packet_info *pinfo); + +static gint dissect_broadcast_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_audio_switch(proto_tree *msg_tree,packet_info *pinfo, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_expansion_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_display_switch(proto_tree *msg_tree, packet_info *pinfo, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_key_indicator_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_basic_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_network_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_broadcast_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_audio_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_expansion_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_display_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_key_indicator_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_basic_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_network_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len); +static gint dissect_unistim_message(proto_tree *unistim_tree, packet_info *pinfo, + tvbuff_t *tvb,gint offset); +static gint dissect_uftp_message(proto_tree *unistim_tree, packet_info *pinfo, + tvbuff_t *tvb,gint offset); + + +static int proto_unistim = -1; +static int hf_unistim_seq_nu = -1; +static int hf_unistim_packet_type = -1; +static int hf_unistim_payload = -1; +static int hf_unistim_cmd_add = -1; +static int hf_unistim_len =-1; +static int hf_terminal_id=-1; +static int hf_basic_bit_field=-1; + +static int hf_basic_switch_cmd=-1; +static int hf_basic_phone_cmd=-1; +static int hf_broadcast_switch_cmd=-1; +/* static int hf_broadcast_phone_cmd=-1; */ +static int hf_audio_switch_cmd=-1; +static int hf_audio_phone_cmd=-1; +static int hf_display_switch_cmd=-1; +static int hf_display_phone_cmd=-1; +static int hf_key_switch_cmd=-1; +static int hf_key_phone_cmd=-1; +static int hf_network_switch_cmd=-1; +static int hf_network_phone_cmd=-1; +static int hf_expansion_switch_cmd=-1; +static int hf_expansion_phone_cmd=-1; +static int hf_module_key_number=-1; + +static int hf_generic_data=-1; +static int hf_generic_string=-1; + +static gint ett_unistim = -1; + +static expert_field ei_unistim_len = EI_INIT; + +static const value_string packet_names[]={ + {0,"NAK"}, + {1,"ACK"}, + {2,"Payload"}, + {0,NULL} +}; + +static const value_string payload_names[]={ + {0x00,"NULL Protocol"}, + {0x01,"Aggregate Unistim"}, + {0x02,"Aggregate Unistim with Terminal ID"}, + {0x03,"UFTP"}, + {0xff,"Free Form Protocol"}, + {0,NULL} +}; + +static const range_string sequence_numbers[]={ + {0x00,0xFFFFFFFE,"Normal Sequence Number"}, + {0xFFFFFFFF,0xFFFFFFFF, "RESET Sequence Number"}, + {0,0,NULL} +}; + +static const value_string command_address[]={ + {0x09,"Expansion Module-1 Manager Switch"}, + {0x0A,"Expansion Module-2 Manager Switch"}, + {0x0B,"Expansion Module-3 Manager Switch"}, + {0x0C,"Expansion Module-4 Manager Switch"}, + {0x0D,"Expansion Module-5 Manager Switch"}, + {0x0E,"Expansion Module-6 Manager Switch"}, + {0x10,"Expansion Module Manager Phone"}, + {0x11,"Broadcast Manager Switch"}, + {0x16,"Audio Manager Switch"}, + {0x17,"Display Manager Switch"}, + {0x19,"Key/Indicator Manager Switch"}, + {0x1a,"Basic Manager Switch"}, + {0x1e,"Network Manager Switch"}, + {0x89,"Expansion Module-1 Manager Phone"}, + {0x8A,"Expansion Module-2 Manager Phone"}, + {0x8B,"Expansion Module-3 Manager Phone"}, + {0x8C,"Expansion Module-4 Manager Phone"}, + {0x8D,"Expansion Module-5 Manager Phone"}, + {0x8E,"Expansion Module-6 Manager Phone"}, + {0x91,"Broadcast Manager Phone"}, + {0x96,"Audio Manager Phone"}, + {0x97,"Display Manager Phone"}, + {0x99,"Key/Indicator Manager Phone"}, + {0x9a,"Basic Manager Phone"}, + {0x9e,"Network Manager Phone"}, + {0,NULL} +}; + +static int +dissect_unistim(tvbuff_t *tvb,packet_info *pinfo,proto_tree *tree,void *data _U_){ + gint offset=0; + proto_item *ti= NULL; + proto_tree *overall_unistim_tree = NULL; + proto_tree *rudpm_tree=NULL; + + /* heuristic*/ + switch(tvb_get_guint8(tvb,offset+4)) {/*rudp packet type 0,1,2 only */ + case 0x0:/*NAK*/ + case 0x1:/*ACK*/ + break; + case 0x2:/*PAYLOAD*/ + switch(tvb_get_guint8(tvb,offset+5)){/*payload type 0,1,2,3,ff only */ + case 0x0: /*NULL*/ + case 0x1: /*UNISTIM*/ + case 0x2: /*UNISTIM WITH TERM ID*/ + case 0x3: /*UFTP*/ + case 0xff:/*UNKNOWN BUT VALID*/ + break; + default: + return 0; + } + break; + default: + return 0; + } + + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNISTIM"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo, COL_INFO); + ti = proto_tree_add_item(tree,proto_unistim,tvb,offset,-1,ENC_NA); + overall_unistim_tree = proto_item_add_subtree(ti,ett_unistim); + rudpm_tree=proto_tree_add_subtree(overall_unistim_tree,tvb,offset,5,ett_unistim,NULL,"Reliable UDP"); + + proto_tree_add_item(rudpm_tree,hf_unistim_seq_nu,tvb,offset,4,ENC_BIG_ENDIAN); + + /* Allocate new mem for queueing */ + uinfo = wmem_new(pinfo->pool, unistim_info_t); + + /* Clear tap struct */ + uinfo->rudp_type = 0; + uinfo->payload_type = 0; + uinfo->sequence = tvb_get_ntohl(tvb,offset); + uinfo->termid = 0; + uinfo->key_val = -1; + uinfo->key_state = -1; + uinfo->hook_state = -1; + uinfo->stream_connect = -1; + uinfo->trans_connect = -1; + uinfo->set_termid = -1; + uinfo->string_data = NULL; + uinfo->key_buffer = NULL; + clear_address(&uinfo->it_ip); + clear_address(&uinfo->ni_ip); + uinfo->it_port = 0; + + offset+=4; + proto_tree_add_item(rudpm_tree,hf_unistim_packet_type,tvb,offset,1,ENC_BIG_ENDIAN); + uinfo->rudp_type = tvb_get_guint8(tvb,offset); + + switch(tvb_get_guint8(tvb,offset)) { + case 0x00: + /*NAK*/ + col_add_fstr(pinfo->cinfo, COL_INFO, "NAK for seq - 0x%X", + tvb_get_ntohl(tvb, offset-4)); + break; + case 0x01: + /*ACK*/ + col_add_fstr(pinfo->cinfo, COL_INFO, "ACK for seq - 0x%X", + tvb_get_ntohl(tvb, offset-4)); + break; + case 0x02: + col_add_fstr(pinfo->cinfo, COL_INFO, "Payload seq - 0x%X", + tvb_get_ntohl(tvb, offset-4)); + offset+=1; + dissect_payload(overall_unistim_tree,tvb,offset,pinfo); + break; + default: + return 0; + break; + } + + /* Queue packet for tap */ + tap_queue_packet(unistim_tap, pinfo, uinfo); + return tvb_captured_length(tvb); +} + +static void +dissect_payload(proto_tree *overall_unistim_tree,tvbuff_t *tvb, gint offset, packet_info *pinfo){ + proto_item *ti; + proto_tree *unistim_tree; + guint payload_proto=tvb_get_guint8(tvb,offset); + + /* Payload type for tap */ + uinfo->payload_type = payload_proto; + + ti=proto_tree_add_item(overall_unistim_tree,hf_unistim_payload, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + unistim_tree=proto_item_add_subtree(ti,ett_unistim); + + switch(payload_proto){ + case 0x00: + /*NULL PROTO - NOTHING LEFT TO DO*/ + return; + case 0x01: + /*UNISTIM only so no term id but further payload work*/ + /* Collect info for tap */ + /* If no term id then packet sourced from NI */ + copy_address(&(uinfo->ni_ip), &(pinfo->src)); + copy_address(&(uinfo->it_ip), &(pinfo->dst)); + uinfo->it_port = pinfo->destport; + break; + case 0x02: + /*UNISTIM with term id*/ + /* Termid packs are always sourced from the it, so collect relevant infos */ + copy_address(&(uinfo->ni_ip),&(pinfo->dst)); + copy_address(&(uinfo->it_ip),&(pinfo->src)); + uinfo->it_port = pinfo->srcport; + uinfo->termid = tvb_get_ntohl(tvb,offset); + + proto_tree_add_item(unistim_tree,hf_terminal_id,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4; + break; + case 0x03: + /* UFTP */ + offset = dissect_uftp_message(unistim_tree,pinfo,tvb,offset); + break; + case 0xff: + /*TODO flesh this out probably only for init*/ + break; + } + + /* Handle UFTP seperately because it is significantly different + than standard UNISTIM */ + while (tvb_reported_length_remaining(tvb, offset) > 0) + offset = dissect_unistim_message(unistim_tree,pinfo,tvb,offset); + +} + +static gint +dissect_uftp_message(proto_tree *unistim_tree,packet_info *pinfo _U_,tvbuff_t *tvb,gint offset){ + + guint command; + guint str_len; + guint dat_len; + proto_tree *msg_tree; + + msg_tree = proto_tree_add_subtree(unistim_tree,tvb,offset,-1,ett_unistim,NULL,"UFTP CMD"); + + command=tvb_get_guint8(tvb,offset); + + proto_tree_add_item(msg_tree,hf_uftp_command,tvb,offset,1,ENC_BIG_ENDIAN); + + offset += 1; + + switch(command) + { + case 0x80: + /* Connection request */ + /* Nothing to do */ + break; + + case 0x81: + /* Connection Details */ + /* Get datablock size */ + proto_tree_add_item(msg_tree,hf_uftp_datablock_size,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2; + /* Get datablock limit b4 flow control */ + proto_tree_add_item(msg_tree,hf_uftp_datablock_limit,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + /* Get filename */ + str_len = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(msg_tree,hf_uftp_filename,tvb,offset,str_len,ENC_ASCII|ENC_NA); + offset += str_len; + break; + + case 0x82: + /* Flow Control off */ + /* Nothing to do */ + break; + + case 0x00: + /* Connection Granted */ + /* Nothing to do */ + break; + + case 0x01: + /* Connection Denied */ + /* Nothing to do */ + break; + + case 0x02: + /* File Data Block */ + /* Raw Data.. */ + dat_len = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(msg_tree,hf_uftp_datablock,tvb,offset,dat_len,ENC_NA); + offset += dat_len; + break; + } + + return offset; + +} + + +static gint +dissect_unistim_message(proto_tree *unistim_tree,packet_info *pinfo,tvbuff_t *tvb,gint offset){ + guint addr; + guint msg_len; + proto_item *ti; + proto_tree *msg_tree; + + msg_tree = proto_tree_add_subtree(unistim_tree,tvb,offset,-1,ett_unistim,&ti,"Unistim CMD"); + + addr=tvb_get_guint8(tvb,offset); + + proto_tree_add_item(msg_tree,hf_unistim_cmd_add,tvb,offset,1,ENC_BIG_ENDIAN); + + offset+=1; + msg_len=tvb_get_guint8(tvb,offset); + + if (msg_len<=2) + { + ti=proto_tree_add_item(msg_tree,hf_unistim_len,tvb,offset,1,ENC_BIG_ENDIAN); + expert_add_info(pinfo,ti,&ei_unistim_len); + return tvb_reported_length(tvb); + } else { + proto_item_set_len(ti,msg_len); + proto_tree_add_item(msg_tree,hf_unistim_len,tvb,offset,1,ENC_BIG_ENDIAN); + } + + offset+=1; + /*from switch*/ + switch(addr){ + case 0x00: + /*Nothing*/ + break; + /*Expansion Manager Switch*/ + case 0x09: + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + offset = dissect_expansion_switch(msg_tree,tvb,offset,msg_len-2); + break; + + case 0x11: + /*Broadcast Manager Switch*/ + offset = dissect_broadcast_switch(msg_tree,tvb,offset,msg_len-2); + break; + case 0x16: + /*Audio Manager Switch*/ + offset = dissect_audio_switch(msg_tree,pinfo,tvb,offset,msg_len-2); + break; + case 0x17: + /*Display Manager Switch*/ + offset = dissect_display_switch(msg_tree,pinfo,tvb,offset,msg_len-2); + break; + case 0x19: + /*Key Indicator Manager Switch*/ + offset = dissect_key_indicator_switch(msg_tree,tvb,offset,msg_len-2); + break; + case 0x1a: + /*Basic Manager Switch*/ + offset = dissect_basic_switch(msg_tree,tvb,offset,msg_len-2); + break; + case 0x1e: + /*Network Manager Switch*/ + offset = dissect_network_switch(msg_tree,tvb,offset,msg_len-2); + break; + case 0x89: + case 0x8A: + case 0x8B: + case 0x8C: + case 0x8D: + case 0x8E: + /*Expansion Manager Phone*/ + offset = dissect_expansion_phone(msg_tree,tvb,offset,msg_len-2); + break; + + case 0x91: + /*Broadcast Manager phone*/ + offset = dissect_broadcast_phone(msg_tree,tvb,offset,msg_len-2); + break; + case 0x96: + /*Audio Manager phone*/ + offset = dissect_audio_phone(msg_tree,tvb,offset,msg_len-2); + break; + case 0x97: + /*Display Manager phone*/ + offset = dissect_display_phone(msg_tree,tvb,offset,msg_len-2); + break; + case 0x99: + /*Key/Indicator Manager phone*/ + offset = dissect_key_indicator_phone(msg_tree,tvb,offset,msg_len-2); + break; + case 0x9a: + /*Basic Manager phone*/ + offset = dissect_basic_phone(msg_tree,tvb,offset,msg_len-2); + break; + case 0x9e: + /*Network Manager Switch*/ + offset = dissect_network_phone(msg_tree,tvb,offset,msg_len-2); + break; + default: + /*See some undocumented messages. Don't want to miss the ones we understand*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len-2,ENC_NA); + + offset+=(msg_len-2); + } + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + return offset; +} + + + /*DONE*/ +static gint +dissect_basic_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset, guint msg_len){ + guint basic_cmd; + + basic_cmd=tvb_get_guint8(tvb,offset); + + proto_tree_add_item(msg_tree,hf_basic_phone_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + + offset+=1;msg_len-=1; + switch(basic_cmd){ + + case 0x00: + /*Basic Manager Attributes Info*/ + proto_tree_add_item(msg_tree,hf_basic_phone_eeprom_stat_cksum, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_basic_phone_eeprom_dynam, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_basic_phone_eeprom_net_config_cksum, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x01: + /*Basic Manager Options Report*/ + proto_tree_add_item(msg_tree,hf_basic_switch_options_secure, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x02: + /*Firmware Version*/ + proto_tree_add_item(msg_tree,hf_basic_phone_fw_ver, + tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=msg_len; + break; + case 0x03: + /*IT Type*/ + proto_tree_add_item(msg_tree,hf_basic_it_type,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x07: + /*Hardware ID*/ + proto_tree_add_item(msg_tree,hf_basic_phone_hw_id, + tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x08: + /*Product Engineering Code*/ + proto_tree_add_item(msg_tree,hf_basic_prod_eng_code, + tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=msg_len; + break; + case 0x09: + /*Grey Market Info*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0a: + /*Encapsulate Command*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x11: + /*Phone Ethernet address*/ + proto_tree_add_item(msg_tree,hf_basic_ether_address, + tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0b: + /*not in pdf but get them*/ + proto_tree_add_item(msg_tree,hf_generic_string,tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=msg_len; + break; + case 0xff: + /*Reserved*/ + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + /*DONE*/ +static gint +dissect_basic_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len){ + guint basic_cmd; + basic_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_basic_switch_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(basic_cmd){ + case 0x01: + /*Query Basic Manager*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_basic_switch_query_attr, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_basic_switch_query_opts, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_basic_switch_query_fw, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_basic_switch_query_hw_id, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_basic_switch_query_it_type, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_basic_switch_query_prod_eng_code, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_basic_switch_query_gray_mkt_info, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x02: + /*Basic Manager Options*/ + proto_tree_add_item(msg_tree,hf_basic_switch_options_secure, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x06: + /*EEprom Write*/ + proto_tree_add_item(msg_tree,hf_basic_switch_element_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_basic_switch_eeprom_data, + tvb,offset,msg_len,ENC_NA); + offset+=1; + break; + case 0x07: + /*Assign Terminal ID*/ + /* Set tap info */ + uinfo->set_termid = 1; + + proto_tree_add_item(msg_tree,hf_basic_switch_terminal_id, + tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=msg_len; + break; + case 0x08: + /*Encapsulate Command*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0f: + /*showing up in captures but not in pdf*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + case 0xff: + /*Reserved*/ + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + + + /*DONE*/ +static gint +dissect_broadcast_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset, guint msg_len){ + guint bcast_cmd; + guint year,month,day,hour,minute,second; + proto_tree *date_tree; + proto_tree *time_tree; + bcast_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_broadcast_switch_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(bcast_cmd){ + case 0x00: + /*Accessory Sync Update - len=3 */ + break; + case 0x01: + /*Logical Icon Update*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_state, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_cadence, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x02: + /*Time and Date Download*/ + year=tvb_get_guint8(tvb,offset); + month=tvb_get_guint8(tvb,offset+1); + day=tvb_get_guint8(tvb,offset+2); + hour=tvb_get_guint8(tvb,offset+3); + minute=tvb_get_guint8(tvb,offset+4); + second=tvb_get_guint8(tvb,offset+5); + date_tree=proto_tree_add_subtree_format(msg_tree,tvb,offset,3,ett_unistim,NULL, + "Date %i/%i/%i",month,day,year%100); + proto_tree_add_item(date_tree,hf_broadcast_year,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(date_tree,hf_broadcast_month,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(date_tree,hf_broadcast_day,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + + time_tree=proto_tree_add_subtree_format(msg_tree,tvb,offset,3,ett_unistim,NULL, + "Time %i:%i:%i",hour,minute,second); + proto_tree_add_item(time_tree,hf_broadcast_hour,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(time_tree,hf_broadcast_minute,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(time_tree,hf_broadcast_second,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x03: + /*Set Default Character Table Config */ + /* UGLY may work may not*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0xff: + /*Reserved*/ + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + /*DONE Haven't seen any phone broadcasts, wouldn't expect to*/ +static gint +dissect_broadcast_phone(proto_tree *msg_tree, + tvbuff_t *tvb, gint offset,guint msg_len){ + + proto_tree_add_item(msg_tree,hf_generic_data, tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + + return offset; +} + + /*DONE*/ +static gint +dissect_display_switch(proto_tree *msg_tree, packet_info *pinfo, + tvbuff_t *tvb, gint offset,guint msg_len){ + guint clear_mask; + guint highlight_cmd; + guint time_date_mask; + guint display_cmd; + guint address_byte; + guint movement_byte; + proto_tree *address_tree; + display_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_display_switch_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + + switch(display_cmd){ + case 0x01: + /*Restore Default Character Table Configuration length = 3*/ + break; + case 0x04: + /*Arrow*/ + proto_tree_add_item(msg_tree,hf_display_arrow,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x05: + /*Query Status Bar Icon*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x06: + /*Highlight Off length = 3*/ + break; + case 0x07: + /*Highlight On length = 3*/ + break; + case 0x09: + /*Restore Time and Date length = 3*/ + break; + case 0x0a: + /*Clear Time and Date length = 3*/ + break; + case 0x0b: + /*Call Duration Timer*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_call_timer_mode,tvb,offset, + 1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_call_timer_reset,tvb,offset, + 1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_call_timer_display,tvb,offset, + 1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_call_timer_delay,tvb,offset, + 1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_call_timer_id,tvb,offset, + 1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0c: + /*Query Display Manager*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0d: + /*Download Call Duration Timer Delay*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0e: + /*Disable Display Field*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0f: + /*Clear Field*/ + clear_mask=tvb_get_guint8(tvb,offset); + /*need to know which paths to take*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_numeric, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_context, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_date, + tvb,offset,1,ENC_BIG_ENDIAN); + + proto_tree_add_item(msg_tree,hf_display_clear_time, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_softkey, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_softkey_label, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if((clear_mask&DISPLAY_CLEAR_LINE)==DISPLAY_CLEAR_LINE){ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line_1, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line_2, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line_3, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line_4, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line_5, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line_6, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line_7, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_line_8, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + if((clear_mask&DISPLAY_CLEAR_STATUS_BAR_ICON)== + DISPLAY_CLEAR_STATUS_BAR_ICON){ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon_1, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon_2, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon_3, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon_4, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon_5, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon_6, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon_7, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_status_bar_icon_8, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + if((clear_mask&DISPLAY_CLEAR_SOFTKEY)==DISPLAY_CLEAR_SOFTKEY){ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_soft_key_1, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_soft_key_2, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_soft_key_3, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_soft_key_4, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_soft_key_5, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_soft_key_6, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_soft_key_7, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_soft_key_8, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + if((clear_mask&DISPLAY_CLEAR_SOFTKEY_LABEL)==DISPLAY_CLEAR_SOFTKEY_LABEL){ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_sk_label_key_id,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_clear_all_slks,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x10: + /*Cursor Control*/ + movement_byte=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_move_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_blink,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if(msg_len==0){ + /*turn cursor off*/ + break; + } + if((movement_byte&0x01)==0x01){ + address_byte=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_address_numeric, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_address_context, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_address_line, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_address_soft_key, + tvb,offset,1,ENC_BIG_ENDIAN); + if((address_byte&DISPLAY_WRITE_ADDRESS_SOFT_KEY_FLAG)== + DISPLAY_WRITE_ADDRESS_SOFT_KEY_FLAG) + proto_tree_add_item(msg_tree, + hf_display_write_address_softkey_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if(msg_len==0){ + /*turn cursor off*/ + break; + } + } + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_address_char_pos, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_address_line_number, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x12: + /*Display Scroll with Data (before)*/ + proto_tree_add_item(msg_tree,hf_generic_string,tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=msg_len; + break; + case 0x13: + /*Display Scroll with Data (after)*/ + proto_tree_add_item(msg_tree,hf_generic_string,tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=msg_len; + break; + case 0x14: + /*Status Bar Icon Update*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field, tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_icon_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_basic_bit_field, tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_state, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_cadence, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x15: + /*Month Labels Download*/ + proto_tree_add_item(msg_tree,hf_generic_string,tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=msg_len; + break; + case 0x16: + /*Call Duration Timer Label Download*/ + proto_tree_add_item(msg_tree,hf_generic_string,tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=1;msg_len-=1; + break; + case 0x17: + /*Time and Date Format*/ + time_date_mask=tvb_get_guint8(tvb,offset); + if((time_date_mask&DISPLAY_USE_TIME_FORMAT)==DISPLAY_USE_TIME_FORMAT){ + proto_tree_add_item(msg_tree,hf_display_time_format,tvb,offset,1,ENC_BIG_ENDIAN); + } + if((time_date_mask&DISPLAY_USE_DATE_FORMAT)==DISPLAY_USE_DATE_FORMAT){ + proto_tree_add_item(msg_tree,hf_display_date_format,tvb,offset,1,ENC_BIG_ENDIAN); + } + proto_tree_add_item(msg_tree,hf_display_use_time_format,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_use_date_format,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + /*Address, control, tag: treat as bitmask to reduce code duplication*/ + case 0x18: /*address|no control|no tag|no*/ + case 0x19: /*address|yes control|no tag|no*/ + case 0x1A: /*address|no control|yes tag|no*/ + case 0x1B: /*address|yes control|yes tag|no*/ + case 0x1C: /*address|no control|no tag|yes*/ + case 0x1D: /*address|yes control|no tag|yes*/ + case 0x1E: /*address|no control|yes tag|yes*/ + case 0x1F: /*address|yes control|yes tag|yes*/ +#define F_ADDR 1 +#define F_CTRL 2 +#define F_TAG 4 + if((display_cmd&F_ADDR)==F_ADDR){ + address_tree=proto_tree_add_subtree(msg_tree,tvb,offset,0,ett_unistim,NULL,"Address Data"); + address_byte=tvb_get_guint8(tvb,offset); + proto_tree_add_item(address_tree,hf_basic_bit_field, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(address_tree,hf_display_write_address_numeric, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(address_tree,hf_display_write_address_context, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(address_tree,hf_display_write_address_line, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(address_tree,hf_display_write_address_soft_key, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(address_tree,hf_display_write_address_soft_label, + tvb,offset,1,ENC_BIG_ENDIAN); + + if((address_byte&DISPLAY_WRITE_ADDRESS_SOFT_KEY_FLAG)== + DISPLAY_WRITE_ADDRESS_SOFT_KEY_FLAG){ + proto_tree_add_item(address_tree, + hf_display_write_address_softkey_id, + tvb,offset,1,ENC_BIG_ENDIAN); + } + offset+=1;msg_len-=1; + if((address_byte&DISPLAY_WRITE_ADDRESS_SOFT_LABEL_FLAG)== + DISPLAY_WRITE_ADDRESS_SOFT_LABEL_FLAG){ + proto_tree_add_item(address_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(address_tree, + hf_display_write_address_char_pos, + tvb,offset,1,ENC_BIG_ENDIAN); + if((address_byte&DISPLAY_WRITE_ADDRESS_LINE_FLAG)!= + DISPLAY_WRITE_ADDRESS_LINE_FLAG){ + offset+=1;msg_len-=1; + } + } + if((address_byte&DISPLAY_WRITE_ADDRESS_LINE_FLAG)== + DISPLAY_WRITE_ADDRESS_LINE_FLAG){ + proto_tree_add_item(address_tree, + hf_display_write_address_char_pos, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(address_tree, + hf_display_write_address_line_number, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + } + if((display_cmd&F_CTRL)==F_CTRL){ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_cursor_move, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_clear_left, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_clear_right, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_shift_left, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_shift_right, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_write_highlight, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + if((display_cmd&F_TAG)==F_TAG){ + proto_tree_add_item(msg_tree,hf_display_write_tag,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + /* whatever's left is the message */ + if(msg_len>0){ + /* I'm guessing this will work flakily at best */ + proto_tree_add_item_ret_string(msg_tree,hf_generic_string,tvb,offset,msg_len, ENC_ASCII|ENC_NA, pinfo->pool, &uinfo->string_data); + offset+=msg_len; + } + break; +#undef F_ADDR +#undef F_CTRL +#undef F_TAG + case 0x20: + /*Context Info Bar Format*/ + while(msg_len>0){ + proto_tree_add_item(msg_tree,hf_display_context_format,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_context_field,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x21: + /*Set Default Character Table Configuration VERY UGLY*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x22: + /*Special Character Download*/ + proto_tree_add_item(msg_tree,hf_display_char_address,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x23: + /*Highlighted Field Definition*/ + highlight_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_display_cursor_numeric,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_context ,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_line,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_softkey,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_softkey_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1;proto_tree_add_item(msg_tree,hf_display_hlight_start,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_hlight_end,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if(msg_len==0) + break; + if((highlight_cmd&DISPLAY_CURSOR_LINE)==DISPLAY_CURSOR_LINE){ + proto_tree_add_item(msg_tree,hf_display_cursor_char_pos,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_line_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x24: + /*Contrast*/ + proto_tree_add_item(msg_tree,hf_display_contrast,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x25: + /*Caller Log Download*/ + proto_tree_add_item(msg_tree,hf_broadcast_hour,tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_broadcast_minute,tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x30: + /*Layered Softkey Text Download*/ + proto_tree_add_item(msg_tree,hf_display_layer_skey_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_layer_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_generic_string,tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=msg_len; + break; + case 0x31: + /*Layered Softkey Clear*/ + proto_tree_add_item(msg_tree,hf_display_layer_skey_id,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_layer_all_skeys,tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_layer_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x32: + /*Set Visible Softkey Layer*/ + proto_tree_add_item(msg_tree,hf_display_layer_skey_id,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_layer_all_skeys,tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_layer_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x33: + /*Layered Softkey Cadence Download*/ + proto_tree_add_item(msg_tree,hf_display_layer_skey_id,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_once_or_cyclic,tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + while(msg_len>0){ + proto_tree_add_item(msg_tree,hf_display_layer_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_layer_duration,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x34: + /*Layered Softkey Cadencing On*/ + proto_tree_add_item(msg_tree,hf_display_layer_skey_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x35: + /*Layered Softkey Cadencing Off*/ + proto_tree_add_item(msg_tree,hf_display_layer_skey_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0xff: + /*Reserved*/ + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data, + tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + /*DONE*/ +static gint +dissect_display_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len){ + guint display_cmd; + guint highlight_cmd; + display_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_display_phone_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(display_cmd){ + case 0x00: + /*Display Manager Attributes Info*/ + proto_tree_add_item(msg_tree,hf_display_line_width,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_lines,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_softkey_width,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_softkeys,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_icon,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_softlabel_key_width,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_context_width,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_numeric_width,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_time_width,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_date_width,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_char_dload,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_freeform_icon_dload,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_icon_type,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_charsets,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + + break; + case 0x01: + /*Contrast Level Report*/ + proto_tree_add_item(msg_tree,hf_display_contrast,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x02: + /*Cursor Location Report*/ + proto_tree_add_item(msg_tree,hf_display_cursor_numeric,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_context ,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_line,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_softkey,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_softkey_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_cursor_char_pos,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_line_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x03: + /*Highlight Status On*/ + highlight_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_display_cursor_numeric,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_context ,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_line,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_softkey,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_softkey_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1;proto_tree_add_item(msg_tree,hf_display_hlight_start,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_display_hlight_end,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if((highlight_cmd&DISPLAY_CURSOR_LINE)==DISPLAY_CURSOR_LINE){ + proto_tree_add_item(msg_tree,hf_display_cursor_char_pos,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_cursor_line_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x04: + /*Current Character Table Configuration Status VERY UGLY*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x05: + /*Default Character Table Configuration Status VERY UGLY*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x06: + /*Timer And Date Format Report*/ + proto_tree_add_item(msg_tree,hf_display_time_format,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_display_date_format,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x07: + /*Status Bar Icon State Report*/ + proto_tree_add_item(msg_tree,hf_icon_id,tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_broadcast_icon_state,tvb,offset,msg_len,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_cadence,tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0a: + /*Highlight Status Off length = 3*/ + break; + case 0xff: + /*Reserved*/ + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + + +static gint +dissect_key_indicator_switch(proto_tree *msg_tree, + tvbuff_t *tvb, gint offset,guint msg_len){ + guint key_cmd; + key_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_key_switch_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(key_cmd){ + case 0x00: + /*LED Update*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_key_led_cadence,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_key_led_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x01: + /*Query Hookswitch length = 3 */ + break; + case 0x02: + /*User Activity Timer Stop length = 3*/ + break; + case 0x03: + /*User Activity Timer Start length = 3*/ + break; + case 0x04: + /*Downloadable Free Form Icon Access (Hardcoded) length of 3*/ + break; + case 0x05: + /*Downloadable Free Form Icon Access (Downloadable) length of 3*/ + break; + case 0x06: + /*Query Key/Indicator Manager*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x07: + /*Key/Indicator Manager Options*/ + proto_tree_add_item(msg_tree,hf_keys_send_key_rel,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_enable_vol,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_conspic_prog_key,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_acd_super_control,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_local_dial_feedback,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x08: + /*Logical Icon Mapping*/ + proto_tree_add_item(msg_tree,hf_key_icon_id,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_admin_command,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_keys_logical_icon_id,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + break; + case 0x09: + /*Key Repeat Timer Download*/ + proto_tree_add_item(msg_tree,hf_keys_repeat_timer_one,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_keys_repeat_timer_two,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0a: + /*Query LED State*/ + proto_tree_add_item(msg_tree,hf_keys_led_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0b: + /*Query Phone Icon State*/ + proto_tree_add_item(msg_tree,hf_keys_phone_icon_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0c: + /*Indicator Cadence Download*/ + while(msg_len>0){ + proto_tree_add_item(msg_tree,hf_keys_cadence_on_time,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_keys_cadence_off_time,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x0d: + /*User Activity Timer Download*/ + proto_tree_add_item(msg_tree,hf_keys_user_activity_timeout,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0e: + /*Free Form Icon Download*/ + proto_tree_add_item(msg_tree,hf_key_icon_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0f: + /*Phone Icon Update*/ + proto_tree_add_item(msg_tree,hf_key_icon_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_state,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_cadence,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0xff: + /*Reserved*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + +/*DONE*/ +static gint +dissect_key_indicator_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset, guint msg_len){ + guint key_cmd; + key_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_key_phone_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(key_cmd){ + case 0x00: + /*Key Event*/ + /* Set the tap info */ + uinfo->key_state = tvb_get_guint8(tvb,offset); + uinfo->key_state >>= 6; + /* Extract the key code */ + uinfo->key_val = (tvb_get_guint8(tvb,offset) & 0x3F); + + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_key_code,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_key_command,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x01: + /*LED Status Report*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x03: + /*On Hook length = 3*/ + /* Set tap info.. */ + uinfo->hook_state = 0; + + break; + case 0x04: + /*Off Hook length = 3*/ + /* Set tap info.. */ + uinfo->hook_state = 1; + + break; + case 0x05: + /*User Activity Timer Expired length = 3*/ + break; + case 0x06: + /*Hookswitch State (on hook) length = 3*/ + break; + case 0x07: + /*Hookswitch State (off hook) length = 3*/ + break; + case 0x08: + /*Key/Indicator Manager Attributes Info*/ + proto_tree_add_item(msg_tree,hf_key_programmable_keys,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_soft_keys,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_keys_hd_key,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_mute_key,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_quit_key,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_copy_key,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_mwi_key,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_keys_num_nav_keys,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_num_conspic_keys,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + + break; + case 0x09: + /*Key/Indicator Manager Options Report*/ + proto_tree_add_item(msg_tree,hf_keys_send_key_rel,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_enable_vol,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_conspic_prog_key,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_acd_super_control,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_keys_local_dial_feedback,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0a: + /*Phone Icon Status Report*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0xff: + /*Reserved*/ + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + + +/*Done*/ +static gint +dissect_network_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset, guint msg_len){ + guint network_cmd; + guint string_len; + + network_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_network_switch_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(network_cmd){ + case 0x02: + /*Soft Reset done*/ + break; + case 0x03: + /*Hard Reset done*/ + break; + case 0x04: + /*Query Network Manager*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_diag_flag,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_managers_flag,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_attributes_flag,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_serv_info_flag,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_options_flag,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_sanity_flag,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x05: + /*Network Manager Options*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_enable_diag,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_enable_rudp,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x06: + /*QoS Configuration*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x09: + /*Set RTCP Source Description Item*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0b: + /*Download Server Information*/ + proto_tree_add_item(msg_tree,hf_net_server_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_net_server_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2; + proto_tree_add_item(msg_tree,hf_net_server_action,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_net_server_retry_count,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_net_server_failover_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_net_server_ip_address,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4; + break; + case 0x0c: + /*Server Switch*/ + proto_tree_add_item(msg_tree,hf_net_server_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x0d: + /*Query Network Configuration Element*/ + proto_tree_add_item(msg_tree,hf_net_server_config_element, + tvb,offset-1,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x0e: + /*Download Software Upgrade*/ + proto_tree_add_item(msg_tree,hf_net_file_xfer_mode,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_force_download,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_use_file_server_port,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_use_local_port,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,1,ENC_NA); + offset+=1;msg_len-=1; + string_len=tvb_strsize(tvb,offset); + proto_tree_add_item(msg_tree,hf_net_full_pathname,tvb,offset,string_len,ENC_ASCII|ENC_NA); + offset+=string_len;msg_len-=string_len; + string_len=tvb_strsize(tvb,offset); + proto_tree_add_item(msg_tree,hf_net_file_identifier,tvb,offset,string_len,ENC_ASCII|ENC_NA); + offset+=string_len;msg_len-=string_len; + proto_tree_add_item(msg_tree,hf_net_file_server_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_net_local_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_net_file_server_address,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + break; + case 0x0f: + /*Set RTCP Report Interval*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x10: + /*Set Primary Server*/ + proto_tree_add_item(msg_tree,hf_net_server_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x12: + /*Reset Watchdog*/ + proto_tree_add_item(msg_tree,hf_net_server_time_out, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2; + break; + case 0x13: + /*Set Recovery Procedure Time Interval*/ + proto_tree_add_item(msg_tree,hf_net_server_recovery_time_low, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2; + proto_tree_add_item(msg_tree,hf_net_server_recovery_time_high, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2; + break; + case 0x14: + /*Transport Reliability Layer Parameters Download*/ + proto_tree_add_item(msg_tree,hf_generic_data, + tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0xff: + /*Reserved*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + +/*DONE*/ +static gint +dissect_expansion_switch(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset, guint msg_len){ + guint expansion_cmd; + + + expansion_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_expansion_switch_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; msg_len-=1; + switch(expansion_cmd){ + case 0x17: + break; + case 0x57: + /*skip a byte for now, not sure what it means*/ + offset+=1; + msg_len-=1; + + + proto_tree_add_item(msg_tree,hf_expansion_softlabel_number,tvb, + offset,1,ENC_BIG_ENDIAN); + offset+=1; + msg_len-=1; + + proto_tree_add_item(msg_tree,hf_generic_string,tvb,offset,msg_len,ENC_ASCII|ENC_NA); + break; + case 0x59: + /*skip a byte for now, not sure what it means*/ + offset+=1; + msg_len-=1; + proto_tree_add_item(msg_tree,hf_expansion_softlabel_number,tvb, + offset,1,ENC_BIG_ENDIAN); + offset+=1; + msg_len-=1; + proto_tree_add_item(msg_tree,hf_basic_bit_field, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_state, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_broadcast_icon_cadence, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + msg_len-=1; + break; + } + offset+=msg_len; + return offset; +} + +static gint +dissect_expansion_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset, guint msg_len){ + guint expansion_cmd; + guint key_number; + + expansion_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_expansion_phone_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; msg_len-=1; + key_number=(tvb_get_guint8(tvb,offset))-64; + + switch(expansion_cmd){ + case 0x59: + proto_tree_add_int(msg_tree,hf_module_key_number,tvb,offset,1,key_number); + offset+=1; + msg_len-=1; + break; + } + offset+=msg_len; + return offset; +} + +static gint +dissect_network_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset, guint msg_len){ + guint network_cmd; + proto_tree *server_tree; + guint i; + network_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_network_phone_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(network_cmd){ + case 0x00: + /*Soft Reset Ack done length = 3*/ + break; + case 0x01: + /*Sanity OK done length = 3*/ + break; + case 0x02: + /*Network Manager Attributes Info*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x03: + /*Network Manager Diagnostic Info*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_phone_rx_ovr_flag, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_phone_tx_ovr_flag, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_phone_rx_empty_flag, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_phone_invalid_msg_flag, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_phone_eeprom_insane_flag, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_net_phone_eeprom_unsafe_flag, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x04: + /*Manager IDs*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x05: + /*Network Manager Options Report*/ + proto_tree_add_boolean(msg_tree,hf_net_phone_diag,tvb,offset,1,FALSE); + proto_tree_add_item(msg_tree,hf_net_phone_rudp,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x08: + /*Resume Connection with Server done*/ + break; + case 0x09: + /*Suspend Connection with Server done*/ + break; + case 0x0b: + /*Network Configuration Element Report*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0c: + /*Server Information Report*/ + proto_tree_add_item(msg_tree,hf_net_phone_primary_server_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + for (i=1; msg_len>8; i++){ + /*if less than 9 not full report so punt*/ +/* guint16 port_num; + port_num=tvb_get_ntohs(tvb,offset); + if(port_num<1064) + break; +*/ + server_tree=proto_tree_add_subtree_format(msg_tree,tvb,offset,9, + ett_unistim,NULL,"Server (S%d) Server ID: %X",i,i-1); + proto_tree_add_item(server_tree, + hf_net_phone_server_port, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(server_tree, + hf_net_phone_server_action, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(server_tree, + hf_net_phone_server_retry_count, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(server_tree, + hf_net_phone_server_failover_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(server_tree,hf_net_phone_server_ip, + tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + } + break; + case 0xff: + /*Reserved*/ + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} +/*DONE*/ +static gint +dissect_audio_switch(proto_tree *msg_tree,packet_info *pinfo, + tvbuff_t *tvb,gint offset,guint msg_len){ + proto_tree *param_tree; + guint audio_cmd; + guint apb_op_code; + guint apb_data_len; + guint vocoder_param; + audio_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_audio_switch_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(audio_cmd){ + case 0x00: + /*Query Audio Manager*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_attr,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_opts,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_alert,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_adj_rx_vol,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_def_rx_vol,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_handset,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_headset,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_audio_default_rx_vol_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x01: + /*Query Supervisor Headset Status*/ + /*done*/ + break; + case 0x02: + /*Audio Manager Options*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_opt_max_vol, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_opt_adj_vol, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_opt_aa_rx_vol_rpt, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_opt_hs_on_air, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_opt_hd_on_air, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_opt_noise_squelch, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x04: + /*Mute/Unmute*/ + while(msg_len>0){ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_mute,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_tx_rx,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_mgr_stream_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x10: + /*Transducer Based Tone On*/ + proto_tree_add_item(msg_tree, + hf_audio_mgr_transducer_based_tone_id, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_attenuated, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x11: + /*Transducer Based Tone Off*/ + proto_tree_add_item(msg_tree,hf_audio_mgr_transducer_based_tone_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x12: + /*Alerting Tone Configuration*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_warbler_select, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_transducer_routing, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_tone_vol_range, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_cadence_select, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x13: + /*Special Tone Configuration*/ + proto_tree_add_item(msg_tree,hf_audio_mgr_transducer_routing, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_audio_mgr_tone_vol_range, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_audio_special_tone,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x14: + /*Paging Tone Configuration*/ + proto_tree_add_item(msg_tree,hf_audio_mgr_transducer_routing, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_audio_mgr_tone_vol_range, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_mgr_cadence_select, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x15: + /*Alerting Tone Cadence Download*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + /*TODO UGLY*/ + case 0x17: + /*Paging Tone Cadence Download*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + /*TODO UGLY*/ + case 0x18: + /*Transducer Based Tone Volume Level*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree, + hf_audio_mgr_transducer_based_tone_id, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_tone_level,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x1a: + /*Visual Transducer Based Tone Enable*/ + proto_tree_add_item(msg_tree,hf_audio_visual_tones, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x1b: + /*Stream Based Tone On*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_stream_based_tone_id, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_stream_based_tone_rx_tx, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_stream_based_tone_mute, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_audio_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_audio_stream_based_volume,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x1c: + /*Stream Based Tone Off*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_stream_based_tone_id, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_stream_based_tone_rx_tx, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + proto_tree_add_item(msg_tree,hf_audio_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x1d: + /*Stream Based Tone Frequency Component List Download*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x1e: + /*Stream Based Tone Cadence Download*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x20: + /*Select Adjustable Rx Volume*/ + proto_tree_add_item(msg_tree,hf_audio_default_rx_vol_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x21: + /*Set APB's Rx Volume Level*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x22: + /*Change Adjustable Rx Volume (quieter) DONE*/ + proto_tree_add_item(msg_tree,hf_generic_data, + tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x23: + /*Change Adjustable Rx Volume (louder) DONE*/ + proto_tree_add_item(msg_tree,hf_generic_data, + tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x24: + /*Adjust Default Rx Volume(quieter)*/ + proto_tree_add_item(msg_tree,hf_audio_default_rx_vol_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x25: + /*Adjust Default Rx Volume(louder)*/ + proto_tree_add_item(msg_tree,hf_audio_default_rx_vol_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1; + break; + case 0x28: + /*APB Download*/ + proto_tree_add_item(msg_tree,hf_audio_apb_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + while(msg_len>0){ + apb_op_code=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_audio_apb_op_code,tvb, + offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if(apb_op_code>0x39){ + /*should have a len + data*/ + apb_data_len=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_audio_apb_param_len,tvb, + offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_apb_data,tvb, + offset,apb_data_len,ENC_NA); + offset+=apb_data_len;msg_len-=apb_data_len; + } + } + break; + case 0x30: + /*Open Audio Stream*/ + /* Set the tap info */ + uinfo->stream_connect = 1; + + proto_tree_add_item(msg_tree,hf_audio_rx_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_tx_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_rx_vocoder_type,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_tx_vocoder_type,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_frames_per_packet,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_tos,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_precedence,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_frf_11,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_rtcp_bucket_id, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_generic_data, + tvb,offset,4,ENC_NA); + offset+=4;msg_len-=4; + proto_tree_add_item(msg_tree,hf_audio_lcl_rtp_port, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_lcl_rtcp_port, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + + proto_tree_add_item(msg_tree,hf_audio_far_rtp_port, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_far_rtcp_port, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + + /* Sometimes the open stream does not specify an endpoint */ + /* In this circumstance the packet is truncated at the far end */ + /* rtp port */ + if(msg_len > 0){ + proto_tree_add_item(msg_tree,hf_audio_far_ip_add,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + { + guint32 far_ip_addr; + address far_addr; + guint16 far_port; + + far_ip_addr = tvb_get_ipv4(tvb, offset-4); + set_address(&far_addr, AT_IPv4, 4, &far_ip_addr); + + far_port = tvb_get_ntohs(tvb, offset-8); + rtp_add_address(pinfo, PT_UDP, &far_addr, far_port, 0, "UNISTIM", pinfo->num, FALSE, NULL); + + far_port = tvb_get_ntohs(tvb, offset-6); + rtcp_add_address(pinfo, &far_addr, far_port, 0, "UNISTIM", pinfo->num); + } + } + break; + case 0x31: + /*Close Audio Stream*/ + /* Set the tap info */ + uinfo->stream_connect = 0; + + proto_tree_add_item(msg_tree,hf_audio_rx_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_tx_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x32: + /*Connect Transducer*/ + /* Tap info again */ + uinfo->trans_connect = 1; + + proto_tree_add_item(msg_tree,hf_basic_bit_field, tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_transducer_pair,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_enable,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_tx_enable,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_basic_bit_field, tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_apb_number,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_sidetone_disable,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_destruct_additive,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_dont_force_active,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + while(msg_len>0){ + proto_tree_add_item(msg_tree,hf_audio_mgr_stream_id,tvb,offset,1,ENC_LITTLE_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x34: + /*Filter Block Download*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x37: + /*Query RTCP Statistics*/ + proto_tree_add_item(msg_tree,hf_audio_rtcp_bucket_id,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_clear_bucket,tvb,offset,1,ENC_BIG_ENDIAN); + + offset+=1;msg_len-=1; + break; + case 0x38: + /*Configure Vocoder Parameters*/ + proto_tree_add_item(msg_tree,hf_audio_mgr_stream_id,tvb,offset,1,ENC_LITTLE_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_vocoder_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + while(msg_len>0){ + param_tree=proto_tree_add_subtree(msg_tree,tvb,offset,0,ett_unistim,NULL,"Param"); + vocoder_param=tvb_get_guint8(tvb,offset); + proto_tree_add_item(param_tree,hf_basic_bit_field, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(param_tree,hf_audio_vocoder_param, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(param_tree,hf_audio_vocoder_entity, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if((vocoder_param&0x0a)==0x0a){ + proto_tree_add_item(param_tree,hf_audio_vocoder_annexa, + tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(param_tree,hf_audio_vocoder_annexb, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + else if((vocoder_param&0x0b)==0x0b){ + proto_tree_add_item(param_tree,hf_audio_sample_rate, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + else if((vocoder_param&0x0c)==0x0c){ + proto_tree_add_item(param_tree,hf_audio_rtp_type, + tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + else if((vocoder_param&0x20)==0x20){ + proto_tree_add_item(param_tree,hf_audio_bytes_per_frame, + tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + } + } + break; + case 0x39: + /*Query RTCP Bucket's SDES Information*/ + proto_tree_add_item(msg_tree,hf_audio_source_descr,tvb,offset,msg_len,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_sdes_rtcp_bucket,tvb,offset,msg_len,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x3a: + /*Jitter Buffer Parameters Configuration*/ + proto_tree_add_item(msg_tree,hf_audio_rx_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_desired_jitter,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_high_water_mark,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_early_packet_resync_thresh,tvb, + offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + proto_tree_add_item(msg_tree,hf_audio_late_packet_resync_thresh,tvb, + offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + break; + case 0x3b: + /*Resolve Port Mapping*/ + proto_tree_add_item(msg_tree,hf_audio_resolve_phone_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_far_end_echo_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_far_end_ip_address,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + break; + case 0x3c: + /*Port Mapping Discovery Ack*/ + proto_tree_add_item(msg_tree,hf_audio_nat_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_nat_ip_address,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + break; + case 0x3d: + /*Query Audio Stream Status*/ + proto_tree_add_item(msg_tree,hf_audio_direction_code,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_mgr_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0xff: + /*Reserved*/ + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + +/*DONE*/ +static gint +dissect_audio_phone(proto_tree *msg_tree, + tvbuff_t *tvb,gint offset,guint msg_len){ + guint audio_cmd; + guint apb_op_code; + guint apb_data_len; + guint stream_dir; + guint stream_state; + audio_cmd=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_audio_phone_cmd,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + switch(audio_cmd){ + case 0x00: + /*Handset Connected length =3*/ + /* Set the tap info */ + uinfo->hook_state = 1; + break; + case 0x01: + /*Handset Disconnected length =3*/ + /* Set the tap info */ + uinfo->hook_state = 0; + break; + case 0x02: + /*Headset Connected length =3*/ + /* Set the tap info */ + uinfo->hook_state = 1; + break; + case 0x03: + /*Headset Disconnected length =3*/ + /* Set the tap info */ + uinfo->hook_state = 0; + break; + case 0x04: + /*Supervisor Headset Connected length =3*/ + /* Set the tap info */ + uinfo->hook_state = 1; + break; + case 0x05: + /*Supervisor Headset Disconnected length =3*/ + /* Set the tap info */ + uinfo->hook_state = 0; + break; + case 0x07: + /*Audio Manager Attributes Info*/ + proto_tree_add_item(msg_tree,hf_audio_hf_support,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + while(msg_len>0){ + proto_tree_add_item(msg_tree,hf_rx_vocoder_type,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x08: + /*Audio Manager Options Report*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_opt_rpt_max,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_opt_rpt_adj_vol,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_opt_rpt_auto_adj_vol,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_opt_rpt_hs_on_air,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_opt_rpt_hd_on_air,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_opt_rpt_noise_squelch,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x09: + /*Adjustable Rx Volume Report*/ + proto_tree_add_item(msg_tree,hf_basic_bit_field,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_apb_rpt,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_up,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_floor,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_ceiling,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0a: + /*Adjustable Rx Volume Information*/ + proto_tree_add_item(msg_tree,hf_audio_current_adj_vol_id,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_apb_rpt,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_up,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_floor,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_ceiling,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_current_rx_level,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_current_rx_range,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0b: + /*APB's Default Rx Volume Value*/ + proto_tree_add_item(msg_tree,hf_audio_current_adj_vol_id,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_apb_rpt,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_up,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_floor,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_rx_vol_vol_ceiling,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_current_rx_level,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_current_rx_range,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0c: + /*Alerting Tone Select*/ + proto_tree_add_item(msg_tree,hf_audio_cadence_select,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_warbler_select,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x0e: + /*RTCP Statistics Report UGLY*/ + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + break; + case 0x0f: + /*Open Audio Stream Report*/ + proto_tree_add_item(msg_tree,hf_audio_open_stream_rpt,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x10: + /*RTCP Bucket SDES Information Report*/ + proto_tree_add_item(msg_tree,hf_audio_sdes_rpt_source_desc,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_sdes_rpt_buk_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_generic_string,tvb,offset,msg_len,ENC_ASCII|ENC_NA); + offset+=msg_len; + break; + case 0x11: + /*Port Mapping Discovery*/ + proto_tree_add_item(msg_tree,hf_audio_phone_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_phone_ip,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + break; + case 0x12: + /*Resolve Port Mapping*/ + proto_tree_add_item(msg_tree,hf_audio_nat_listen_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_nat_ip,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + proto_tree_add_item(msg_tree,hf_audio_nat_add_len,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_phone_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_phone_ip,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + proto_tree_add_item(msg_tree,hf_audio_phone_add_len,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + break; + case 0x13: + /*Audio Stream Status Report*/ + stream_dir=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_audio_stream_direction_code,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_mgr_stream_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + stream_state=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_audio_stream_state,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if((AUDIO_STREAM_STATE&stream_state)!=AUDIO_STREAM_STATE) + break; + if((AUDIO_STREAM_DIRECTION_RX&stream_dir)==AUDIO_STREAM_DIRECTION_RX) + proto_tree_add_item(msg_tree,hf_rx_vocoder_type,tvb,offset,1,ENC_BIG_ENDIAN); + else if((AUDIO_STREAM_DIRECTION_TX&stream_dir)==AUDIO_STREAM_DIRECTION_TX) + proto_tree_add_item(msg_tree,hf_tx_vocoder_type,tvb,offset,1,ENC_BIG_ENDIAN); + else + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,1,ENC_NA); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_frames_per_packet,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_tos,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_precedence,tvb,offset,1,ENC_BIG_ENDIAN); + proto_tree_add_item(msg_tree,hf_audio_frf_11,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_rtcp_bucket_id,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_lcl_rtp_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_lcl_rtcp_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_far_rtp_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_far_rtcp_port,tvb,offset,2,ENC_BIG_ENDIAN); + offset+=2;msg_len-=2; + proto_tree_add_item(msg_tree,hf_audio_far_ip_add,tvb,offset,4,ENC_BIG_ENDIAN); + offset+=4;msg_len-=4; + proto_tree_add_item(msg_tree,hf_audio_transducer_list_length,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + while(msg_len>0){ + proto_tree_add_item(msg_tree,hf_audio_transducer_pair,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + } + break; + case 0x14: + /*Query APB Response*/ + proto_tree_add_item(msg_tree,hf_audio_apb_number,tvb,offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + while(msg_len>0){ + apb_op_code=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_audio_apb_op_code,tvb, + offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + if(apb_op_code>0x39){ + /*should have a len + data*/ + apb_data_len=tvb_get_guint8(tvb,offset); + proto_tree_add_item(msg_tree,hf_audio_apb_param_len,tvb, + offset,1,ENC_BIG_ENDIAN); + offset+=1;msg_len-=1; + proto_tree_add_item(msg_tree,hf_audio_apb_data,tvb, + offset,apb_data_len,ENC_NA); + offset+=apb_data_len;msg_len-=apb_data_len; + } + } + break; + case 0xff: + /*Reserved*/ + break; + default: + proto_tree_add_item(msg_tree,hf_generic_data,tvb,offset,msg_len,ENC_NA); + offset+=msg_len; + } + + if(msg_len){ + /* TODO: add Expert info to indicate there is unknown data ! + For the moment, this code only remove Clang Warnings about not used msg_len... */ + } + + return offset; +} + +void +proto_register_unistim(void){ + + static hf_register_info hf[] = { + { &hf_unistim_seq_nu, + { "RUDP Seq Num","unistim.num",FT_UINT32, + BASE_HEX|BASE_RANGE_STRING, RVALS(sequence_numbers), 0x0, NULL, HFILL} + }, + { &hf_unistim_cmd_add, + { "UNISTIM CMD Address","unistim.add",FT_UINT8, + BASE_HEX,VALS(command_address),0x0,NULL,HFILL} + }, + { &hf_uftp_command, + { "UFTP CMD","unistim.uftp.cmd",FT_UINT8, + BASE_HEX,VALS(uftp_commands),0x0,NULL,HFILL} + }, + { &hf_uftp_datablock_size, + { "UFTP Datablock Size","unistim.uftp.blocksize",FT_UINT32, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_uftp_datablock_limit, + { "UFTP Datablock Limit","unistim.uftp.limit",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_uftp_filename, + { "UFTP Filename","unistim.uftp.filename",FT_STRINGZ, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_uftp_datablock, + { "UFTP Data Block","unistim.uftp.datablock",FT_BYTES, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_unistim_packet_type, + { "RUDP Pkt type","unistim.type",FT_UINT8, + BASE_DEC, VALS(packet_names),0x0,NULL,HFILL} + }, + { &hf_unistim_payload, + { "UNISTIM Payload","unistim.pay",FT_UINT8, + BASE_HEX, VALS(payload_names),0x0,NULL,HFILL} + }, + { &hf_unistim_len , + { "UNISTIM CMD Length","unistim.len",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_basic_bit_field, + {"FLAGS","unistim.bit.fields",FT_BOOLEAN, + 8,NULL,0xff,NULL,HFILL} + }, + { &hf_basic_switch_cmd , + {"Basic Cmd (switch)","unistim.basic.switch",FT_UINT8, + BASE_HEX,VALS(basic_switch_msgs),0x0,NULL,HFILL} + }, + { &hf_basic_phone_cmd , + {"Basic Cmd (phone)","unistim.basic.phone",FT_UINT8, + BASE_HEX,VALS(basic_phone_msgs),0x0,NULL,HFILL} + }, + { &hf_broadcast_switch_cmd , + {"Broadcast Cmd (switch)","unistim.broadcast.switch",FT_UINT8, + BASE_HEX,VALS(broadcast_switch_msgs),0x0,NULL,HFILL} + }, +#if 0 + { &hf_broadcast_phone_cmd , + {"Broadcast Cmd (phone)","unistim.broadcast.phone",FT_UINT8, + BASE_HEX,VALS(broadcast_phone_msgs),0x0,NULL,HFILL} + }, +#endif + { &hf_audio_switch_cmd , + {"Audio Cmd (switch)","unistim.audio.switch",FT_UINT8, + BASE_HEX,VALS(audio_switch_msgs),0x0,NULL,HFILL} + }, + { &hf_audio_phone_cmd , + {"Audio Cmd (phone)","unistim.audio.phone",FT_UINT8, + BASE_HEX,VALS(audio_phone_msgs),0x0,NULL,HFILL} + }, + { &hf_display_switch_cmd , + {"Display Cmd (switch)","unistim.display.switch",FT_UINT8, + BASE_HEX,VALS(display_switch_msgs),0x0,NULL,HFILL} + }, + { &hf_display_phone_cmd , + {"Display Cmd (phone)","unistim.display.phone",FT_UINT8, + BASE_HEX,VALS(display_phone_msgs),0x0,NULL,HFILL} + }, + { &hf_key_switch_cmd , + {"Key Cmd (switch)","unistim.key.switch",FT_UINT8, + BASE_HEX,VALS(key_switch_msgs),0x0,NULL,HFILL} + }, + { &hf_key_phone_cmd , + {"Key Cmd (phone)","unistim.key.phone",FT_UINT8, + BASE_HEX,VALS(key_phone_msgs),0x0,NULL,HFILL} + }, + { &hf_network_switch_cmd , + {"Network Cmd (switch)","unistim.network.switch",FT_UINT8, + BASE_HEX,VALS(network_switch_msgs),0x0,NULL,HFILL} + }, + { &hf_network_phone_cmd , + {"Network Cmd (phone)","unistim.network.phone",FT_UINT8, + BASE_HEX,VALS(network_phone_msgs),0x0,NULL,HFILL} + }, + { &hf_terminal_id, + {"Terminal ID","unistim.terminal.id",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_broadcast_year, + {"Year","unistim.broadcast.year",FT_UINT8, + BASE_DEC,NULL,0x7f,NULL,HFILL} + }, + { &hf_broadcast_month, + {"Month","unistim.broadcast.month",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_broadcast_day, + {"Day","unistim.broadcast.day",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_broadcast_hour, + {"Hour","unistim.broadcast.hour",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_broadcast_minute, + {"Minute","unistim.broadcast.minute",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_broadcast_second, + {"Second","unistim.broadcast.second",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_net_diag_flag, + {"Query Network Manager Diagnostic","unistim.query.diagnostic", + FT_BOOLEAN,8, NULL, + QUERY_NETWORK_MANAGER_DIAGNOSTIC, NULL,HFILL} + }, + { &hf_net_managers_flag, + {"Query Network Manager Managers","unistim.query.managers", + FT_BOOLEAN,8, NULL, + QUERY_NETWORK_MANAGER_MANAGERS, NULL,HFILL} + }, + { &hf_net_attributes_flag, + {"Query Network Manager Attributes","unistim.query.attributes", + FT_BOOLEAN, 8,NULL, + QUERY_NETWORK_MANAGER_ATTRIBUTES,NULL,HFILL} + }, + { &hf_net_serv_info_flag, + {"Query Network Manager Server Info","unistim.query.serverInfo", + FT_BOOLEAN, 8,NULL, + QUERY_NETWORK_MANAGER_SERVER_INFO,NULL,HFILL} + }, + { &hf_net_options_flag, + {"Query Network Manager Options","unistim.query.options", + FT_BOOLEAN, 8,NULL, + QUERY_NETWORK_MANAGER_OPTIONS,NULL,HFILL} + }, + { &hf_net_sanity_flag, + {"Query Network Manager Sanity","unistim.query.sanity", + FT_BOOLEAN, 8,NULL, + QUERY_NETWORK_MANAGER_SANITY,NULL,HFILL} + }, + { &hf_net_enable_diag, + {"Network Manager Enable DIAG","unistim.enable.diag", + FT_BOOLEAN, 8,NULL, + NETWORK_MANAGER_ENABLE_DIAG,NULL,HFILL} + }, + { &hf_net_enable_rudp, + {"Network Manager Enable RUDP","unistim.enable.network.rel.udp", + FT_BOOLEAN, 8,NULL, + NETWORK_MANAGER_ENABLE_RUDP,NULL,HFILL} + }, + { &hf_net_server_id, + {"Download Server ID","unistim.download.id",FT_UINT8, + BASE_HEX, VALS(network_server_id),0x0,NULL,HFILL} + }, + { &hf_net_server_port, + {"Download Server Port","unistim.download.port",FT_UINT16, + BASE_DEC, NULL,0x0,NULL,HFILL} + }, + { &hf_net_server_action, + {"Download Server Action","unistim.download.action",FT_UINT8, + BASE_HEX, VALS(server_action),0x0,NULL,HFILL} + }, + { &hf_net_server_retry_count, + {"Download Retry Count","unistim.download.retry",FT_UINT8, + BASE_DEC, NULL,0x0,NULL,HFILL} + }, + { &hf_net_server_failover_id, + {"Download Failover Server ID","unistim.download.failover",FT_UINT8, + BASE_HEX, VALS(network_server_id),0x0,NULL,HFILL} + }, + { &hf_net_server_ip_address, + {"Download Server Address","unistim.download.address",FT_IPv4, + BASE_NONE, NULL,0x0,NULL,HFILL} + }, + { &hf_net_server_time_out, + {"Watchdog Timeout","unistim.watchdog.timeout",FT_UINT16, + BASE_DEC, NULL,0x0,NULL,HFILL} + }, + { &hf_net_server_config_element, + {"Configure Network Element","unistim.config.element",FT_UINT8, + BASE_HEX, VALS(network_elements),0x0,NULL,HFILL} + }, + { &hf_net_server_recovery_time_low, + {"Recovery Procedure Idle Low Boundary","unistim.recovery.low",FT_UINT16, + BASE_DEC, NULL,0x0,NULL,HFILL} + }, + { &hf_net_server_recovery_time_high, + {"Recovery Procedure Idle High Boundary","unistim.recovery.high",FT_UINT16, + BASE_DEC, NULL,0x0,NULL,HFILL} + }, + { &hf_net_phone_rx_ovr_flag, + {"Receive Buffer Overflow","unistim.receive.overflow", + FT_BOOLEAN, 8,NULL, + RX_BUFFER_OVERFLOW,NULL,HFILL} + }, + { &hf_net_phone_tx_ovr_flag, + {"Transmit Buffer Overflow","unistim.trans.overflow", + FT_BOOLEAN, 8,NULL, + TX_BUFFER_OVERFLOW,NULL,HFILL} + }, + { &hf_net_phone_rx_empty_flag, + {"Receive Buffer Unexpectedly Empty","unistim.receive.empty", + FT_BOOLEAN, 8,NULL, + RX_UNEXPECT_EMPTY,NULL,HFILL} + }, + { &hf_net_phone_invalid_msg_flag, + {"Received Invalid MSG","unistim.invalid.msg", + FT_BOOLEAN, 8,NULL, + INVALID_MSG,NULL,HFILL} + }, + { &hf_net_phone_eeprom_insane_flag, + {"EEProm Insane","unistim.eeprom.insane", + FT_BOOLEAN, 8,NULL, + EEPROM_INSANE,NULL,HFILL} + }, + { &hf_net_phone_eeprom_unsafe_flag, + {"EEProm Unsafe","unistim.eeprom.unsafe", + FT_BOOLEAN, 8,NULL, + EEPROM_UNSAFE,NULL,HFILL} + }, + { &hf_net_phone_diag, + {"Diagnostic Command Enabled","unistim.diag.enabled",FT_BOOLEAN, + 8,NULL,NETWORK_MGR_REPORT_DIAG,NULL,HFILL} + }, + { &hf_net_phone_rudp, + {"Reliable UDP Active","unistim.rudp.active",FT_BOOLEAN, + 8,NULL,NETWORK_MGR_REPORT_RUDP,NULL,HFILL} + }, + { &hf_basic_switch_query_flags, + {"Query Basic Manager","unistim.basic.query",FT_UINT8, + BASE_HEX, NULL,0x00,"INITIAL PHONE QUERY",HFILL} + }, + { &hf_basic_switch_query_attr, + {"Query Basic Manager Attributes","unistim.basic.attrs",FT_BOOLEAN, + 8,NULL,BASIC_QUERY_ATTRIBUTES,"Basic Query Attributes",HFILL} + }, + { &hf_basic_switch_query_opts, + {"Query Basic Manager Options","unistim.basic.opts",FT_BOOLEAN, + 8,NULL,BASIC_QUERY_OPTIONS,"Basic Query Options",HFILL} + }, + { &hf_basic_switch_query_fw, + {"Query Basic Switch Firmware","unistim.basic.fw",FT_BOOLEAN, + 8,NULL,BASIC_QUERY_FW,"Basic Query Firmware",HFILL} + }, + { &hf_basic_switch_query_hw_id, + {"Query Basic Manager Hardware ID","unistim.basic.hwid",FT_BOOLEAN, + 8,NULL,BASIC_QUERY_HW_ID,"Basic Query Hardware ID",HFILL} + }, + { &hf_basic_switch_query_it_type, + {"Query Basic Manager Phone Type","unistim.basic.type",FT_BOOLEAN, + 8,NULL,BASIC_QUERY_IT_TYPE,"Basic Query Phone Type",HFILL} + }, + { &hf_basic_switch_query_prod_eng_code, + {"Query Basic Manager Prod Eng Code","unistim.basic.code",FT_BOOLEAN, + 8,NULL,BASIC_QUERY_PROD_ENG_CODE,"Basic Query Production Engineering Code",HFILL} + }, + { &hf_basic_switch_query_gray_mkt_info, + {"Query Basic Manager Gray Mkt Info","unistim.basic.gray",FT_BOOLEAN, + 8,NULL,BASIC_QUERY_GRAY_MKT_INFO,"Basic Query Gray Market Info",HFILL} + }, + { &hf_basic_switch_options_secure, + {"Basic Switch Options Secure Code","unistim.basic.secure",FT_BOOLEAN, + 8,NULL,BASIC_OPTION_SECURE,NULL,HFILL} + }, + { &hf_basic_switch_element_id, + {"Basic Element ID","unistim.basic.element.id",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_basic_switch_eeprom_data, + {"EEProm Data","unistim.basic.eeprom.data",FT_BYTES, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_basic_phone_eeprom_stat_cksum, + {"Basic Phone EEProm Static Checksum","unistim.static.cksum",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_basic_phone_eeprom_dynam, + {"Basic Phone EEProm Dynamic Checksum","unistim.dynam.cksum",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_basic_phone_eeprom_net_config_cksum, + {"Basic Phone EEProm Net Config Checksum","unistim.netconfig.cksum",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_basic_phone_hw_id, + {"Basic Phone Hardware ID","unistim.basic.hw.id",FT_BYTES, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_basic_phone_fw_ver, + {"Basic Phone Firmware Version","unistim.basic.fw.ver",FT_STRING, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_key_code, + {"Key Name","unistim.key.name",FT_UINT8, + BASE_HEX,VALS(key_names),0x3f,NULL,HFILL} + }, + { &hf_key_command, + {"Key Action","unistim.key.action",FT_UINT8, + BASE_HEX,VALS(key_cmds),0xc0,NULL,HFILL} + }, + { &hf_icon_id, + {"Icon ID","unistim.icon.id",FT_UINT8, + BASE_HEX,NULL, DISPLAY_ICON_ID,NULL,HFILL} + }, + { &hf_broadcast_icon_state, + {"Icon State","unistim.icon.state",FT_UINT8, + BASE_HEX,VALS(bcast_icon_states),0x1f,NULL,HFILL} + }, + { &hf_broadcast_icon_cadence, + {"Icon Cadence","unistim.icon.cadence",FT_UINT8, + BASE_HEX,VALS(bcast_icon_cadence),0xe0,NULL,HFILL} + }, + { &hf_audio_mgr_attr, + {"Query Audio Manager Attributes","unistim.audio.attr",FT_BOOLEAN, + 8,NULL,QUERY_AUDIO_MGR_ATTRIBUTES,NULL,HFILL} + }, + { &hf_audio_mgr_opts, + {"Query Audio Manager Options","unistim.audio.options",FT_BOOLEAN, + 8,NULL,QUERY_AUDIO_MGR_OPTIONS,NULL,HFILL} + }, + { &hf_audio_mgr_alert, + {"Query Audio Manager Alerting","unistim.audio.alerting",FT_BOOLEAN, + 8,NULL,QUERY_AUDIO_MGR_ALERTING ,NULL,HFILL} + }, + { &hf_audio_mgr_adj_rx_vol, + {"Query Audio Manager Adjustable Receive Volume","unistim.audio.adj.volume",FT_BOOLEAN, + 8,NULL,QUERY_AUDIO_MGR_ADJ_RX_VOL,NULL,HFILL} + }, + { &hf_audio_mgr_def_rx_vol, + {"Query Audio Manager Default Receive Volume","unistim.audio.def.volume",FT_BOOLEAN, + 8,NULL,QUERY_AUDIO_MGR_DEF_RX_VOL,NULL,HFILL} + }, + { &hf_audio_mgr_handset, + {"Query Audio Manager Handset","unistim.audio.handset",FT_BOOLEAN, + 8,NULL,QUERY_AUDIO_MGR_HANDSET,NULL,HFILL} + }, + { &hf_audio_mgr_headset, + {"Query Audio Manager Headset","unistim.audio.headset",FT_BOOLEAN, + 8,NULL,QUERY_AUDIO_MGR_HEADSET,NULL,HFILL} + }, + { &hf_audio_default_rx_vol_id, + {"Audio Manager Default Receive Volume ID","unistim.audio.volume.id",FT_UINT8, + BASE_HEX,VALS(default_rx_vol_id),0x0,NULL,HFILL} + }, + { &hf_audio_mgr_opt_max_vol, + {"Audio Manager Enable Max Tone Volume","unistim.audio.max.tone",FT_BOOLEAN, + 8,TFS(&audio_opts_enable_max_tone_vol),AUDIO_MGR_OPTS_MAX_VOL,NULL,HFILL} + }, + { &hf_audio_mgr_opt_adj_vol, + {"Audio Manager Adjust Volume","unistim.audio.opts.adj.vol",FT_BOOLEAN, + 8,TFS(&audio_opts_adjust_volume),AUDIO_MGR_ADJ_VOL,NULL,HFILL} + }, + { &hf_audio_mgr_opt_aa_rx_vol_rpt, + {"Audio Manager Auto Adjust Volume RPT","unistim.audio.aa.vol.rpt",FT_BOOLEAN, + 8,TFS(&audio_opts_automatic_adjustable),AUDIO_MGR_AUTO_RX_VOL_RPT,NULL,HFILL} + }, + { &hf_audio_mgr_opt_hs_on_air, + {"Audio Manager Handset","unistim.audio.handset",FT_BOOLEAN, + 8,TFS(&audio_opts_hs_on_air_feature),AUDIO_MGR_HS_ON_AIR,NULL,HFILL} + }, + { &hf_audio_mgr_opt_hd_on_air, + {"Audio Manager Headset","unistim.audio.headset",FT_BOOLEAN, + 8,TFS(&audio_opts_hd_on_air_feature),AUDIO_MGR_HD_ON_AIR,NULL,HFILL} + }, + { &hf_audio_mgr_opt_noise_squelch, + {"Audio Manager Noise Squelch","unistim.audio.squelch",FT_BOOLEAN, + 8,TFS(&noise_sqlch_disable), AUDIO_MGR_NOISE_SQUELCH,NULL,HFILL} + }, + { &hf_audio_mgr_mute, + {"Audio Manager Mute","unistim.audio.mute",FT_BOOLEAN, + 8,TFS(&audio_mgr_mute_val),AUDIO_MGR_MUTE,NULL,HFILL} + }, + { &hf_audio_mgr_tx_rx, + {"Audio Manager RX or TX","unistim.audio.rx.tx",FT_BOOLEAN, + 8,TFS(&audio_mgr_tx_rx_val),AUDIO_MGR_TX_RX,NULL,HFILL} + }, + { &hf_audio_mgr_stream_id, + {"Audio Manager Stream ID","unistim.audio.stream.id",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_mgr_transducer_based_tone_id, + {"Audio Manager Transducer Based Tone On","unistim.audio.transducer.on",FT_UINT8, + BASE_HEX,VALS(trans_base_tone_ids),0x07,NULL,HFILL} + }, + { &hf_audio_mgr_attenuated, + {"Audio Manager Transducer Tone Attenuated","unistim.audio.attenuated.on",FT_BOOLEAN, + 8,NULL,AUDIO_MGR_ATTENUATED,NULL,HFILL} + }, + { &hf_audio_mgr_warbler_select, + {"Warbler Select","unistim.warbler.select",FT_UINT8, + BASE_HEX,NULL,0x07,NULL,HFILL} + }, + { &hf_audio_mgr_transducer_routing, + {"Transducer Routing","unistim.transducer.routing",FT_UINT8, + BASE_HEX,VALS(transducer_routing_vals),0xf8,NULL,HFILL} + }, + { &hf_audio_mgr_tone_vol_range, + {"Tone Volume Range in Steps","unistim.tone.volume.range",FT_UINT8, + BASE_HEX,NULL,0x0f,NULL,HFILL} + }, + { &hf_audio_mgr_cadence_select, + {"Cadence Select","unistim.cadence.select",FT_UINT8, + BASE_HEX,VALS(cadence_select_vals),0xf0,NULL,HFILL} + }, + { &hf_audio_special_tone, + {"Special Tone Select","unistim.special.tone.select",FT_UINT8, + BASE_HEX,VALS(special_tones_vals),0x0,NULL,HFILL} + }, + { &hf_audio_tone_level, + {"Tone Level","unistim.audio.tone.level",FT_UINT8, + BASE_DEC,NULL,0xf0,NULL,HFILL} + }, + { &hf_audio_visual_tones, + {"Enable Visual Tones","unistim.visual.tones",FT_BOOLEAN, + 8,NULL,AUDIO_MGR_VISUAL_TONE,NULL,HFILL} + }, + { &hf_audio_stream_based_tone_id, + {"Stream Based Tone ID","unistim.stream.tone.id",FT_UINT8, + BASE_HEX,VALS(stream_based_tone_vals),0x1f,NULL,HFILL} + }, + { &hf_audio_stream_based_tone_rx_tx, + {"Stream Based Tone RX or TX","unistim.stream.based.tone.rx.tx",FT_BOOLEAN, + 8,TFS(&stream_based_tone_rx_tx_yn),AUDIO_STREAM_BASED_TONE_RX_TX,NULL,HFILL} + }, + { &hf_audio_stream_based_tone_mute, + {"Stream Based Tone Mute","unistim.stream.tone.mute",FT_BOOLEAN, + 8,TFS(&stream_based_tone_mute_yn),AUDIO_STREAM_BASED_TONE_MUTE,NULL,HFILL} + }, + { &hf_audio_stream_id, + {"Stream ID","unistim.audio.stream.id",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_stream_based_volume, + {"Stream Based Volume ID","unistim.stream.volume.id",FT_UINT8, + BASE_HEX,VALS(stream_base_vol_level),0x0,NULL,HFILL} + }, + { &hf_basic_switch_terminal_id, + {"Terminal ID assigned by Switch","unistim.switch.terminal.id",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_basic_it_type, + {"IT (Phone) Type","unistim.it.type",FT_UINT8, + BASE_HEX,VALS(it_types),0x0,NULL,HFILL} + }, + { &hf_basic_prod_eng_code, + {"Product Engineering Code for phone","unistim.basic.eng.code",FT_STRING, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_net_phone_primary_server_id, + {"Phone Primary Server ID","unistim.net.phone.primary.id",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_net_phone_server_port, + {"Port Number","unistim.server.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_net_phone_server_action, + {"Action","unistim.server.action.byte",FT_UINT8, + BASE_HEX,VALS(action_bytes),0x0,NULL,HFILL} + }, + { &hf_net_phone_server_retry_count, + {"Number of times to Retry","unistim.server.retry.count",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_net_phone_server_failover_id, + {"Failover Server ID","unistim.server.failover.id",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_net_phone_server_ip, + {"IP address","unistim.server.ip.address",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_apb_number, + {"APB Number","unistim.audio.apb.number",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { & hf_audio_apb_op_code, + {"APB Operation Code","unistim.audio.apb.op.code",FT_UINT8, + BASE_HEX,VALS(apb_op_codes),0x0,NULL,HFILL} + }, + { &hf_audio_apb_param_len, + {"APB Operation Parameter Length","unistim.apb.param.len",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_apb_data, + {"APB Operation Data","unistim.apb.operation.data",FT_BYTES, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_display_write_address_numeric, + {"Is Address Numeric","unistim.write.address.numeric",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_ADDRESS_NUMERIC_FLAG,NULL,HFILL} + }, + { &hf_display_write_address_context, + {"Context Field in the Info Bar","unistim.write.address.context",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_ADDRESS_CONTEXT_FLAG,NULL,HFILL} + }, + { &hf_display_write_address_line, + {"Write A Line","unistim.write.address.line",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_ADDRESS_LINE_FLAG ,NULL,HFILL} + }, + { &hf_display_write_address_soft_key, + {"Write a SoftKey","unistim.write.address.softkey",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_ADDRESS_SOFT_KEY_FLAG,NULL,HFILL} + }, + { &hf_display_write_address_soft_label, + {"Write A Softkey Label","unistim.write.address.softkey.label",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_ADDRESS_SOFT_LABEL_FLAG,NULL,HFILL} + }, + { &hf_display_write_address_softkey_id, + {"Soft Key ID","unistim.write.address.softkey.id",FT_UINT8, + BASE_HEX,NULL,DISPLAY_WRITE_ADDRESS_SOFT_KEY_ID,NULL,HFILL} + }, + { &hf_display_write_address_char_pos, + {"Character Position or Soft-Label Key ID","unistim.display.write.address.char.pos",FT_UINT8, + BASE_HEX,NULL,DISPLAY_WRITE_ADDRESS_CHAR_POS,NULL,HFILL} + }, + { &hf_display_write_address_line_number, + {"Line Number","unistim.write.address.line.number",FT_UINT8, + BASE_DEC,NULL,DISPLAY_WRITE_ADDRESS_LINE_NUM,NULL,HFILL} + }, + { &hf_display_write_cursor_move, + {"Cursor Move","unistim.display.cursor.move",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_CURSOR_MOVE,NULL,HFILL} + }, + { &hf_display_write_clear_left, + {"Clear Left","unistim.display.clear.left",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_CLEAR_LEFT,NULL,HFILL} + }, + { &hf_display_write_clear_right, + {"Clear Right","unistim.display.clear.right",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_CLEAR_RIGHT,NULL,HFILL} + }, + { &hf_display_write_shift_left, + {"Shift Left","unistim.display.shift.left",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_SHIFT_LEFT,NULL,HFILL} + }, + { &hf_display_write_shift_right, + {"Shift Right","unistim.display.shift.right",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_SHIFT_RIGHT,NULL,HFILL} + }, + { &hf_display_write_highlight, + {"Highlight","unistim.display.highlight",FT_BOOLEAN, + 8,NULL,DISPLAY_WRITE_HIGHLIGHT,NULL,HFILL} + }, + { &hf_display_write_tag, + {"Tag for text","unistim.display.text.tag",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_display_cursor_move_cmd, + {"Cursor Movement Command","unistim.cursor.move.cmd",FT_UINT8, + BASE_HEX,VALS(cursor_move_cmds),DISPLAY_CURSOR_MOVE_CMD,NULL,HFILL} + }, + { &hf_display_cursor_blink, + {"Should Cursor Blink","unistim.cursor.blink",FT_BOOLEAN, + 8,NULL,DISPLAY_CURSOR_BLINK,NULL,HFILL} + }, + { &hf_audio_vocoder_id, + {"Vocoder Protocol","unistim.vocoder.id",FT_UINT8, + BASE_HEX,VALS(vocoder_ids),0x0,NULL,HFILL} + }, + { &hf_audio_vocoder_param, + {"Vocoder Config Param","unistim.vocoder.config.param",FT_UINT8, + BASE_HEX,VALS(vocoder_config_params),AUDIO_VOCODER_CONFIG_PARAM,NULL,HFILL} + }, + { &hf_audio_vocoder_entity, + {"Vocoder Entity","unistim.vocoder.entity",FT_UINT8, + BASE_HEX,VALS(config_param_entities),AUDIO_VOCODER_CONFIG_ENTITY,NULL,HFILL} + }, + { &hf_audio_vocoder_annexa, + {"Enable Annex A","unistim.enable.annexa",FT_BOOLEAN, + 8,NULL,AUDIO_VOCODER_ANNEXA,NULL,HFILL} + }, + { &hf_audio_vocoder_annexb, + {"Enable Annex B","unistim.enable.annexb",FT_BOOLEAN, + 8,NULL,AUDIO_VOCODER_ANNEXB,NULL,HFILL} + }, + { &hf_audio_sample_rate, + {"Sample Rate","unistim.audio.sample.rate",FT_UINT8, + BASE_HEX,VALS(sample_rates),0x0,NULL,HFILL} + }, + { &hf_audio_rtp_type, + {"RTP Type","unistim.audio.rtp.type",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_bytes_per_frame, + {"Bytes Per Frame","unistim.audio.bytes.per.frame",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_rx_stream_id, + {"Receive Stream Id","unistim.rx.stream.id",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_tx_stream_id, + {"Transmit Stream Id","unistim.tx.stream.id",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_rx_vocoder_type, + {"Receive Vocoder Protocol","unistim.vocoder.id",FT_UINT8, + BASE_HEX,VALS(vocoder_ids),0x0,NULL,HFILL} + }, + { &hf_tx_vocoder_type, + {"Transmit Vocoder Protocol","unistim.vocoder.id",FT_UINT8, + BASE_HEX,VALS(vocoder_ids),0x0,NULL,HFILL} + }, + { &hf_frames_per_packet, + {"Frames Per Packet","unistim.vocoder.frames.per.packet",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_tos, + {"Type of Service","unistim.audio.type.service",FT_UINT8, + BASE_HEX,VALS(types_of_service),AUDIO_TYPE_OF_SERVICE,NULL,HFILL} + }, + { &hf_audio_precedence, + {"Precedence","unistim.audio.precedence",FT_UINT8, + BASE_HEX,VALS(precedences),AUDIO_PRECENDENCE,NULL,HFILL} + }, + { &hf_audio_frf_11, + {"FRF.11 Enable","unistim.audio.frf.11",FT_BOOLEAN, + 8,NULL,AUDIO_FRF_11,NULL,HFILL} + }, + { &hf_audio_lcl_rtp_port, + {"Phone RTP Port","unistim.local.rtp.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_lcl_rtcp_port, + {"Phone RTCP Port","unistim.local.rtcp.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_far_rtp_port, + {"Distant RTP Port","unistim.far.rtp.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_far_rtcp_port, + {"Distant RTCP Port","unistim.far.rtcp.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_far_ip_add, + {"Distant IP Address for RT[C]P","unistim.far.ip.address",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_rtcp_bucket_id, + {"RTCP Bucket ID","unistim.rtcp.bucket.id",FT_UINT16, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_key_icon_id, + {"Icon ID","unistim.key.icon.id",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_display_clear_numeric, + {"Numeric Index Field in InfoBar","unistim.display.clear.numeric",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_NUMERIC,NULL,HFILL} + }, + { &hf_display_clear_context , + {"Context Field in InfoBar","unistim.display.clear.context",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_CONTEXT,NULL,HFILL} + }, + { &hf_display_clear_date , + {"Date Field","unistim.display.clear.date",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_DATE,NULL,HFILL} + }, + { &hf_display_clear_time, + {"Time Field","unistim.display.clear.time",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_TIME,NULL,HFILL} + }, + { &hf_display_clear_line, + {"Line Data","unistim.display.clear.line",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon, + {"Status Bar Icon","unistim.display.statusbar.icon",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_STATUS_BAR_ICON,NULL,HFILL} + }, + { &hf_display_clear_softkey, + {"Soft Key","unistim.display.clear.softkey",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_SOFTKEY,NULL,HFILL} + }, + { &hf_display_clear_softkey_label , + {"Soft Key Label","unistim.display.clear.softkey.label",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_SOFTKEY_LABEL,NULL,HFILL} + }, + { &hf_display_clear_line_1 , + {"Line 1","unistim.display.clear.line1",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE_1,NULL,HFILL} + }, + { &hf_display_clear_line_2 , + {"Line 2","unistim.display.clear.line2",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE_2,NULL,HFILL} + }, + { &hf_display_clear_line_3 , + {"Line 3","unistim.display.clear.line3",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE_3,NULL,HFILL} + }, + { &hf_display_clear_line_4 , + {"Line 4","unistim.display.clear.line4",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE_4,NULL,HFILL} + }, + { &hf_display_clear_line_5 , + {"Line 5","unistim.display.clear.line5",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE_5,NULL,HFILL} + }, + { &hf_display_clear_line_6 , + {"Line 6","unistim.display.clear.line6",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE_6,NULL,HFILL} + }, + { &hf_display_clear_line_7 , + {"Line 7","unistim.display.clear.line7",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE_7,NULL,HFILL} + }, + { &hf_display_clear_line_8 , + {"Line 8","unistim.display.clear.line8",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_LINE_8,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon_1 , + {"Status Bar Icon 1","unistim.display.clear.sbar.icon1",FT_BOOLEAN, + 8,NULL,DISPLAY_STATUS_BAR_ICON_1,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon_2 , + {"Status Bar Icon 2","unistim.display.clear.sbar.icon2",FT_BOOLEAN, + 8,NULL,DISPLAY_STATUS_BAR_ICON_2,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon_3 , + {"Status Bar Icon 3","unistim.display.clear.sbar.icon3",FT_BOOLEAN, + 8,NULL,DISPLAY_STATUS_BAR_ICON_3,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon_4 , + {"Status Bar Icon 4","unistim.display.clear.sbar.icon4",FT_BOOLEAN, + 8,NULL,DISPLAY_STATUS_BAR_ICON_4,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon_5 , + {"Status Bar Icon 5","unistim.display.clear.sbar.icon5",FT_BOOLEAN, + 8,NULL,DISPLAY_STATUS_BAR_ICON_5,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon_6 , + {"Status Bar Icon 6","unistim.display.clear.sbar.icon6",FT_BOOLEAN, + 8,NULL,DISPLAY_STATUS_BAR_ICON_6,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon_7 , + {"Status Bar Icon 7","unistim.display.clear.sbar.icon7",FT_BOOLEAN, + 8,NULL,DISPLAY_STATUS_BAR_ICON_7,NULL,HFILL} + }, + { &hf_display_clear_status_bar_icon_8 , + {"Status Bar Icon 8","unistim.display.clear.sbar.icon8",FT_BOOLEAN, + 8,NULL,DISPLAY_STATUS_BAR_ICON_8,NULL,HFILL} + }, + { &hf_display_clear_soft_key_1 , + {"Soft Key 1","unistim.display.clear.soft.key1",FT_BOOLEAN, + 8,NULL,DISPLAY_SOFT_KEY_1,NULL,HFILL} + }, + { &hf_display_clear_soft_key_2 , + {"Soft Key 2","unistim.display.clear.soft.key2",FT_BOOLEAN, + 8,NULL,DISPLAY_SOFT_KEY_2,NULL,HFILL} + }, + { &hf_display_clear_soft_key_3 , + {"Soft Key 3","unistim.display.clear.soft.key3",FT_BOOLEAN, + 8,NULL,DISPLAY_SOFT_KEY_3,NULL,HFILL} + }, + { &hf_display_clear_soft_key_4 , + {"Soft Key 4","unistim.display.clear.soft.key4",FT_BOOLEAN, + 8,NULL,DISPLAY_SOFT_KEY_4,NULL,HFILL} + }, + { &hf_display_clear_soft_key_5 , + {"Soft Key 5","unistim.display.clear.soft.key5",FT_BOOLEAN, + 8,NULL,DISPLAY_SOFT_KEY_5,NULL,HFILL} + }, + { &hf_display_clear_soft_key_6 , + {"Soft Key 6","unistim.display.clear.soft.key6",FT_BOOLEAN, + 8,NULL,DISPLAY_SOFT_KEY_6,NULL,HFILL} + }, + { &hf_display_clear_soft_key_7 , + {"Soft Key 7","unistim.display.clear.soft.key7",FT_BOOLEAN, + 8,NULL,DISPLAY_SOFT_KEY_7,NULL,HFILL} + }, + { &hf_display_clear_soft_key_8 , + {"Soft Key 8","unistim.display.clear.soft.key8",FT_BOOLEAN, + 8,NULL,DISPLAY_SOFT_KEY_8,NULL,HFILL} + }, + { &hf_display_clear_sk_label_key_id, + {"Soft Key Label ID","unistim.display.clear.sk.label.id",FT_UINT8, + BASE_HEX,NULL, DISPLAY_CLEAR_SK_LABEL_KEY_ID,NULL,HFILL} + }, + { &hf_display_clear_all_slks, + {"Clear All Soft Key Labels","unistim.display.clear.all.sks",FT_BOOLEAN, + 8,NULL,DISPLAY_CLEAR_ALL_SLKS,NULL,HFILL} + }, + { &hf_key_led_cadence, + {"LED Cadence","unistim.key.led.cadence",FT_UINT8, + BASE_HEX,VALS(led_cadences),KEY_LED_CADENCE,NULL,HFILL} + }, + { &hf_key_led_id, + {"LED ID","unistim.key.led.id",FT_UINT8, + BASE_HEX,VALS(led_ids),KEY_LED_ID,NULL,HFILL} + }, + { &hf_basic_ether_address, + {"Phone Ethernet Address","unistim.phone.ether",FT_ETHER, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_rtcp_bucket_id, + {"RTCP Bucket ID","unistim.audio.rtcp.bucket.id",FT_UINT8, + BASE_HEX,NULL,AUDIO_RTCP_BUCKET_ID,NULL,HFILL} + }, + { &hf_audio_clear_bucket, + {"Clear Bucket Counter","unistim.clear.bucket",FT_BOOLEAN, + 8,NULL,AUDIO_CLEAR_BUCKET,NULL,HFILL} + }, + { &hf_display_arrow, + {"Arrow Display Direction","unistim.arrow.direction",FT_UINT8, + BASE_HEX,VALS(arrow_dirs),0x0,NULL,HFILL} + }, + { &hf_audio_transducer_pair, + {"Audio Transducer Pair","unistim.transducer.pairs",FT_UINT8, + BASE_HEX,VALS(transducer_pairs),AUDIO_TRANSDUCER_PAIR_ID,NULL,HFILL} + }, + { &hf_audio_rx_enable, + {"RX Enable","unistim.receive.enable",FT_BOOLEAN, + 8,NULL,AUDIO_RX_ENABLE,NULL,HFILL} + }, + { &hf_audio_tx_enable, + {"TX Enable","unistim.transmit.enable",FT_BOOLEAN, + 8,NULL,AUDIO_TX_ENABLE,NULL,HFILL} + }, + { &hf_audio_sidetone_disable, + {"Disable Sidetone","unistim.audio.sidetone.disable",FT_BOOLEAN, + 8,NULL,AUDIO_SIDETONE_DISABLE,NULL,HFILL} + }, + { &hf_audio_destruct_additive, + {"Destructive/Additive","unistim.destructive.additive",FT_BOOLEAN, + 8,TFS(&destruct_additive),AUDIO_DESTRUCT_ADD,NULL,HFILL} + }, + { &hf_audio_dont_force_active, + {"Don't Force Active","unistim.dont.force.active",FT_BOOLEAN, + 8,TFS(&dont_force_active),AUDIO_DONT_FORCE_ACTIVE,NULL,HFILL} + }, + { &hf_display_line_width, + {"Phone Line Width","unistim.line.width",FT_UINT8, + BASE_DEC,NULL,DISPLAY_LINE_WIDTH,NULL,HFILL} + }, + { &hf_display_lines, + {"Number Of Lines","unistim.number.lines",FT_UINT8, + BASE_DEC,NULL,DISPLAY_LINES,NULL,HFILL} + }, + { &hf_display_softkey_width, + {"Phone Softkey Width","unistim.softkey.width",FT_UINT8, + BASE_DEC,NULL,DISPLAY_SKEY_WIDTH,NULL,HFILL} + }, + { &hf_display_softkeys, + {"Phone Softkeys","unistim.phone.softkeys",FT_UINT8, + BASE_DEC,NULL,DISPLAY_SKEYS,NULL,HFILL} + }, + { &hf_display_icon, + {"Phone Icon Type","unistim.phone.icon.type",FT_UINT8, + BASE_HEX,VALS(icon_types),DISPLAY_ICON,NULL,HFILL} + }, + { &hf_display_softlabel_key_width, + {"Soft-Label Key width","unistim.softlabel.key.width",FT_UINT8, + BASE_DEC,NULL,DISPLAY_SOFTLABEL_WIDTH,NULL,HFILL} + }, + { &hf_display_context_width, + {"Phone Context Width","unistim.context.width",FT_UINT8, + BASE_DEC,NULL,DISPLAY_CONTEXT_WIDTH,NULL,HFILL} + }, + { &hf_display_numeric_width, + {"Phone Numeric Width","unistim.numeric.width",FT_UINT8, + BASE_DEC,NULL,DISPLAY_NUMERIC_WIDTH,NULL,HFILL} + }, + { &hf_display_time_width, + {"Phone Time Width","unistim.time.width",FT_UINT8, + BASE_DEC,NULL,DISPLAY_TIME_WIDTH,NULL,HFILL} + }, + { &hf_display_date_width, + {"Phone Date Width","unistim.date.width",FT_UINT8, + BASE_DEC,NULL,DISPLAY_DATE_WIDTH,NULL,HFILL} + }, + { &hf_display_char_dload, + {"Number of Downloadable Chars","unistim.number.dload.chars",FT_UINT8, + BASE_DEC,NULL,DISPLAY_CHAR_DLOAD,NULL,HFILL} + }, + { &hf_display_freeform_icon_dload, + {"Number of Freeform Icon Downloads","unistim.number.dload.icons",FT_UINT8, + BASE_DEC,NULL,DISPLAY_FFORM_ICON_DLOAD,NULL,HFILL} + }, + { &hf_display_icon_type, + {"Icon Types","unistim.icon.types",FT_UINT8, + BASE_HEX,NULL,DISPLAY_ICON_TYPE,NULL,HFILL} + }, + { &hf_display_charsets, + {"Character Sets","unistim.phone.charsets",FT_UINT8, + BASE_HEX,NULL,DISPLAY_CHARSET,NULL,HFILL} + }, + { &hf_display_contrast, + {"Phone Contrast Level","unistim.phone.contrast.level",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_display_cursor_numeric, + {"Numeric Index Field","unistim.field.numeric",FT_BOOLEAN, + 8,NULL,DISPLAY_CURSOR_NUMERIC,NULL,HFILL} + }, + { &hf_display_cursor_context, + {"Context Field","unistim.field.context",FT_BOOLEAN, + 8,NULL,DISPLAY_CURSOR_CONTEXT,NULL,HFILL} + }, + { &hf_display_cursor_line, + {"Text Line","unistim.field.text.line",FT_BOOLEAN, + 8,NULL,DISPLAY_CURSOR_LINE,NULL,HFILL} + }, + { &hf_display_cursor_softkey, + {"Softkey Position","unistim.position.skey",FT_BOOLEAN, + 8,NULL,DISPLAY_CURSOR_SKEY,NULL,HFILL} + }, + { &hf_display_cursor_softkey_id, + {"Soft Key Id","unistim.cursor.skey.id",FT_UINT8, + BASE_DEC,NULL,DISPLAY_CURSOR_SKEY_ID,NULL,HFILL} + }, + { &hf_display_cursor_char_pos, + {"Character Position","unistim.phone.char.pos",FT_UINT8, + BASE_DEC,NULL,DISPLAY_CURSOR_CHAR_POS,NULL,HFILL} + }, + { &hf_display_cursor_line_number, + {"Display Line Number","unistim.display.line.number",FT_UINT8, + BASE_DEC,NULL,DISPLAY_CURSOR_LINE_NUM,NULL,HFILL} + }, + { &hf_display_hlight_start, + {"Display Highlight Start Position","unistim.hilite.start.pos",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_display_hlight_end, + {"Display Highlight End Position","unistim.hilite.end.pos",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_display_date_format, + {"Date Format","unistim.display.date.format",FT_UINT8, + BASE_HEX,VALS(date_formats),DISPLAY_DATE_FORMAT,NULL,HFILL} + }, + { &hf_display_time_format, + {"Time Format","unistim.display.time.format",FT_UINT8, + BASE_HEX,VALS(time_formats),DISPLAY_TIME_FORMAT,NULL,HFILL} + }, + { &hf_display_use_time_format, + {"Use Time Format","unistim.display.use.time.format",FT_BOOLEAN, + 8,NULL,DISPLAY_USE_TIME_FORMAT,NULL,HFILL} + }, + { &hf_display_use_date_format, + {"Use Date Format","unistim.display.use.date.format",FT_BOOLEAN, + 8,NULL,DISPLAY_USE_DATE_FORMAT,NULL,HFILL} + }, + { &hf_display_context_format, + {"Context Info Bar Format","unistim.display.context.format",FT_UINT8, + BASE_HEX,VALS(display_formats),DISPLAY_CTX_FORMAT,NULL,HFILL} + }, + { &hf_display_context_field, + {"Context Info Bar Field","unistim.display.context.field",FT_UINT8, + BASE_HEX,VALS(display_format_fields),DISPLAY_CTX_FIELD,NULL,HFILL} + }, + { &hf_display_char_address, + {"Display Character Address","unistim.display.char.address",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_display_layer_number, + {"Softkey Layer Number","unistim.softkey.layer.num",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_display_layer_skey_id, + {"Softkey ID","unistim.layer.softkey.id",FT_UINT8, + BASE_DEC,NULL,DISPLAY_LAYER_SKEY_ID,NULL,HFILL} + }, + { &hf_display_layer_all_skeys, + {"All Softkeys","unistim.layer.all.skeys",FT_BOOLEAN, + 8,NULL,DISPLAY_LAYER_ALL_SKEYS,NULL,HFILL} + }, + { &hf_display_once_or_cyclic, + {"Layer Softkey Once/Cyclic","unistim.layer.once.cyclic",FT_BOOLEAN, + 8,TFS(&once_or_cyclic),DISPLAY_ONE_OR_CYCLIC,NULL,HFILL} + }, + { &hf_display_layer_duration, + {"Display Duration (20ms steps)","unistim.layer.display.duration",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_key_programmable_keys, + {"Number of Programmable Keys","unistim.num.prog.keys",FT_UINT8, + BASE_DEC,NULL,KEY_NUM_PROG_KEYS,NULL,HFILL} + }, + { &hf_keys_soft_keys, + {"Number of Soft Keys","unistim.num.soft.keys",FT_UINT8, + BASE_DEC,NULL,KEY_NUM_SOFT_KEYS,NULL,HFILL} + }, + { &hf_keys_hd_key, + {"Headset Key Exists","unistim.exist.hd.key",FT_BOOLEAN, + 8,NULL,KEY_HD_KEY_EXISTS,NULL,HFILL} + }, + { &hf_keys_mute_key, + {"Mute Key Exists","unistim.exist.mute.key",FT_BOOLEAN, + 8,NULL,KEY_MUTE_KEY_EXISTS,NULL,HFILL} + }, + { &hf_keys_quit_key, + {"Quit Key Exists","unistim.exist.quit.key",FT_BOOLEAN, + 8,NULL,KEY_QUIT_KEY_EXISTS,NULL,HFILL} + }, + { &hf_keys_copy_key, + {"Copy Key Exists","unistim.exist.copy.key",FT_BOOLEAN, + 8,NULL,KEY_COPY_KEY_EXISTS,NULL,HFILL} + }, + { &hf_keys_mwi_key, + {"Message Waiting Indicator Exists","unistim.exist.mwi.key",FT_BOOLEAN, + 8,NULL,KEY_MWI_EXISTS,NULL,HFILL} + }, + { &hf_keys_num_nav_keys, + {"Number of Navigation Keys","unistim.num.nav.keys",FT_UINT8, + BASE_DEC,VALS(number_nav_keys),KEY_NUM_NAV_KEYS,NULL,HFILL} + }, + { &hf_keys_num_conspic_keys, + {"Number Of Conspicuous Keys","unistim.num.conspic.keys",FT_UINT8, + BASE_DEC,NULL,KEY_NUM_CONSPIC_KEYS,NULL,HFILL} + }, + { &hf_keys_send_key_rel, + {"Send Key Release","unistim.key.send.release",FT_BOOLEAN, + 8,TFS(&key_release),KEY_SEND_KEY_RELEASE,NULL,HFILL} + }, + { &hf_keys_enable_vol, + {"Enable Volume Control","unistim.key.enable.vol",FT_BOOLEAN, + 8,TFS(&enable_vol),KEY_ENABLE_VOL_KEY,NULL,HFILL} + }, + { &hf_keys_conspic_prog_key, + {"Conspicuous and Programmable Keys Same","unistim.conspic.prog.keys",FT_BOOLEAN, + 8,TFS(&conspic_prog),KEY_CONSPIC_PROG_KEY0,NULL,HFILL} + }, + { &hf_keys_acd_super_control, + {"ACD Supervisor Control","unistim.acd.super.control",FT_BOOLEAN, + 8,TFS(&acd_supervisor),KEY_ACD_SUP_CONTROL,NULL,HFILL} + }, + { &hf_keys_local_dial_feedback, + {"Local Keypad Feedback","unistim.key.feedback",FT_UINT8, + BASE_HEX,VALS(local_dialpad_feedback),KEY_LOCAL_DIAL_PAD_FEED,NULL,HFILL} + }, + { &hf_audio_source_descr, + {"Source Description Item","unistim.source.desc.item",FT_UINT8, + BASE_HEX,VALS(source_descriptions),AUDIO_SOURCE_DESCRIPTION,NULL,HFILL} + }, + { &hf_audio_sdes_rtcp_bucket, + {"RTCP Bucket Id","unistim.sdes.rtcp.bucket",FT_UINT8, + BASE_HEX,NULL,AUDIO_SDES_RTCP_BUCKET,NULL,HFILL} + }, + { &hf_audio_desired_jitter, + {"Desired Jitter","unistim.audio.desired.jitter",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_high_water_mark, + {"Threshold of audio frames where jitter buffer removes frames","unistim.high.water.mark",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_early_packet_resync_thresh, + {"Threshold in x/8000 sec where packets are too early","unistim.early.packet.thresh",FT_UINT32, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_late_packet_resync_thresh, + {"Threshold in x/8000 sec where packets are too late","unistim.late.packet.thresh",FT_UINT32, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_resolve_phone_port, + {"Resolve Phone Port","unistim.resolve.phone.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_far_end_echo_port, + {"Resolve Far End Port","unistim.resolve.far.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_far_end_ip_address, + {"Resolve Far End IP","unistim.resolve.far.ip",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_nat_port, + {"NAT Port","unistim.audio.nat.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_nat_ip_address, + {"NAT IP Address","unistim.audio.nat.ip",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_direction_code, + {"Stream Direction Code","unistim.audio.direction.codes",FT_UINT8, + BASE_HEX,VALS(direction_codes),AUDIO_DIRECTION_CODE,NULL,HFILL} + }, + { &hf_audio_hf_support, + {"Handsfree supported","unistim.handsfree.support",FT_BOOLEAN, + 8,NULL,AUDIO_HF_SUPPORT,NULL,HFILL} + }, + { &hf_audio_opt_rpt_max, + {"Max Volume","unistim.max.vol",FT_BOOLEAN, + 8,TFS(&opt_rpt_enable_max_tone_vol),AUDIO_ENABLED_MAX_TONE,NULL,HFILL} + }, + { &hf_audio_opt_rpt_adj_vol, + {"Volume Adjustments","unistim.audio.volume.adj",FT_BOOLEAN, + 8,TFS(&opt_rpt_adjust_volume),AUDIO_ENABLED_ADJ_VOL,NULL,HFILL} + }, + { &hf_audio_opt_rpt_auto_adj_vol, + {"Auto Adjust RX Volume","unistim.auto.adj.rx.vol",FT_BOOLEAN, + 8,TFS(&opt_rpt_automatic_adjustable_rx_volume_report), + AUDIO_AUTO_ADJ_RX_REP,NULL,HFILL} + }, + { &hf_audio_opt_rpt_hs_on_air, + {"HS On Air","unistim.audio.hs.on.air",FT_BOOLEAN, + 8,TFS(&opt_rpths_on_air_feature),AUDIO_HS_ON_AIR_FEATURE,NULL,HFILL} + }, + { &hf_audio_opt_rpt_hd_on_air, + {"HD On Air","unistim.audio.hd.on.air",FT_BOOLEAN, + 8,TFS(&opt_rpt_hd_on_air_feature),AUDIO_HD_ON_AIR_FEATURE,NULL,HFILL} + }, + { &hf_audio_opt_rpt_noise_squelch, + {"Automatic Squelch","unistim.auto.noise.squelch",FT_BOOLEAN, + 8,TFS(&opt_rpt_noise_sqlch_disable),AUDIO_NOISE_SQUELCH_DIS,NULL,HFILL} + }, + { &hf_audio_rx_vol_apb_rpt, + {"APB Volume Report","unistim.apb.volume.rpt",FT_UINT8, + BASE_HEX,VALS(volume_rpt_apbs),AUDIO_APB_VOL_RPT,NULL,HFILL} + }, + { &hf_audio_rx_vol_vol_up, + {"Volume Up","unistim.audio.volume.up",FT_BOOLEAN, + 8,NULL,AUDIO_VOL_UP_RPT,NULL,HFILL} + }, + { &hf_audio_rx_vol_vol_floor, + {"RX Volume at Floor","unistim.audio.rx.vol.floor",FT_BOOLEAN, + 8,NULL,AUDIO_VOL_FLR_RPT,NULL,HFILL} + }, + { &hf_audio_rx_vol_vol_ceiling, + {"RX Volume at Ceiling","unistim.audio.rx.vol.ceiling",FT_BOOLEAN, + 8,NULL,AUDIO_VOL_CEIL_RPT,NULL,HFILL} + }, + { &hf_audio_current_adj_vol_id, + {"Current APB Volume Report","unistim.current.volume.rpt",FT_UINT8, + BASE_HEX,VALS(volume_rpt_apbs),AUDIO_APB_VOL_RPT,NULL,HFILL} + }, + { &hf_audio_current_rx_level, + {"Current RX Volume Level","unistim.current.rx.vol.level",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_current_rx_range, + {"Current RX Volume Range","unistim.current.rx.vol.range",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_cadence_select, + {"Alerting Cadence Select","unistim.alert.cad.sel",FT_UINT8, + BASE_HEX,NULL,AUDIO_ALERT_CADENCE_SEL,NULL,HFILL} + }, + { &hf_audio_warbler_select, + {"Alerting Warbler Select","unistim.alert.warb.select",FT_UINT8, + BASE_HEX,NULL,AUDIO_ALERT_WARBLER_SEL,NULL,HFILL} + }, + { &hf_audio_open_stream_rpt, + {"Open Stream Report","unistim.open.audio.stream.rpt",FT_UINT8, + BASE_HEX,VALS(stream_result),0x0,NULL,HFILL} + }, + { &hf_audio_sdes_rpt_source_desc, + {"Report Source Description","unistim.rpt.src.desc",FT_UINT8, + BASE_HEX,VALS(source_descipts),AUDIO_SDES_INFO_RPT_DESC,NULL,HFILL} + }, + { &hf_audio_sdes_rpt_buk_id, + {"Report RTCP Bucket ID","unistim.rpt.rtcp.buk.id",FT_UINT8, + BASE_HEX,NULL,AUDIO_SDES_INFO_RPT_BUK,NULL,HFILL} + }, + { &hf_audio_phone_port, + {"Phone Listen Port","unistim.phone.listen.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_phone_ip, + {"Phone Listen Address","unistim.phone.listen.address",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_phone_add_len, + {"Phone Address Length","unistim.phone.address.len",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_nat_listen_port, + {"NAT Listen Port","unistim.nat.listen.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_nat_ip, + {"NAT Listen Address","unistim.nat.listen.address",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_nat_add_len, + {"NAT Address Length","unistim.nat.address.len",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_audio_stream_direction_code, + {"Audio Stream Direction","unistim.audio.stream.direction",FT_UINT8, + BASE_HEX,VALS(stream_direction_codes),AUDIO_STREAM_DIRECTION,NULL,HFILL} + }, + { &hf_audio_stream_state, + {"Audio Stream State","unistim.audio.stream.state",FT_BOOLEAN, + 8,TFS(&stream_states),AUDIO_STREAM_STATE,NULL,HFILL} + }, + { &hf_audio_transducer_list_length, + {"Transducer List Length","unistim.trans.list.len",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_net_file_xfer_mode, + {"File Transfer Mode","unistim.net.file.xfer.mode",FT_UINT8, + BASE_HEX,VALS(file_xfer_modes),NETWORK_FILE_XFER_MODE,NULL,HFILL} + }, + { &hf_net_force_download , + {"Force Download","unistim.net.force.download",FT_BOOLEAN, + 8,NULL,NETWORK_FORCE_DLOAD,NULL,HFILL} + }, + { &hf_net_use_file_server_port, + {"Use Custom Server Port","unistim.net.use.server.port",FT_BOOLEAN, + 8,NULL,NETWORK_USE_FSERV_PORT,NULL,HFILL} + }, + { &hf_net_use_local_port, + {"Use Custom Local Port","unistim.net.use.local.port",FT_BOOLEAN, + 8,NULL,NETWORK_USE_LOCAL_PORT,NULL,HFILL} + }, + { &hf_net_file_server_port, + {"File Server Port","unistim.net.file.server.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_net_full_pathname, + {"Full Pathname","unistim.net.full_pathname",FT_STRINGZ, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_net_file_identifier, + {"File Identifier","unistim.net.file_identifier",FT_STRINGZ, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_net_local_port, + {"Local XFer Port","unistim.net.local.xfer.port",FT_UINT16, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_net_file_server_address, + {"File Server IP Address","unistim.net.file.server.address",FT_IPv4, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_keys_admin_command, + {"Admin Command","unistim.key.icon.admin.cmd",FT_UINT8, + BASE_HEX,VALS(admin_commands),KEY_ADMIN_CMD,NULL,HFILL} + }, + { &hf_keys_logical_icon_id, + {"Logical Icon ID","unistim.keys.logical.icon.id",FT_UINT16, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_keys_repeat_timer_one, + {"Key Repeat Timer 1 Value","unistim.keys.repeat.time.one",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_keys_repeat_timer_two, + {"Key Repeat Timer 2 Value","unistim.keys.repeat.time.two",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_keys_led_id, + {"Led ID","unistim.keys.led.id",FT_UINT8, + BASE_HEX,VALS(keys_led_ids),0x0,NULL,HFILL} + }, + { &hf_keys_phone_icon_id, + {"Phone Icon ID","unistim.keys.phone.icon.id",FT_UINT8, + BASE_HEX,NULL,0x0,NULL,HFILL} + }, + { &hf_keys_cadence_on_time, + {"Indicator Cadence On Time","unistim.keys.cadence.on.time",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_keys_cadence_off_time, + {"Indicator Cadence Off Time","unistim.keys.cadence.off.time",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_keys_user_activity_timeout, + {"User Activity Timeout Value","unistim.keys.user.timeout.value",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_display_call_timer_mode, + {"Call Timer Mode","unistim.display.call.timer.mode",FT_BOOLEAN, + 8,TFS(&call_duration_timer_mode),DISPLAY_CALL_TIMER_MODE,NULL,HFILL} + }, + { &hf_display_call_timer_reset, + {"Call Timer Reset","unistim.display.call.timer.reset",FT_BOOLEAN, + 8,TFS(&call_duration_timer_reset),DISPLAY_CALL_TIMER_RESET,NULL,HFILL} + }, + { &hf_display_call_timer_display, + {"Call Timer Display","unistim.display.call.timer.display",FT_BOOLEAN, + 8,TFS(&call_duration_display_timer),DISPLAY_CALL_TIMER_DISPLAY,NULL,HFILL} + }, + { &hf_display_call_timer_delay, + {"Call Timer Delay","unistim.display.call.timer.delay",FT_BOOLEAN, + 8,TFS(&call_duration_timer_delay),DISPLAY_CALL_TIMER_DELAY,NULL,HFILL} + }, + { &hf_display_call_timer_id, + {"Call Timer ID","unistim.display.call.timer.id",FT_UINT8, + BASE_DEC,NULL,DISPLAY_CALL_TIMER_ID,NULL,HFILL} + }, + { &hf_expansion_switch_cmd, + {"Expansion CMD (switch)","unistim.expansion.switch",FT_UINT8, + BASE_HEX,VALS(expansion_switch_msgs),0x0,NULL,HFILL} + }, + { &hf_expansion_phone_cmd, + {"Expansion CMD (phone)","unistim.expansion.phone",FT_UINT8, + BASE_HEX,VALS(expansion_phone_msgs),0x0,NULL,HFILL} + }, + { &hf_module_key_number, + {"Module Key Number","unistim.module.key.number",FT_INT32, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + { &hf_expansion_softlabel_number, + {"Module Soft Label Number","unistim.expansion.label.number",FT_UINT8, + BASE_DEC,NULL,0x0,NULL,HFILL} + }, + + + /****LAST****/ + { &hf_generic_string, + {"DATA","unistim.generic.string_data",FT_STRING, + BASE_NONE,NULL,0x0,NULL,HFILL} + }, + { &hf_generic_data, + {"DATA","unistim.generic.data",FT_BYTES, + BASE_NONE,NULL,0x0,NULL,HFILL} + } + }; + +/* Setup protocol subtree array */ + + static gint *ett[] = { + &ett_unistim + }; + + static ei_register_info ei[] = { + { &ei_unistim_len, { "unistim.len.bad", PI_MALFORMED, PI_ERROR, "Length too short", EXPFILL }}, + }; + + expert_module_t* expert_unistim; + + proto_unistim=proto_register_protocol("UNISTIM Protocol", "UNISTIM", "unistim"); + unistim_handle=register_dissector("unistim", dissect_unistim,proto_unistim); + + proto_register_subtree_array(ett,array_length(ett)); + proto_register_field_array(proto_unistim,hf,array_length(hf)); + expert_unistim = expert_register_protocol(proto_unistim); + expert_register_field_array(expert_unistim, ei, array_length(ei)); + + unistim_tap = register_tap("unistim"); +} + +void +proto_reg_handoff_unistim(void) { + dissector_add_for_decode_as_with_preference("udp.port", unistim_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 3 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=3 tabstop=8 expandtab: + * :indentSize=3:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/unistim/packet-unistim.h b/plugins/epan/unistim/packet-unistim.h new file mode 100644 index 00000000..b1462a6a --- /dev/null +++ b/plugins/epan/unistim/packet-unistim.h @@ -0,0 +1,37 @@ +/* packet-unistim.h + * header field declarations, value_string definitions, true_false_string + * definitions and function prototypes for main dissectors + * Copyright 2007 Don Newton + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef PACKET_UNISTIM_H +#define PACKET_UNISTIM_H + +typedef struct _unistim_info_t +{ + guint8 rudp_type; /* NAK, ACK, Payload */ + guint8 payload_type; /* unistim payload type (aggregate, non-aggregate, encapsulated) */ + guint32 sequence; /* rudp sequence number */ + guint32 termid; /* termid if available */ + address it_ip; /* IP addr of it, determined by who is sending termids */ + guint32 it_port; /* port of it (phone) */ + address ni_ip; /* IP addr of ni (server) as determined by who's sending termids */ + gint key_val; /* actual key pressed (-1 if not used) */ + gint key_state; /* Key state 1=down 0=up */ + gint hook_state; /* Hook state 1=offhook 0=onhook */ + gint stream_connect; /* Audio stream connect 1=connect 0=disconnect */ + gint trans_connect; /* Transducer connect? 1=connect 0=disconnect */ + gint set_termid; /* Set the termid 1=set termid */ + const guint8 *string_data; /* Any time a string is written to the display, this has the string */ + gint call_state; /* Not used? */ + guchar *key_buffer; /* Used in voip-calls.c tap, holds call keys pressed */ +} unistim_info_t; + +#endif + diff --git a/plugins/epan/unistim/uftp.h b/plugins/epan/unistim/uftp.h new file mode 100644 index 00000000..865f23b5 --- /dev/null +++ b/plugins/epan/unistim/uftp.h @@ -0,0 +1,34 @@ +/* uftp.h + * header field declarations, value_string def and true_false_string + * definitions for uftp commands and messages + * Copyright 2007 Chad Singer + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef UNISTIM_UFTP_H +#define UNISTIM_UFTP_H + +static int hf_uftp_datablock_size=-1; +static int hf_uftp_datablock_limit=-1; +static int hf_uftp_filename=-1; +static int hf_uftp_datablock=-1; +static int hf_uftp_command=-1; + +static const value_string uftp_commands[]={ + {0x00,"Connection Granted"}, + {0x01,"Connection Denied"}, + {0x02,"File Data Block"}, + {0x80,"Connection Request"}, + {0x81,"Connection Details"}, + {0x82,"Flow Control Off"}, + {0,NULL} +}; + +#endif + + diff --git a/plugins/epan/wimax/.editorconfig b/plugins/epan/wimax/.editorconfig new file mode 100644 index 00000000..541cd9d3 --- /dev/null +++ b/plugins/epan/wimax/.editorconfig @@ -0,0 +1,10 @@ +# +# Editor configuration +# +# https://editorconfig.org/ +# + +[msg_dlmap.[ch]] +indent_style = tab +indent_size = tab + diff --git a/plugins/epan/wimax/AUTHORS b/plugins/epan/wimax/AUTHORS new file mode 100644 index 00000000..f7c8e66c --- /dev/null +++ b/plugins/epan/wimax/AUTHORS @@ -0,0 +1,5 @@ +Authors: +Lu Pan +Mike Harvey +John R. Underwood +Daniel J. Sauble diff --git a/plugins/epan/wimax/CMakeLists.txt b/plugins/epan/wimax/CMakeLists.txt new file mode 100644 index 00000000..50c3a7a3 --- /dev/null +++ b/plugins/epan/wimax/CMakeLists.txt @@ -0,0 +1,112 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(wimax 1 2 0 0) + +set(DISSECTOR_SRC + packet-m2m.c + packet-wmx.c +) + +set(DISSECTOR_SUPPORT_SRC + wimax_ffb_decoder.c + wimax_fch_decoder.c + wimax_pdu_decoder.c + wimax_cdma_code_decoder.c + wimax_hack_decoder.c + wimax_phy_attributes_decoder.c + mac_hd_generic_decoder.c + mac_hd_type1_decoder.c + mac_hd_type2_decoder.c + mac_mgmt_msg_decoder.c + msg_dcd.c + msg_ucd.c + msg_dlmap.c + msg_ulmap.c + msg_rng_req.c + msg_rng_rsp.c + msg_reg_req.c + msg_reg_rsp.c + msg_dreg.c + msg_dsa.c + msg_dsc.c + msg_dsd.c + msg_arq.c + msg_sbc.c + msg_pkm.c + msg_aas_fbck.c + msg_fpc.c + msg_pmc.c + msg_prc_lt_ctrl.c + msg_aas_beam.c + msg_res_cmd.c + msg_rep.c + msg_clk_cmp.c + msg_dsx_rvd.c + wimax_harq_map_decoder.c + wimax_compact_dlmap_ie_decoder.c + wimax_compact_ulmap_ie_decoder.c + wimax_utils.c + crc.c + crc_data.c + wimax_tlv.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} +) + +add_wireshark_plugin_library(wimax epan) + +target_link_libraries(wimax epan) + +install_plugin(wimax epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + wimax + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_SUPPORT_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/wimax/README.wimax b/plugins/epan/wimax/README.wimax new file mode 100644 index 00000000..4f7981fc --- /dev/null +++ b/plugins/epan/wimax/README.wimax @@ -0,0 +1,86 @@ +This document is an attempt, to explain how to use the wimax plugin +in this directory. + + +Overview +-------- +The wimax plugin is a standalone Wireshark plugin that contains a set +of WiMax Protocol dissectors. The plugin registers the WiMax Protocol +dissectors without attached to any packet type. So none of the +dissectors will be called by the Wireshark because there is no any +packet type hookup to the plugin. However, it is very simple to add +the WiMax Protocol decoding capability into any of the packet decoder +by searching and calling the WiMax Protocol dissectors since they are +registered to Wireshark already (see WiMAX M2M Encapsulation Protocol +for an example). + + +WiMax Protocol dissector list +------------- +WiMax Burst Dissectors: + 1. wimax_cdma_code_burst_handler - WiMax CDMA Code Attribute Burst dissector. + 2. wimax_fch_burst_handler - WiMax FCH Burst dissector. + 3. wimax_ffb_burst_handler - WiMax Fast Feedback Burst dissector. + 4. wimax_pdu_burst_handler - WiMax PDU Burst dissector. + 5. wimax_hack_burst_handler - WiMax HACK Burst dissector. + 6. wimax_phy_attributes_burst_handler - WiMax PHY Attributes Burst dissector. + +WiMax MAC dissectors: + 7. mac_header_type_1_handler - WiMax TYPE I MAC Header PDU dissector. + 8. mac_header_type_2_handler - WiMax TYPE II MAC Header PDU dissector. + 9. mac_header_generic_handler - WiMax Generic MAC Header PDU dissector. + 10. mac_mgmt_msg_handler - WiMax MAC Management Messages dissector. + +WiMax Utility dissectors: +11. wimax_service_flow_encodings_decoder - WiMax Service Flow Encodings dissector. +12. wimax_error_parameter_set_decoder - WiMax Error Parameter Set dissector. +13. wimax_security_negotiation_parameters_decoder - WiMax Security Negotiation Parameter dissector. +14. wimax_pkm_tlv_encoded_attributes_decoder - WiMax PKM TLV Encoded Attributes dissector. +15. wimax_tek_parameters_decoder - WiMax TEK Parameters dissector. +16. wimax_pkm_configuration_settings_decoder - WiMax PKM Configuration Settings dissector. +17. wimax_sa_descriptor_decoder - WiMax SA Descriptor dissector. +18. wimax_cryptographic_suite_list_decoder - WiMax Cryptographic Suite List dissector. +19. wimax_security_capabilities_decoder - WiMax Security Capabilities dissector. +20. wimax_common_tlv_encoding_decoder - WiMax Common TLV Encoding dissector. +19. wimax_vendor_specific_information_decoder - WiMax Vendor-Specific Information dissector. + + +Usages +-------- +To use any of the dissectors listed above: + +1. Call Wireshark function: handle = find_dissector("dissector_name") +to get the dissector's handler. +Example: mgt_msg_handle = find_dissector("mac_mgmt_msg_handler"); + +2. If find_dissector() finds the dissector successfully a non-NULL +handle will be returned. Then call another Wireshark function: +call_dissector(handle, tvb, pinfo, tree) to call the dissector +corresponding to the handle. + +Here, handle is the value returned by find_dissector() function. + tvb is the pointer of the data buffer which contains the exact + content defined by the IEEE 802.16 standards for the dissector. + pinfo is the pointer to the packet information from Wireshark. + tree is the pointer to the display tree or sub-tree. +Example: call_dissector(mgt_msg_handle, mgt_msg_tvb, pinfo, mgt_msg_tree); + +3. The WiMax Utility dissectors should be called directly. + + +Notes +-------- +1. All the burst data has to be defraged before passing it to the +WiMax burst dissectors. + +2. The wimax_pdu_burst_handler will automatically call +mac_header_generic_handler, mac_header_type_1_handler and +mac_header_type_2_handler based on the PDU contents. + +3. The mac_header_generic_handler will automatically call +mac_mgmt_msg_handler based on the PDU payload. + +4. All the dissectors can be called independently but the data passed +to the dissectors has to contain exact content defined by the +IEEE 802.16 standards. + diff --git a/plugins/epan/wimax/crc.c b/plugins/epan/wimax/crc.c new file mode 100644 index 00000000..4bc74a2a --- /dev/null +++ b/plugins/epan/wimax/crc.c @@ -0,0 +1,198 @@ +/* crc.c + * crc checksum generation and calculation functions: crc.c + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Mike Harvey + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "crc.h" + +#define WMAX_MAC_CRC32_POLYNOMIAL 0x04c11db7U /* polynomial used in calculating the CRC-32 checksum */ +#define CCITT_X25_CRC16_POLYNOMIAL 0x1021 /* polynomial used in calculating the CRC-16 checksum */ +#define WMAX_MAC_CRC8_POLYNOMIAL 0x07 /* polynomial used in calculating the CRC-8 checksum */ +#define CRC32_INITIAL_VALUE 0xFFFFFFFF +#define CRC16_INITIAL_VALUE 0xFFFF + +#ifndef STATIC_DATA +static guint8 crc8_table[256]; +static guint32 crc32_table[256]; + +extern guint16 crc16_table[256]; + +/* + void wimax_mac_gen_crc32_table(void) + + REQUIRES: The functions must be called only once to initialze CRC table + + DESCRIPTION: Generate the table of CRC remainders + for all possible bytes + + ARGS: + + RETURNS: + + SIDE EFFECTS: + +*/ +void wimax_mac_gen_crc32_table(void) +{ + guint32 i, bit; + guint32 crc; + + /* little-endian (reflected) algorithm */ + for ( i = 0; i < G_N_ELEMENTS(crc32_table); i++ ) + { + crc = ( i << 24 ); + for ( bit = 0; bit < 8; bit++ ) + { + if ( crc & 0x80000000U ) + crc = ( crc << 1 ) ^ WMAX_MAC_CRC32_POLYNOMIAL; + else + crc = ( crc << 1 ); + } + crc32_table[i] = crc; + } +} + +/* + void wimax_mac_gen_crc8_table(void) + + REQUIRES: The functions must be called only once to initialze CRC table + + DESCRIPTION: Generate the table of CRC remainders + for all possible bytes + + ARGS: + + RETURNS: + + SIDE EFFECTS: + +*/ +void wimax_mac_gen_crc8_table(void) +{ + guint i, bit; + guint8 crc; + + for ( i = 0; i < G_N_ELEMENTS(crc8_table); i++ ) + { + crc = i; + for ( bit = 0; bit < 8; bit++ ) + { + if ( crc & 0x80 ) + crc = ( crc << 1 ) ^ WMAX_MAC_CRC8_POLYNOMIAL; + else + crc = ( crc << 1 ); + } + crc8_table[i] = crc; + } +} +#endif + +/* + + guint32 wimax_mac_calc_crc32(guint8 *data, guint data_len) + + REQUIRES: wimax_mac_gen_crc32_table() must be called before + + DESCRIPTION: Calculate the 32-bit CRC from a given data block + + ARGS: data - pointer to data + data_len - length of data (in bytes) + + RETURNS: calculated crc32 + + SIDE EFFECTS: + +*/ +guint32 wimax_mac_calc_crc32(const guint8 *data, guint data_len) +{ + guint32 crc=CRC32_INITIAL_VALUE; + guint i, j; + + for ( j = 0; j < data_len; j++ ) + { + i = ( (guint8)(crc>>24) ^ data[j] ) & 0xff; + crc = ( crc<<8 ) ^ crc32_table[i]; + } + return ~crc; +} + +/* + + guint16 wimax_mac_calc_crc16(guint8 *data, guint data_len) + + REQUIRES: crc16_table[] in crc_data.c + + DESCRIPTION: Calculate the 16-bit CRC from a given data block + + ARGS: data - pointer to data + data_len - length of data (in bytes) + + RETURNS: calculated crc16 + + SIDE EFFECTS: + +*/ +guint16 wimax_mac_calc_crc16(const guint8 *data, guint data_len) +{ + guint32 crc=CRC16_INITIAL_VALUE; + guint j; + + for ( j = 0; j < data_len; j++ ) + { + crc ^= data[j] << 8; + crc = (crc << 8) ^ crc16_table[(crc & 0xff00) >> 8]; + } + crc ^= 0xFFFF; /* Invert the output. */ + crc &= 0xFFFF; + return crc; +} + +/* + + guint8 wimax_mac_calc_crc8(guint8 *data, guint data_len) + + REQUIRES: wimax_mac_gen_crc8_table() must be called before + + DESCRIPTION: Calculate the 8-bit CRC from a given data block + + ARGS: data - pointer to data + data_len - length of data (in bytes) + + RETURNS: calculated crc8 + + SIDE EFFECTS: + +*/ +guint8 wimax_mac_calc_crc8(const guint8 *data, guint data_len) +{ + guint8 crc=0; + guint i; + + for(i = 0; i < data_len; i++) + { + crc = crc8_table[data[i]^crc]; + } + return crc; +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local Variables: + * c-basic-offset: 2 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=2 tabstop=8 expandtab: + * :indentSize=2:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/wimax/crc.h b/plugins/epan/wimax/crc.h new file mode 100644 index 00000000..43c5faf1 --- /dev/null +++ b/plugins/epan/wimax/crc.h @@ -0,0 +1,33 @@ +/* crc.h + * header file of crc.c + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Mike Harvey + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef CRC_H +#define CRC_H + +#include + +/* use lookup tables to compute CRC values */ +#ifdef STATIC_DATA +extern guint8 crc8_table[]; +extern guint32 crc32_table[]; +#else +void wimax_mac_gen_crc32_table(void); +void wimax_mac_gen_crc8_table(void); +#endif + +guint32 wimax_mac_calc_crc32(const guint8 *data, guint data_len); +guint16 wimax_mac_calc_crc16(const guint8 *data, guint data_len); +guint8 wimax_mac_calc_crc8(const guint8 *data, guint data_len); + +#endif /* CRC_H */ diff --git a/plugins/epan/wimax/crc_data.c b/plugins/epan/wimax/crc_data.c new file mode 100644 index 00000000..0dcc8b27 --- /dev/null +++ b/plugins/epan/wimax/crc_data.c @@ -0,0 +1,171 @@ +/* crc_data.c + * static crc tables for crc.c + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Mike Harvey + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "crc.h" + +#ifdef STATIC_DATA + +#include + +guint32 crc32_table[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, + 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, + 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, + 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, + 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, + 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, + 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, + 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, + 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, + 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, + 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, + 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, + 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, + 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, + 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, + 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, + 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, + 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, + 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, + 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, + 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, + 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, + 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, + 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, + 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, + 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, + 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, + 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, + 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, + 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, + 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, + 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, + 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, + 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, + 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, + 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, + 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, + 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, + 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, + 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, + 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, + 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, + 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + + +guint8 hcs_table[256] = { + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, + 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, + 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, + 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, + 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, + 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, + 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, + 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, + 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, + 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, + 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, + 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, + 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, + 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, + 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, + 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, + 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, + 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, + 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, + 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, + 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, + 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, + 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, + 0x76, 0x71, 0x78, 0x7f, 0x6a, 0x6d, 0x64, 0x63, + 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, + 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, + 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, + 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8d, 0x84, 0x83, + 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, + 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 +}; +#endif + +guint16 crc16_table[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, + 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, + 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, + 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, + 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, + 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, + 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, + 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, + 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, + 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, + 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, + 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, + 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, + 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, + 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, + 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, + 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, +}; + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/wimax/mac_hd_generic_decoder.c b/plugins/epan/wimax/mac_hd_generic_decoder.c new file mode 100644 index 00000000..d083103a --- /dev/null +++ b/plugins/epan/wimax/mac_hd_generic_decoder.c @@ -0,0 +1,2300 @@ +/* mac_hd_generic_decoder.c + * WiMax Generic MAC Header decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* TODO: Add FT_UINT24 and FT_INT24 cases to gtk_widget_get_toplevel() + * to prevent having to make all the changes from BASE_DEC to BASE_HEX + * made to this file today: 10/20/06. + */ + +/* Include files */ + +#include "config.h" + +/* +#define DEBUG +*/ + +#include + +#include +#include +#include +#include "crc.h" +#include "wimax-int.h" +#include "wimax_utils.h" + +void proto_reg_handoff_mac_header_generic(void); + +extern gint proto_wimax; + +extern gint seen_a_service_type; +extern gboolean first_gmh; /* defined in wimax_pdu_decoder.c */ + +extern gint8 arq_enabled; /* declared in packet-wmx.c */ +extern gint scheduling_service_type; /* declared in packet-wmx.c */ + +extern address bs_address; /* declared in packet-wmx.c */ +extern guint max_logical_bands; /* declared in wimax_compact_dlmap_ie_decoder.c */ + +static dissector_handle_t mac_mgmt_msg_decoder_handle = NULL; +static dissector_handle_t mac_ip_handle = NULL; + +/* global variables */ +gboolean include_cor2_changes = FALSE; + +/* Well-known CIDs */ +guint cid_initial_ranging = 0x0000; +guint global_cid_max_basic = 320; +guint cid_max_primary = 640; +guint cid_aas_ranging = 0xFeFF; +guint cid_normal_multicast = 0xFFFa; +guint cid_sleep_multicast = 0xFFFb; +guint cid_idle_multicast = 0xFFFc; +guint cid_frag_broadcast = 0xFFFd; +guint cid_padding = 0xFFFe; +guint cid_broadcast = 0xFFFF; + +/* Maximum number of CID's */ +#define MAX_CID 64 + +/* forward reference */ +static gint extended_subheader_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +static gint arq_feedback_payload_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *parent_item); + +/* Static variables */ +static reassembly_table payload_reassembly_table; + +gint proto_mac_header_generic_decoder = -1; +static gint ett_mac_header_generic_decoder = -1; +/* static gint ett_mac_subheader_decoder = -1; */ +static gint ett_mac_mesh_subheader_decoder = -1; +static gint ett_mac_frag_subheader_decoder = -1; +static gint ett_mac_grant_mgmt_subheader_decoder = -1; +static gint ett_mac_pkt_subheader_decoder = -1; +static gint ett_mac_fast_fb_subheader_decoder = -1; +static gint ett_mac_ext_subheader_decoder = -1; +static gint ett_mac_ext_subheader_dl_decoder = -1; +static gint ett_mac_ext_subheader_ul_decoder = -1; +static gint ett_mac_arq_fb_payload_decoder = -1; +static gint ett_mac_data_pdu_decoder = -1; +static gint hf_mac_header_generic_value_bytes = -1; + +static guint frag_type, frag_len; +static guint extended_type, arq_fb_payload, seq_number; + +static guint cid_adjust[MAX_CID]; /* Must not start with 0 */ +static guint cid_vernier[MAX_CID]; +static guint cid_adj_array_size = 0; +static guint *cid_adj_array = NULL; +static guint8 *frag_num_array = NULL; + +static address save_src; +static address save_dst; + +#define WIMAX_MAC_HEADER_SIZE 6 +#define IP_HEADER_BYTE 0x45 + +#define EXTENDED_SUB_HEADER_RSV_MASK 0x80 +#define EXTENDED_SUB_HEADER_TYPE_MASK 0x7F + +/* WIMAX GENERIC MAC HEADER FIELDS (figure 19) */ +/* 1st to 3rd bytes */ +#define WIMAX_MAC_HEADER_GENERIC_HT 0x800000 +#define WIMAX_MAC_HEADER_GENERIC_EC 0x400000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_5 0x200000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_4 0x100000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_3 0x080000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_2 0x040000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_1 0x020000 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_0 0x010000 +#define WIMAX_MAC_HEADER_GENERIC_ESF 0x008000 +#define WIMAX_MAC_HEADER_GENERIC_CI 0x004000 +#define WIMAX_MAC_HEADER_GENERIC_EKS 0x003000 +#define WIMAX_MAC_HEADER_GENERIC_RSV 0x000800 +#define WIMAX_MAC_HEADER_GENERIC_LEN 0x0007FF + +/* WIMAX GENERIC MAC HEADER 1st byte masks */ +#define WIMAX_MAC_HEADER_GENERIC_HT_MASK 0x80 +#define WIMAX_MAC_HEADER_GENERIC_EC_MASK 0x40 +#define WIMAX_MAC_HEADER_GENERIC_TYPE_MASK 0x3F +/* WiMax Generic MAC Header Sub Type Masks */ +#define GENERIC_SUB_TYPE_0 0x01 +#define GENERIC_SUB_TYPE_1 0x02 +#define GENERIC_SUB_TYPE_2 0x04 +#define GENERIC_SUB_TYPE_3 0x08 +#define GENERIC_SUB_TYPE_4 0x10 +#define GENERIC_SUB_TYPE_5 0x20 + +/* WIMAX GENERIC MAC HEADER 2nd byte masks */ +#define WIMAX_MAC_HEADER_GENERIC_ESF_MASK 0x80 +#define WIMAX_MAC_HEADER_GENERIC_CI_MASK 0x40 +#define WIMAX_MAC_HEADER_GENERIC_EKS_MASK 0x30 +#define WIMAX_MAC_HEADER_GENERIC_LEN_MASK 0x07 + +static int hf_mac_header_generic_ht = -1; +static int hf_mac_header_generic_ec = -1; +static int hf_mac_header_generic_type_0 = -1; +static int hf_mac_header_generic_type_1 = -1; +static int hf_mac_header_generic_type_2 = -1; +static int hf_mac_header_generic_type_3 = -1; +static int hf_mac_header_generic_type_4 = -1; +static int hf_mac_header_generic_type_5 = -1; +static int hf_mac_header_generic_esf = -1; +static int hf_mac_header_generic_ci = -1; +static int hf_mac_header_generic_eks = -1; +static int hf_mac_header_generic_rsv = -1; +static int hf_mac_header_generic_len = -1; +static int hf_mac_header_generic_cid = -1; +static int hf_mac_header_generic_hcs = -1; +static int hf_mac_header_generic_crc = -1; +static int hf_mac_header_generic_crc_status = -1; + +/* MAC Header types */ +static const value_string ht_msgs[] = +{ + { 0, "Generic" }, + { 1, "Signaling" }, + { 0, NULL} +}; + +/* Encryption Controls */ +static const value_string ec_msgs[] = +{ + { 0, "Not encrypted" }, + { 1, "Encrypted" }, + { 0, NULL} +}; + +/* ESF messages */ +static const value_string esf_msgs[] = +{ + { 0, "Extended subheader is absent" }, + { 1, "Extended subheader is present" }, + { 0, NULL} +}; + +/* CRC Indicator messages */ +static const value_string ci_msgs[] = +{ + { 0, "No CRC is included" }, + { 1, "CRC is included" }, + { 0, NULL} +}; + +/* Sub-Type message 0 */ +static const value_string type_msg0[] = +{ + { 0, "Fast-feedback allocation subheader(DL)/Grant management subheader(UL) is absent" }, + { 1, "Fast-feedback allocation subheader(DL)/Grant management subheader(UL) is present" }, + { 0, NULL} +}; + +/* Sub-Type message 1 */ +static const value_string type_msg1[] = +{ + { 0, "Packing subheader is absent" }, + { 1, "Packing Subheader is present" }, + { 0, NULL} +}; + +/* Sub-Type message 2 */ +static const value_string type_msg2[] = +{ + { 0, "Fragmentation subheader is absent" }, + { 1, "Fragmentation subheader is present" }, + { 0, NULL} +}; + +/* Sub-Type message 3 */ +static const value_string type_msg3[] = +{ + { 0, "The subheader is not extended" }, + { 1, "The subheader is extended" }, + { 0, NULL} +}; + +/* Sub-Type message 4 */ +static const value_string type_msg4[] = +{ + { 0, "ARQ feedback payload is absent" }, + { 1, "ARQ feedback payload is present" }, + { 0, NULL} +}; + +/* Sub-Type message 5 */ +static const value_string type_msg5[] = +{ + { 0, "Mesh subheader is absent" }, + { 1, "Mesh subheader is present" }, + { 0, NULL} +}; + +/* Fast-Feedback Feedback Types */ +static const value_string fast_fb_types[] = +{ + { 0, "Fast DL measurement" }, + { 1, "Fast MIMO Feedback, Antenna #0" }, + { 2, "Fast MIMO Feedback, Antenna #1" }, + { 3, "MIMO Mode and Permutation Mode Feedback" }, + { 0, NULL} +}; + +/* Extended sub-headers */ +/* DL sub-header types */ +typedef enum +{ +SDU_SN, +DL_SLEEP_CONTROL, +FEEDBACK_REQ, +SN_REQ, +PDU_SN_SHORT_DL, +PDU_SN_LONG_DL +} DL_EXT_SUBHEADER_e; + +static const value_string dl_ext_sub_header_type[] = +{ + {0, "SDU_SN"}, + {1, "DL Sleep Control"}, + {2, "Feedback Request"}, + {3, "SN Request"}, + {4, "PDU SN (short)"}, + {5, "PDU SN (long)"}, + {0, NULL} +}; + +/* DL Sleep Control Extended Subheader field masks (table 13e) */ +#define DL_SLEEP_CONTROL_POWER_SAVING_CLASS_ID_MASK 0xFC0000 /*0x00003F*/ +#define DL_SLEEP_CONTROL_OPERATION_MASK 0x020000 /*0x000040*/ +#define DL_SLEEP_CONTROL_FINAL_SLEEP_WINDOW_EXPONENT_MASK 0x01C000 /*0x000380*/ +#define DL_SLEEP_CONTROL_FINAL_SLEEP_WINDOW_BASE_MASK 0x003FF0 /*0x0FFC00*/ +#define DL_SLEEP_CONTROL_RESERVED_MASK 0x00000F /*0xF00000*/ + +/* Feedback Request Extended Subheader field masks (table 13f) */ +#define FEEDBACK_REQUEST_UIUC_MASK 0xF00000 /*0x00000F*/ +#define FEEDBACK_REQUEST_FEEDBACK_TYPE_MASK 0x0F0000 /*0x0000F0*/ +#define FEEDBACK_REQUEST_OFDMA_SYMBOL_OFFSET_MASK 0x00FC00 /*0x003F00*/ +#define FEEDBACK_REQUEST_SUBCHANNEL_OFFSET_MASK 0x0003F0 /*0x0FC000*/ +#define FEEDBACK_REQUEST_NUMBER_OF_SLOTS_MASK 0x00000E /*0x700000*/ +#define FEEDBACK_REQUEST_FRAME_OFFSET_MASK 0x000001 /*0x800000*/ + +/* OFDMA UIUC Values ??? */ +static const value_string uiuc_values[] = +{ + { 0, "Fast-Feedback Channel" }, + { 1, "Burst Profile 1" }, + { 2, "Burst Profile 2" }, + { 3, "Burst Profile 3" }, + { 4, "Burst Profile 4" }, + { 5, "Burst Profile 5" }, + { 6, "Burst Profile 6" }, + { 7, "Burst Profile 7" }, + { 8, "Burst Profile 8" }, + { 9, "Burst Profile 9" }, + { 10, "Burst Profile 10" }, + { 11, "Extended UIUC 2 IE" }, + { 12, "CDMA Bandwidth Request, CDMA Ranging" }, + { 13, "PAPR Reduction Allocation, Safety Zone" }, + { 14, "CDMA Allocation IE" }, + { 15, "Extended UIUC" }, + { 0, NULL} +}; + +/* UL sub-header types */ +typedef enum +{ +MIMO_MODE_FEEDBACK, +UL_TX_POWER_REPORT, +MINI_FEEDBACK, +PDU_SN_SHORT_UL, +PDU_SN_LONG_UL +} UL_EXT_SUBHEADER_e; + +static const value_string ul_ext_sub_header_type[] = +{ + {0, "MIMO Mode Feedback"}, + {1, "UL TX Power Report"}, + {2, "Mini-feedback"}, + {3, "PDU SN (short)"}, + {4, "PDU SN (long)"}, + {0, NULL} +}; + +/* MIMO Mode Feedback Extended Subheader field masks (table 13g) */ +#define MIMO_FEEDBACK_TYPE_MASK 0xC0 /*0x03*/ +#define MIMO_FEEDBACK_CONTENT_MASK 0x3F /*0xFC*/ +/* Mimo Feedback Types ??? */ +static const value_string mimo_fb_types[] = +{ + { 0, "Fast DL measurement" }, + { 1, "Default Feedback with Antenna Grouping" }, + { 2, "Antenna Selection and Reduced Codebook" }, + { 3, "Quantized Precoding Weight Feedback" }, + { 0, NULL} +}; + +/* MNI-Feedback Extended Subheader field masks (table 13i) */ +#define MINI_FEEDBACK_TYPE_MASK 0xF000 /*0x000F*/ +#define MINI_FEEDBACK_CONTENT_MASK 0x0FFF /*0xFFF0*/ +/* Feedback Types */ +static const value_string fb_types[] = +{ + { 0, "CQI and MIMO Feedback" }, + { 1, "DL average CINR" }, + { 2, "MIMO Coefficients Feedback" }, + { 3, "Preferred DL Channel DIUC Feedback" }, + { 4, "UL Transmission Power" }, + { 5, "PHY Channel Feedback" }, + { 6, "AMC Band Indication Bitmap" }, + { 7, "Life Span of Short-term Precoding Feedback" }, + { 8, "Multiple Types of Feedback" }, + { 9, "Long-term Precoding Feedback" }, + { 10, "Combined DL Average CINR of Active BSs" }, + { 11, "MIMO Channel Feedback" }, + { 12, "CINR Feedback" }, + { 13, "Close-loop MIMO Feedback" }, + { 14, "Reserved" }, + { 15, "Reserved" }, + { 0, NULL} +}; + +/* common fields */ +static gint hf_mac_header_generic_ext_subheader_rsv = -1; +/* DL sub-header */ +static gint hf_mac_header_generic_ext_subheader_type_dl = -1; +static gint hf_mac_header_generic_ext_subheader_sdu_sn = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_pscid = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_op = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_fswe = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_fswb = -1; +static gint hf_mac_header_generic_ext_subheader_dl_sleep_control_rsv = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_uiuc = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_fb_type = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_ofdma_symbol_offset = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_subchannel_offset = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_slots = -1; +static gint hf_mac_header_generic_ext_subheader_fb_req_frame_offset = -1; + +/* DL Sleep Control Operations */ +static const value_string dl_sleep_control_ops[] = +{ + { 0, "De-activate Power Saving Class" }, + { 1, "Activate Power Saving Class" }, + { 0, NULL} +}; + +/* UL sub-header */ +static gint hf_mac_header_generic_ext_subheader_type_ul = -1; +static gint hf_mac_header_generic_ext_subheader_mimo_mode_fb_type = -1; +static gint hf_mac_header_generic_ext_subheader_mimo_fb_content = -1; +static gint hf_mac_header_generic_ext_subheader_ul_tx_pwr_rep = -1; +static gint hf_mac_header_generic_ext_subheader_mini_fb_type = -1; +static gint hf_mac_header_generic_ext_subheader_mini_fb_content = -1; +/* common fields */ +static gint hf_mac_header_generic_ext_subheader_pdu_sn_short = -1; +static gint hf_mac_header_generic_ext_subheader_pdu_sn_long = -1; + +/* SN Request subheader */ +#define SN_REQUEST_SUBHEADER_SN_REPORT_INDICATION_1_MASK 0x01 +#define SN_REQUEST_SUBHEADER_SN_REPORT_INDICATION_2_MASK 0x02 +#define SN_REQUEST_SUBHEADER_RESERVED_MASK 0xFC + +static gint hf_mac_header_generic_ext_subheader_sn_req_rep_ind_1 = -1; +static gint hf_mac_header_generic_ext_subheader_sn_req_rep_ind_2 = -1; +static gint hf_mac_header_generic_ext_subheader_sn_req_rsv = -1; +/* SN Report Indication message */ +static const value_string sn_rep_msg[] = +{ + { 0, "" }, + { 1, "request transmission" }, + { 0, NULL} +}; + +/* Mesh Subheader */ +static gint hf_mac_header_generic_mesh_subheader = -1; + +/* Fragmentation Subheader (table 8) */ +#define FRAGMENTATION_SUBHEADER_FC_MASK 0xC000 /*0x0003*/ +#define FRAGMENTATION_SUBHEADER_BSN_MASK 0x3FF8 /*0x1FFC*/ +#define FRAGMENTATION_SUBHEADER_RSV_EXT_MASK 0x0007 /*0xE000*/ +#define FRAGMENTATION_SUBHEADER_FSN_MASK 0x38 /*0x1C*/ +#define FRAGMENTATION_SUBHEADER_RSV_MASK 0x07 /*0xE0*/ +#define FRAGMENT_TYPE_MASK 0xC0 +#define SEQ_NUMBER_MASK 0x38 +#define SEQ_NUMBER_MASK_11 0x3FF8 + +#define NO_FRAG 0 +#define LAST_FRAG 1 +#define FIRST_FRAG 2 +#define MIDDLE_FRAG 3 + +static gint hf_mac_header_generic_frag_subhd_fc = -1; +static gint hf_mac_header_generic_frag_subhd_fc_ext = -1; +static gint hf_mac_header_generic_frag_subhd_bsn = -1; +static gint hf_mac_header_generic_frag_subhd_fsn = -1; +static gint hf_mac_header_generic_frag_subhd_fsn_ext = -1; +static gint hf_mac_header_generic_frag_subhd_rsv = -1; +static gint hf_mac_header_generic_frag_subhd_rsv_ext = -1; + +/* Fragment Types */ +static const value_string frag_types[] = +{ + { 0, "No fragmentation" }, + { 1, "Last fragment" }, + { 2, "First fragment" }, + { 3, "Continuing (middle) fragment" }, + { 0, NULL} +}; + +/* Packing Subheader (table 11) */ +#define PACKING_SUBHEADER_FC_MASK 0xC00000 +#define PACKING_SUBHEADER_BSN_MASK 0x3FF800 +#define PACKING_SUBHEADER_FSN_MASK 0x38 +#define PACKING_SUBHEADER_LENGTH_MASK 0x07FF +#define PACKING_SUBHEADER_LENGTH_EXT_MASK 0x0007FF + +#define FRAG_LENGTH_MASK 0x0007FF00 + +static gint hf_mac_header_generic_packing_subhd_fc = -1; +static gint hf_mac_header_generic_packing_subhd_fc_ext = -1; +static gint hf_mac_header_generic_packing_subhd_bsn = -1; +static gint hf_mac_header_generic_packing_subhd_fsn = -1; +static gint hf_mac_header_generic_packing_subhd_fsn_ext = -1; +static gint hf_mac_header_generic_packing_subhd_len = -1; +static gint hf_mac_header_generic_packing_subhd_len_ext = -1; + +/* Fast-feedback Allocation Subheader (table 13) */ +#define FAST_FEEDBACK_ALLOCATION_OFFSET_MASK 0xFC /*0x3F*/ +#define FAST_FEEDBACK_FEEDBACK_TYPE_MASK 0x03 /*0xC0*/ + +static gint hf_mac_header_generic_fast_fb_subhd_alloc_offset = -1; +static gint hf_mac_header_generic_fast_fb_subhd_fb_type = -1; + +/* Grant Management Subheader (table 9 & 10) */ +#define GRANT_MGMT_SUBHEADER_UGS_SI_MASK 0x8000 /*0x0001*/ +#define GRANT_MGMT_SUBHEADER_UGS_PM_MASK 0x4000 /*0x0002*/ +#define GRANT_MGMT_SUBHEADER_UGS_FLI_MASK 0x2000 /*0x0004*/ +#define GRANT_MGMT_SUBHEADER_UGS_FL_MASK 0x1E00 /*0x0078*/ +#define GRANT_MGMT_SUBHEADER_UGS_RSV_MASK 0x01FF /*0xFF80*/ +#define GRANT_MGMT_SUBHEADER_EXT_PBR_MASK 0xFFE0 /*0x07FF*/ +#define GRANT_MGMT_SUBHEADER_EXT_FLI_MASK 0x0010 /*0x0800*/ +#define GRANT_MGMT_SUBHEADER_EXT_FL_MASK 0x000F /*0xF000*/ + +typedef enum +{ + SCHEDULE_SERVICE_TYPE_RSVD, + SCHEDULE_SERVICE_TYPE_UNDEFINED, + SCHEDULE_SERVICE_TYPE_BE, + SCHEDULE_SERVICE_TYPE_NRTPS, + SCHEDULE_SERVICE_TYPE_RTPS, + SCHEDULE_SERVICE_TYPE_EXT_RTPS, + SCHEDULE_SERVICE_TYPE_UGS +} SCHEDULE_SERVICE_TYPE_e; + +static gint hf_mac_header_generic_grant_mgmt_ugs_tree = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_si = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_pm = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_fli = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_fl = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ugs_rsv = -1; +static gint hf_mac_header_generic_grant_mgmt_ext_rtps_tree = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ext_pbr = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ext_fli = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_ext_fl = -1; +static gint hf_mac_header_generic_grant_mgmt_ext_pbr_tree = -1; +static gint hf_mac_header_generic_grant_mgmt_subhd_pbr = -1; + +/* Slip Indicators */ +static const value_string si_msgs[] = +{ + { 0, "No action" }, + { 1, "A slip of UL grants relative to the UL queue depth" }, + { 0, NULL} +}; + +/* Poll-Me Messages */ +static const value_string pm_msgs[] = +{ + { 0, "No action" }, + { 1, "Request a bandwidth poll" }, + { 0, NULL} +}; + +/* Frame Latency Indications */ +static const value_string fli_msgs[] = +{ + { 0, "Frame latency field disabled" }, + { 1, "Frame latency field enabled" }, + { 0, NULL} +}; + +/* ARQ Feedback Payload */ + +/* ARQ Feedback IE bit masks (table 111) */ +#define ARQ_FB_IE_LAST_BIT_MASK 0x8000 /*0x0001*/ +#define ARQ_FB_IE_ACK_TYPE_MASK 0x6000 /*0x0006*/ +#define ARQ_FB_IE_BSN_MASK 0x1FFC /*0x3FF8*/ +#define ARQ_FB_IE_NUM_MAPS_MASK 0x0003 /*0xC000*/ +#define ARQ_FB_IE_SEQ_FORMAT_MASK 0x8000 /*0x0001*/ +#define ARQ_FB_IE_SEQ_ACK_MAP_MASK 0x7000 /*0x000E*/ +#define ARQ_FB_IE_SEQ1_LENGTH_MASK 0x0F00 /*0x00F0*/ +#define ARQ_FB_IE_SEQ2_LENGTH_MASK 0x00F0 /*0x0F00*/ +#define ARQ_FB_IE_SEQ3_LENGTH_MASK 0x000F /*0xF000*/ +#define ARQ_FB_IE_SEQ_ACK_MAP_2_MASK 0x6000 /*0x0006*/ +#define ARQ_FB_IE_SEQ1_LENGTH_6_MASK 0x1F80 /*0x01F8*/ +#define ARQ_FB_IE_SEQ2_LENGTH_6_MASK 0x007E /*0x7E00*/ +#define ARQ_FB_IE_RSV_MASK 0x0001 /*0x8000*/ + +static gint hf_mac_header_generic_arq_fb_ie_cid = -1; +static gint hf_mac_header_generic_arq_fb_ie_last = -1; +static gint hf_mac_header_generic_arq_fb_ie_ack_type = -1; +static gint hf_mac_header_generic_arq_fb_ie_bsn = -1; +static gint hf_mac_header_generic_arq_fb_ie_num_maps = -1; +static gint hf_ack_type_reserved = -1; +static gint hf_mac_header_generic_arq_fb_ie_sel_ack_map = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq_format = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq_ack_map = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq1_length = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq2_length = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq3_length = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq_ack_map_2 = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq1_length_6 = -1; +static gint hf_mac_header_generic_arq_fb_ie_seq2_length_6 = -1; +static gint hf_mac_header_generic_arq_fb_ie_rsv = -1; +static gint hf_mac_header_payload_fragment = -1; + +static expert_field ei_mac_crc_malformed = EI_INIT; +static expert_field ei_mac_crc_missing = EI_INIT; +static expert_field ei_mac_header_generic_crc = EI_INIT; + +/* Last IE Indicators */ +static const value_string last_ie_msgs[] = +{ + { 0, "No" }, + { 1, "Yes" }, + { 0, NULL} +}; + +/* Copied and renamed from proto.c because global value_strings don't work for plugins */ +static const value_string plugin_proto_checksum_vals[] = { + { PROTO_CHECKSUM_E_BAD, "Bad" }, + { PROTO_CHECKSUM_E_GOOD, "Good" }, + { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" }, + { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" }, + + { 0, NULL } +}; + +/* Register Wimax defrag table init routine. */ +static void wimax_defragment_init(void) +{ + gint i; + + /* Init fragmentation variables. */ + for (i = 0; i < MAX_CID; i++) + { + cid_adjust[i] = 1; /* Must not start with 0 */ + cid_vernier[i] = 0; + } + cid_adj_array_size = 0; + /* Initialize to make sure bs_address gets set in FCH decoder. */ + bs_address.len = 0; + + /* Initialize the Scheduling Service Type flag */ + seen_a_service_type = 0; + + max_logical_bands = 12; + + /* Initialize UL_MAP globals. */ + init_wimax_globals(); +} + +static void wimax_defragment_cleanup(void) +{ + g_free(cid_adj_array); + cid_adj_array = NULL; + g_free(frag_num_array); + frag_num_array = NULL; +} + +static guint decode_packing_subheader(tvbuff_t *payload_tvb, packet_info *pinfo, proto_tree *tree, guint payload_length _U_, guint payload_offset, proto_item *parent_item) +{ + proto_item *generic_item = NULL; + proto_tree *generic_tree = NULL; + guint starting_offset = payload_offset; + + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Packing subhdr"); + /* add the Packing subheader info */ + proto_item_append_text(parent_item, ", Packing Subheader"); + /* display Packing subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, payload_tvb, payload_offset, ((arq_enabled|extended_type)?3:2), "Packing subheader (%u bytes)", ((arq_enabled|extended_type)?3:2)); + /* add Packing subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_pkt_subheader_decoder); + /* decode and display the Packing subheader */ + /* Get the fragment type */ + frag_type = (tvb_get_guint8(payload_tvb, payload_offset) & FRAGMENT_TYPE_MASK) >> 6; + /* if ARQ Feedback payload is present */ + if (arq_fb_payload) + { /* get the frag length */ + frag_len = ((tvb_get_ntohl(payload_tvb, payload_offset) & FRAG_LENGTH_MASK) >> 8); + /* get the sequence number */ + seq_number = (tvb_get_ntohs(payload_tvb, payload_offset) & SEQ_NUMBER_MASK_11) >> 3; + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fc_ext, payload_tvb, payload_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_bsn, payload_tvb, payload_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_len_ext, payload_tvb, payload_offset, 3, ENC_BIG_ENDIAN); + /* update the length and offset */ + payload_offset += 3; + frag_len -= 3; + } + else + { + if (extended_type) + { /* get the frag length */ + frag_len = ((tvb_get_ntohl(payload_tvb, payload_offset) & FRAG_LENGTH_MASK) >> 8); + /* get the sequence number */ + seq_number = (tvb_get_ntohs(payload_tvb, payload_offset) & SEQ_NUMBER_MASK_11) >> 3; + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fc_ext, payload_tvb, payload_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fsn_ext, payload_tvb, payload_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_len_ext, payload_tvb, payload_offset, 3, ENC_BIG_ENDIAN); + /* update the length and offset */ + payload_offset += 3; + frag_len -= 3; + } + else + { /* get the frag length */ + frag_len = (tvb_get_ntohs(payload_tvb, payload_offset) & PACKING_SUBHEADER_LENGTH_MASK); + /* get the sequence number */ + seq_number = (tvb_get_guint8(payload_tvb, payload_offset) & SEQ_NUMBER_MASK) >> 3; + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fc, payload_tvb, payload_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_fsn, payload_tvb, payload_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_packing_subhd_len, payload_tvb, payload_offset, 2, ENC_BIG_ENDIAN); + /* update the length and offset */ + payload_offset += 2; + frag_len -= 2; + } + } + /* Prevent a crash! */ + if ((gint)frag_len < 0) + frag_len = 0; + /* Return the number of bytes decoded. */ + return payload_offset - starting_offset; +} + + +static int dissect_mac_header_generic_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint payload_offset; + guint payload_length = 0; + + static guint8 frag_number[MAX_CID]; + static guint cid_list[MAX_CID]; + static guint cid_base; + static const char reassem_str[] = "Reassembled Data transport PDU (%u bytes)"; + static const char data_str[] = "Data transport PDU (%u bytes)"; + const char *str_ptr; + gint length, i, cid_index; + guint tvb_len, ret_length, ubyte, new_tvb_len; + guint new_payload_len = 0; + guint /*mac_ht,*/ mac_ec, mac_esf, mac_ci, /*mac_eks,*/ mac_len, mac_cid, cid; + guint ffb_grant_mgmt_subheader, packing_subheader, fragment_subheader; + guint mesh_subheader; + guint packing_length; + guint32 mac_crc, calculated_crc; + proto_item *parent_item = NULL; + proto_item *generic_item = NULL; + proto_tree *generic_tree = NULL; + proto_item *child_item = NULL; + proto_tree *child_tree = NULL; + tvbuff_t *payload_tvb; + tvbuff_t *data_pdu_tvb; + fragment_head *payload_frag; + gboolean first_arq_fb_payload = TRUE; + + proto_mac_header_generic_decoder = proto_wimax; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "GMH"); +#endif + + /* Get the frame length */ + tvb_len = tvb_reported_length(tvb); + if (tvb_len < WIMAX_MAC_HEADER_SIZE) + { + /* display the error message */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, tvb_len, "Error: the size of Generic MAC Header tvb is too small! (%u bytes)", tvb_len); + /* add subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_header_generic_decoder); + /* display the Generic MAC Header in Hex */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, tvb_len, ENC_NA); + return tvb_captured_length(tvb); + } + /* get the parent */ + parent_item = proto_tree_get_parent(tree); + /* add the MAC header info */ + proto_item_append_text(parent_item, " - Generic MAC Header"); + /* display MAC header message */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, WIMAX_MAC_HEADER_SIZE, "Generic MAC Header (%u bytes)", WIMAX_MAC_HEADER_SIZE); + /* add MAC header subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_header_generic_decoder); + /* Decode and display the MAC header */ + /* Get the first byte */ + ubyte = tvb_get_guint8(tvb, offset); + /* get the Header Type (HT) */ + /*mac_ht = ((ubyte & WIMAX_MAC_HEADER_GENERIC_HT_MASK)?1:0); XX: not used ?? */ + /* get the Encryption Control (EC) */ + mac_ec = ((ubyte & WIMAX_MAC_HEADER_GENERIC_EC_MASK)?1:0); + /* get the sub types */ + ffb_grant_mgmt_subheader = ((ubyte & GENERIC_SUB_TYPE_0)?1:0); + packing_subheader = ((ubyte & GENERIC_SUB_TYPE_1)?1:0); + fragment_subheader = ((ubyte & GENERIC_SUB_TYPE_2)?1:0); + extended_type = ((ubyte & GENERIC_SUB_TYPE_3)?1:0); + arq_fb_payload = ((ubyte & GENERIC_SUB_TYPE_4)?1:0); + mesh_subheader = ((ubyte & GENERIC_SUB_TYPE_5)?1:0); + /* Get the 2nd byte */ + ubyte = tvb_get_guint8(tvb, (offset+1)); + /* get the Extended subheader field (ESF) */ + mac_esf = ((ubyte & WIMAX_MAC_HEADER_GENERIC_ESF_MASK)?1:0); + /* get the CRC indicator (CI) */ + mac_ci = ((ubyte & WIMAX_MAC_HEADER_GENERIC_CI_MASK)?1:0); + /* get the Encryption key sequence (EKS) */ + /*mac_eks = ((ubyte & WIMAX_MAC_HEADER_GENERIC_EKS_MASK)>>4); XX: not used ?? */ + /* get the MAC length; this is used even if tree is null */ + mac_len = (tvb_get_ntohs(tvb, (offset+1)) & WIMAX_MAC_HEADER_GENERIC_LEN); + /* get the CID */ + mac_cid = tvb_get_ntohs(tvb, (offset+3)); + /* display the Header Type (HT) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_ht, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the Encryption Control (EC) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_ec, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the sub-types (Type) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_5, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_4, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_3, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_2, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_1, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_type_0, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the Extended sub-header Field (ESF) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_esf, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the CRC Indicator (CI) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_ci, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the Encryption Key Sequence (EKS) */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_eks, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the reserved field */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_rsv, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the length */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_len, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the CID */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_cid, tvb, (offset+3), 2, ENC_BIG_ENDIAN); + /* Decode and display the HCS */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_hcs, tvb, (offset+5), 1, ENC_BIG_ENDIAN); + /* get the frame length without MAC header */ + length = mac_len - WIMAX_MAC_HEADER_SIZE; +#ifdef DEBUG + proto_item_append_text(parent_item, "tvb length=%u, mac length=%u, frame length=%u,", tvb_len, mac_len, length); +#endif + /* set the offset for the frame */ + offset += WIMAX_MAC_HEADER_SIZE; + /* the processing of the subheaders is order sensitive */ + /* do not change the order */ + + if (mac_ec) + { + if (mac_ci) + { + if (length >= (gint)sizeof(mac_crc)) + { + length -= (int)sizeof(mac_crc); + } + } + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Encrypted PDU (%u bytes)", length); + /* add payload subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_data_pdu_decoder); + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, length, ENC_NA); + goto check_crc; + } + + /* if Extended subheader is present */ + if (mac_esf) + { /* add the Extended subheader info */ + proto_item_append_text(parent_item, ", Extended Subheader(s)"); + ret_length = extended_subheader_decoder(tvb_new_subset_length(tvb, offset, length), pinfo, tree); + /* update the length and offset */ + length -= ret_length; + offset += ret_length; + } + /* if Mesh subheader is present */ + if (mesh_subheader) + { /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Mesh subhdr"); + /* add the Mesh subheader info */ + proto_item_append_text(parent_item, ", Mesh Subheader"); + /* display Mesh subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Mesh subheader (2 bytes)"); + /* add Mesh subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_mesh_subheader_decoder); + /* decode and display the Mesh subheader */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_mesh_subheader, tvb, offset, 2, ENC_BIG_ENDIAN); + /* update the length and offset */ + length -= 2; + offset += 2; + } + /* if Fast-feedback allocation (DL) subheader or Grant management (UL) subheader is present */ + if (ffb_grant_mgmt_subheader) + { /* check if it is downlink packet */ + if (is_down_link(pinfo)) + { /* Fast-feedback allocation (DL) subheader is present */ + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Fast-fb subhdr"); + /* add the Fast-feedback subheader info */ + proto_item_append_text(parent_item, ", Fast-feedback Subheader"); + /* display Fast-feedback allocation subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Fast-feedback allocation (DL) subheader (%u bytes)", length); + /* add Fast-feedback allocation subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_fast_fb_subheader_decoder); + proto_tree_add_item(generic_tree, hf_mac_header_generic_fast_fb_subhd_alloc_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_fast_fb_subhd_fb_type, tvb, offset, 1, ENC_BIG_ENDIAN); + /* update the length and offset */ + length -= 1; + offset += 1; + } + else /* Grant management (UL) subheader is present */ + { /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Grant mgmt subhdr"); + /* add the Grant management subheader info */ + proto_item_append_text(parent_item, ", Grant Management Subheader"); + /* display Grant management subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, 2, "Grant management (UL) subheader (2 bytes)"); + /* add Grant management subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_grant_mgmt_subheader_decoder); + scheduling_service_type = get_service_type(); + switch (scheduling_service_type) + { + case SCHEDULE_SERVICE_TYPE_UGS: + proto_item_append_text(generic_item, ": It looks like UGS is the correct Scheduling Service Type"); + break; + case SCHEDULE_SERVICE_TYPE_EXT_RTPS: + proto_item_append_text(generic_item, ": It looks like Extended rtPS is the correct Scheduling Service Type"); + break; + case -1: + proto_item_append_text(generic_item, ": Cannot determine the correct Scheduling Service Type"); + break; + default: + proto_item_append_text(generic_item, ": It looks like Piggyback Request is the correct Scheduling Service Type"); + break; + } + /* Create tree for Scheduling Service Type (UGS) */ + child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ugs_tree, tvb, offset, 2, ENC_BIG_ENDIAN); + child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_si, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_pm, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_fli, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_fl, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + + /* Create tree for Scheduling Service Type (Extended RTPS) */ + child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ext_rtps_tree, tvb, offset, 2, ENC_BIG_ENDIAN); + child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_pbr, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_fli, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_fl, tvb, offset, 2, ENC_BIG_ENDIAN); + + /* Create tree for Scheduling Service Type (Piggyback Request) */ + child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ext_pbr_tree, tvb, offset, 2, ENC_BIG_ENDIAN); + child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder); + proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_pbr, tvb, offset, 2, ENC_BIG_ENDIAN); + + /* update the length and offset */ + length -= 2; + offset += 2; + } + } + /* if Fragmentation subheader is present */ + if (fragment_subheader) + { /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Frag subhdr"); + /* add the Fragmentation subheader info */ + proto_item_append_text(parent_item, ", Frag Subheader"); + /* display Fragmentation subheader type */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, ((arq_enabled|extended_type)?2:1), "Fragmentation subheader (%u bytes)", ((arq_enabled|extended_type)?2:1)); + /* add Fragmentation subheader subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_frag_subheader_decoder); + /* Get the fragment type */ + frag_type = (tvb_get_guint8(tvb, offset) & FRAGMENT_TYPE_MASK) >> 6; + if (arq_fb_payload) + { /* get the sequence number */ + seq_number = (tvb_get_ntohs(tvb, offset) & SEQ_NUMBER_MASK_11) >> 3; + /* decode and display the header */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc_ext, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_bsn, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv_ext, tvb, offset, 2, ENC_BIG_ENDIAN); + /* update the length and offset */ + length -= 2; + offset += 2; + } + else + { + if (extended_type) + { /* get the sequence number */ + seq_number = (tvb_get_ntohs(tvb, offset) & SEQ_NUMBER_MASK_11) >> 3; + /* decode and display the header */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc_ext, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fsn_ext, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv_ext, tvb, offset, 2, ENC_BIG_ENDIAN); + /* update the length and offset */ + length -= 2; + offset += 2; + } + else + { /* get the sequence number */ + seq_number = (tvb_get_guint8(tvb, offset) & SEQ_NUMBER_MASK) >> 3; + /* decode and display the header */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fsn, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv, tvb, offset, 1, ENC_BIG_ENDIAN); + /* update the length and offset */ + length -= 1; + offset += 1; + } + } + frag_len = length; + } + else /* ??? default fragment type: no fragment */ + { + frag_type = NO_FRAG; + } + /* Decode the MAC payload if there is any */ + if (mac_ci) + { + if (length < (gint)sizeof(mac_crc)) + { /* display error message */ + proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Error - the frame is too short (%u bytes)", length); + return tvb_captured_length(tvb); + } + length -= (int)sizeof(mac_crc); + } + while (length > 0) + { + frag_len = length; /* Can be changed by Packing subhdr */ + if (packing_subheader) + { + packing_length = decode_packing_subheader(tvb, pinfo, tree, length, offset, parent_item); + length -= packing_length; + offset += packing_length; + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, frag_len, "Data transport PDU (%u bytes)", frag_len); + /* add payload subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_data_pdu_decoder); + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, frag_len, ENC_NA); + } + /* defragment first if it is fragmented */ + if (frag_type == NO_FRAG) + { /* not fragmented payload */ + payload_tvb = tvb_new_subset_length(tvb, offset, frag_len); + payload_length = frag_len; + new_payload_len = frag_len; + } + else /* fragmented payload */ + { /* add the fragment */ + /* Make sure cid will not match a previous packet with different data */ + for (i = 0; i < MAX_CID; i++) + { + if (cid_list[i] == mac_cid) + { + cid_base = i * (0xFFFFFFFF / MAX_CID); + break; + } + if (cid_list[i] == 0) + { + cid_list[i] = mac_cid; + cid_base = i * (0xFFFFFFFF / MAX_CID); + break; + } + } + cid_index = i; + while (pinfo->num > cid_adj_array_size) + { + cid_adj_array_size += 1024; + cid_adj_array = (guint *)g_realloc(cid_adj_array, (int)sizeof(guint) * cid_adj_array_size); + frag_num_array = (guint8 *)g_realloc(frag_num_array, (int)sizeof(guint8) * cid_adj_array_size); + /* Clear the added memory */ + memset(&cid_adj_array[cid_adj_array_size - 1024], 0, (int)sizeof(guint) * 1024); + } + if (first_gmh) + { + /* New cid_adjust for each packet with fragment(s) */ + cid_adjust[cid_index] += cid_vernier[cid_index]; + /* cid_vernier must always be 0 at start of packet. */ + cid_vernier[cid_index] = 0; + } + /* Create artificial sequence numbers. */ + frag_number[cid_index]++; + if (frag_type == FIRST_FRAG) + { + frag_number[cid_index] = 0; + } + if (cid_adj_array[pinfo->num]) + { + /* We apparently just clicked on the packet again. */ + cid_adjust[cid_index] = cid_adj_array[pinfo->num]; + /* Set the frag_number at start of packet. */ + if (first_gmh) + { + frag_number[cid_index] = frag_num_array[pinfo->num]; + } + } else { + /* Save for next time we click on this packet. */ + cid_adj_array[pinfo->num] = cid_adjust[cid_index]; + if (first_gmh) + { + frag_num_array[pinfo->num] = frag_number[cid_index]; + } + } + /* Reset in case we stay in this while() loop to finish the packet. */ + first_gmh = FALSE; + cid = cid_base + cid_adjust[cid_index] + cid_vernier[cid_index]; + /* Save address pointers. */ + copy_address_shallow(&save_src, &pinfo->src); + copy_address_shallow(&save_dst, &pinfo->dst); + /* Use dl_src and dl_dst in defragmentation. */ + copy_address_shallow(&pinfo->src, &pinfo->dl_src); + copy_address_shallow(&pinfo->dst, &pinfo->dl_dst); + payload_frag = fragment_add_seq(&payload_reassembly_table, tvb, offset, pinfo, cid, NULL, frag_number[cid_index], frag_len, ((frag_type==LAST_FRAG)?0:1), 0); + /* Restore address pointers. */ + copy_address_shallow(&pinfo->src, &save_src); + copy_address_shallow(&pinfo->dst, &save_dst); + if (frag_type == LAST_FRAG) + { + /* Make sure fragment_add_seq() sees next one as a new frame. */ + cid_vernier[cid_index]++; + } + /* Don't show reassembled packet until last fragment. */ + proto_tree_add_bytes_format(tree, hf_mac_header_payload_fragment, tvb, offset, frag_len, NULL, "Payload Fragment (%d bytes)", frag_len); + + if (payload_frag && frag_type == LAST_FRAG) + { /* defragmented completely */ + payload_length = payload_frag->len; + /* create the new tvb for defragmented frame */ + payload_tvb = tvb_new_chain(tvb, payload_frag->tvb_data); + /* add the defragmented data to the data source list */ + add_new_data_source(pinfo, payload_tvb, "Reassembled WiMax MAC payload"); + /* save the tvb langth */ + new_payload_len = payload_length; + } + else /* error or defragment is not complete */ + { + payload_tvb = NULL; +#ifdef DEBUG /* for debug only */ +/* if (frag_type == LAST_FRAG)*/ + { /* error */ + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Dropped the incomplete frame"); + } +#endif +#if 0 + if (frag_type == FIRST_FRAG) + { /* Set up to decode the first fragment (even though next fragment not read yet) */ + payload_tvb = tvb_new_subset_length(tvb, offset, length); + payload_length = length; + frag_len = length; + } +#endif + } + } + /* process the defragmented payload */ + if (payload_tvb) + { /* reset the payload_offset */ + payload_offset = 0; + /* process the payload */ + if (payload_length > 0) + { + if (!new_payload_len) + continue; + /* if ARQ Feedback payload is present, it should be the first SDU */ + if (first_arq_fb_payload && arq_fb_payload) + { /* decode and display the ARQ feedback payload */ + first_arq_fb_payload = FALSE; +#ifndef DEBUG + arq_feedback_payload_decoder(tvb_new_subset_length(payload_tvb, payload_offset, new_payload_len), pinfo, generic_tree, parent_item); +#else + ret_length = arq_feedback_payload_decoder(tvb_new_subset_length(payload_tvb, payload_offset, new_payload_len), pinfo, generic_tree, parent_item); + if (ret_length != new_payload_len) + { /* error */ + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "incorrect ARQ fb payload size"); + } +#endif + } + else /* decode SDUs */ + { /* check the payload type */ + if (mac_cid == cid_padding) + { /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Padding CID"); + /* get the parent */ + generic_item = proto_tree_get_parent(tree); + /* add the MAC header info */ + proto_item_append_text(generic_item, ", Padding CID"); + /* display padding CID */ + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, payload_tvb, payload_offset, new_payload_len, "Padding CID (%u bytes)", new_payload_len); + /* add payload subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_header_generic_decoder); + /* display the Padding CID payload in Hex */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, payload_tvb, payload_offset, new_payload_len, ENC_NA); + } + else if ((mac_cid <= (2 * global_cid_max_basic)) || (mac_cid == cid_aas_ranging) + || (mac_cid >= cid_normal_multicast)) + { /* MAC management message */ + call_dissector(mac_mgmt_msg_decoder_handle, tvb_new_subset_length(payload_tvb, payload_offset, new_payload_len), pinfo, tree); + } + else /* data transport PDU */ + { /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Data"); + /* add the MAC payload info */ + proto_item_append_text(parent_item, ", Data"); + /* display payload info */ + if ((new_payload_len + payload_offset) > payload_length) + { + new_tvb_len = new_payload_len - payload_offset; + } + else + { + new_tvb_len = new_payload_len; + } + if (frag_type == LAST_FRAG || frag_type == NO_FRAG) + { + if (frag_type == NO_FRAG) + { + str_ptr = data_str; + new_payload_len = frag_len; + } + else + { + str_ptr = reassem_str; + } + data_pdu_tvb = tvb_new_subset_length(payload_tvb, payload_offset, new_tvb_len); + generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, data_pdu_tvb, payload_offset, new_payload_len, str_ptr, new_payload_len); + /* add payload subtree */ + generic_tree = proto_item_add_subtree(generic_item, ett_mac_data_pdu_decoder); + /* check the data type */ + if (tvb_get_guint8(payload_tvb, payload_offset) == IP_HEADER_BYTE) + { + if (mac_ip_handle) + call_dissector(mac_ip_handle, tvb_new_subset_length(payload_tvb, payload_offset, new_tvb_len), pinfo, generic_tree); + else /* display the Generic MAC Header in Hex */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, payload_tvb, payload_offset, new_tvb_len, ENC_NA); + } + else /* display the Generic MAC Header in Hex */ + proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, payload_tvb, payload_offset, new_tvb_len, ENC_NA); + } + } + } + payload_length -= new_payload_len; + } /* end of while loop */ + } /* end of payload processing */ + length -= frag_len; + offset += frag_len; + } /* end of payload decoding */ + +check_crc: + /* Decode and display the CRC if it is present */ + if (mac_ci) + { + /* add the CRC info */ + proto_item_append_text(parent_item, ", CRC"); + /* check the length */ + if (MIN(tvb_len, tvb_reported_length(tvb)) >= mac_len) + { + /* calculate the CRC */ + calculated_crc = wimax_mac_calc_crc32(tvb_get_ptr(tvb, 0, mac_len - (int)sizeof(mac_crc)), mac_len - (int)sizeof(mac_crc)); + /* display the CRC */ + proto_tree_add_checksum(tree, tvb, mac_len - (int)sizeof(mac_crc), hf_mac_header_generic_crc, hf_mac_header_generic_crc_status, &ei_mac_header_generic_crc, + pinfo, calculated_crc, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + } + else + { /* display error message */ + expert_add_info_format(pinfo, tree, &ei_mac_crc_malformed, "CRC missing - the frame is too short (%u bytes)", tvb_len); + } + } + else /* CRC is not included */ + { /* add the CRC info */ + proto_item_append_text(parent_item, ", No CRC"); + /* display message */ + expert_add_info(pinfo, tree, &ei_mac_crc_missing); + } + return tvb_captured_length(tvb); +} + +static gint extended_subheader_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + gint offset = 0; + gint length, ext_length, ubyte, i; + proto_item *ti = NULL; + proto_tree *sub_tree = NULL; + proto_tree *ti_tree = NULL; + + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Ext subhdrs"); + + /* Get the tvb reported length */ + length = tvb_reported_length(tvb); + if (!length) + { /* display the error message */ + proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Error: extended subheader tvb is empty ! (%u bytes)", length); + return length; + } + + /* Get the length of the extended subheader group */ + ext_length = tvb_get_guint8(tvb, offset); + /* display subheader type */ + ti = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Extended subheader group (%u bytes)", ext_length); + /* add extended subheader subtree */ + sub_tree = proto_item_add_subtree(ti, ett_mac_ext_subheader_decoder); + /* decode and display the extended subheaders */ + for (i=1; icinfo, COL_INFO, NULL, "ARQ feedback payld"); + + /* add the MAC header info */ + proto_item_append_text(parent_item, ", ARQ feedback payload"); + + /* reset the offset */ + offset = 0; + + /* Get the tvb reported length */ + length = tvb_reported_length(tvb); + if (!length) + { /* display the error message */ + proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Error: ARQ feedback payload tvb is empty ! (%u bytes)", length); + return length; + } + + /* display subheader type */ + ti = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "ARQ feedback payload "); + /* add extended subheader subtree */ + sub_tree = proto_item_add_subtree(ti, ett_mac_arq_fb_payload_decoder); + /* decode and display the ARQ Feedback IEs */ + while (!last_ie) + { /* decode and display CID */ + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_cid, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next 16-bit word */ + offset += 2; + /* Get the 2nd 16-bit */ + word2 = tvb_get_ntohs(tvb, offset); + /* get the last bit */ + last_ie = (word2 & ARQ_FB_IE_LAST_BIT_MASK); + /* get the ACK type */ + ack_type = ((word2 & ARQ_FB_IE_ACK_TYPE_MASK) >> 13); + /* get the number of ACK maps */ + num_maps = (word2 & ARQ_FB_IE_NUM_MAPS_MASK) + 1; + /* decode and display the 2nd word */ + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_last, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_ack_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_bsn, tvb, offset, 2, ENC_BIG_ENDIAN); + /* decode and display the 3rd word */ + if (ack_type != 1) + { + sub_ti = proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_num_maps, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next 16-bit word */ + offset += 2; + proto_item_append_text(sub_ti, " (%d map(s))", num_maps); + for (i = 0; i < num_maps; i++) + { + if (ack_type != 3) + { + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_sel_ack_map, tvb, offset, 2, ENC_BIG_ENDIAN); + } + else + { /* Get the next 16-bit */ + word3 = tvb_get_ntohs(tvb, offset); + /* get the sequence format */ + seq_format = (word3 & ARQ_FB_IE_SEQ_FORMAT_MASK); + /* decode and display the sequence format */ + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq_format, tvb, offset, 2, ENC_BIG_ENDIAN); + if (!seq_format) + { + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq_ack_map_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq1_length_6, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq2_length_6, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq_ack_map, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq1_length, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq2_length, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_mac_header_generic_arq_fb_ie_seq3_length, tvb, offset, 2, ENC_BIG_ENDIAN); + } + } + /* move to next 16-bit word */ + offset += 2; + } + } + else + { + /* Number of ACK Maps bits are reserved when ACK TYPE == 1 */ + proto_tree_add_item(sub_tree, hf_ack_type_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next 16-bit word */ + offset += 2; + } + } + /* append text */ + proto_item_append_text(ti,"(%u bytes)", offset); + /* return the offset */ + return offset; +} + +/* Register Wimax Generic Mac Header Protocol and Dissector */ +void wimax_proto_register_mac_header_generic(void) +{ + /* Generic MAC header display */ + static hf_register_info hf[] = + { + { + &hf_mac_header_generic_value_bytes, + { + "Values", "wmx.genericValueBytes", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ht, + { + "MAC Header Type", "wmx.genericHt", + FT_UINT24, BASE_HEX, VALS(ht_msgs), WIMAX_MAC_HEADER_GENERIC_HT, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ec, + { + "MAC Encryption Control", "wmx.genericEc", + FT_UINT24, BASE_HEX, VALS(ec_msgs), WIMAX_MAC_HEADER_GENERIC_EC, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_type_0, + { + "MAC Sub-type Bit 0", "wmx.genericType0", + FT_UINT24, BASE_HEX, VALS(type_msg0), WIMAX_MAC_HEADER_GENERIC_TYPE_0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_type_1, + { + "MAC Sub-type Bit 1", "wmx.genericType1", + FT_UINT24, BASE_HEX, VALS(type_msg1), WIMAX_MAC_HEADER_GENERIC_TYPE_1, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_type_2, + { + "MAC Sub-type Bit 2", "wmx.genericType2", + FT_UINT24, BASE_HEX, VALS(type_msg2), WIMAX_MAC_HEADER_GENERIC_TYPE_2, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_type_3, + { + "MAC Sub-type Bit 3", "wmx.genericType3", + FT_UINT24, BASE_HEX, VALS(type_msg3), WIMAX_MAC_HEADER_GENERIC_TYPE_3, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_type_4, + { + "MAC Sub-type Bit 4", "wmx.genericType4", + FT_UINT24, BASE_HEX, VALS(type_msg4), WIMAX_MAC_HEADER_GENERIC_TYPE_4, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_type_5, + { + "MAC Sub-type Bit 5", "wmx.genericType5", + FT_UINT24, BASE_HEX, VALS(type_msg5), WIMAX_MAC_HEADER_GENERIC_TYPE_5, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_esf, + { + "Extended Sub-header Field", "wmx.genericEsf", + FT_UINT24, BASE_HEX, VALS(esf_msgs), WIMAX_MAC_HEADER_GENERIC_ESF, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ci, + { + "CRC Indicator", "wmx.genericCi", + FT_UINT24, BASE_HEX, VALS(ci_msgs), WIMAX_MAC_HEADER_GENERIC_CI, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_eks, + { + "Encryption Key Sequence", "wmx.genericEks", + FT_UINT24, BASE_HEX, NULL, WIMAX_MAC_HEADER_GENERIC_EKS, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_rsv, + { + "Reserved", "wmx.genericRsv", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_GENERIC_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_len, + { + "Length", "wmx.genericLen", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_GENERIC_LEN, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_cid, + { + "Connection ID", "wmx.genericCid", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_hcs, + { + "Header Check Sequence", "wmx.genericHcs", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_crc, + { + "CRC", "wmx.genericCrc", + FT_UINT32, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_crc_status, + { + "CRC Status", "wmx.genericCrc.status", + FT_UINT8, BASE_NONE, VALS(plugin_proto_checksum_vals), 0x0, + NULL, HFILL + } + }, + + + }; + + /* Extended Subheader display */ + static hf_register_info hf_ext[] = + { + { + &hf_mac_header_generic_ext_subheader_rsv, + { + "Reserved", "wmx.genericExtSubhd.Rsv", + FT_UINT8, BASE_DEC, NULL, EXTENDED_SUB_HEADER_RSV_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_type_dl, + { + "DL Extended Subheader Type", "wmx.genericExtSubhd.Dl", + FT_UINT8, BASE_DEC, VALS(dl_ext_sub_header_type), EXTENDED_SUB_HEADER_TYPE_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_type_ul, + { + "UL Extended Subheader Type", "wmx.genericExtSubhd.Ul", + FT_UINT8, BASE_DEC, VALS(ul_ext_sub_header_type), EXTENDED_SUB_HEADER_TYPE_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_sdu_sn, + { + "SDU Sequence Number", "wmx.genericExtSubhd.SduSn", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_pscid, + { + "Power Saving Class ID", "wmx.genericExtSubhd.DlSleepCtrlPSCID", + FT_UINT24, BASE_DEC, NULL, DL_SLEEP_CONTROL_POWER_SAVING_CLASS_ID_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_op, + { + "Operation", "wmx.genericExtSubhd.DlSleepCtrlOP", + FT_UINT24, BASE_HEX, VALS(dl_sleep_control_ops), DL_SLEEP_CONTROL_OPERATION_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_fswe, + { + "Final Sleep Window Exponent", "wmx.genericExtSubhd.DlSleepCtrlFSWE", + FT_UINT24, BASE_DEC, NULL, DL_SLEEP_CONTROL_FINAL_SLEEP_WINDOW_EXPONENT_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_fswb, + { + "Final Sleep Window Base", "wmx.genericExtSubhd.DlSleepCtrlFSWB", + FT_UINT24, BASE_DEC, NULL, DL_SLEEP_CONTROL_FINAL_SLEEP_WINDOW_BASE_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_dl_sleep_control_rsv, + { + "Reserved", "wmx.genericExtSubhd.DlSleepCtrlRsv", + FT_UINT24, BASE_DEC, NULL, DL_SLEEP_CONTROL_RESERVED_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_uiuc, + { + "UIUC", "wmx.genericExtSubhd.FbReqUIUC", + FT_UINT24, BASE_HEX, VALS(uiuc_values), FEEDBACK_REQUEST_UIUC_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_fb_type, + { + "Feedback Type", "wmx.genericExtSubhd.FbReqFbType", + FT_UINT24, BASE_HEX, VALS(fb_types), FEEDBACK_REQUEST_FEEDBACK_TYPE_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_ofdma_symbol_offset, + { + "OFDMA Symbol Offset", "wmx.genericExtSubhd.FbReqOfdmaSymbolOffset", + FT_UINT24, BASE_HEX, NULL, FEEDBACK_REQUEST_OFDMA_SYMBOL_OFFSET_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_subchannel_offset, + { + "Subchannel Offset", "wmx.genericExtSubhd.FbReqSubchannelOffset", + FT_UINT24, BASE_HEX, NULL, FEEDBACK_REQUEST_SUBCHANNEL_OFFSET_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_slots, + { + "Number of Slots", "wmx.genericExtSubhd.FbReqSlots", + FT_UINT24, BASE_HEX, NULL, FEEDBACK_REQUEST_NUMBER_OF_SLOTS_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_fb_req_frame_offset, + { + "Frame Offset", "wmx.genericExtSubhd.FbReqFrameOffset", + FT_UINT24, BASE_HEX, NULL, FEEDBACK_REQUEST_FRAME_OFFSET_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_sn_req_rep_ind_1, + { + "First SN Report Indication", "wmx.genericExtSubhd.SnReqRepInd1", + FT_UINT8, BASE_DEC, VALS(sn_rep_msg), SN_REQUEST_SUBHEADER_SN_REPORT_INDICATION_1_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_sn_req_rep_ind_2, + { + "Second SN Report Indication", "wmx.genericExtSubhd.SnReqRepInd2", + FT_UINT8, BASE_DEC, VALS(sn_rep_msg), SN_REQUEST_SUBHEADER_SN_REPORT_INDICATION_2_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_sn_req_rsv, + { + "Reserved", "wmx.genericExtSubhd.SnReqRsv", + FT_UINT8, BASE_DEC, NULL, SN_REQUEST_SUBHEADER_RESERVED_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_mimo_mode_fb_type, + { + "Feedback Type", "wmx.genericExtSubhd.MimoFbType", + FT_UINT8, BASE_DEC, VALS(mimo_fb_types), MIMO_FEEDBACK_TYPE_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_mimo_fb_content, + { + "Feedback Content", "wmx.genericExtSubhd.MimoFbContent", + FT_UINT8, BASE_DEC, NULL, MIMO_FEEDBACK_CONTENT_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_ul_tx_pwr_rep, + { + "UL TX Power", "wmx.genericExtSubhd.UlTxPwr", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_mini_fb_type, + { + "Feedback Type", "wmx.genericExtSubhd.MiniFbType", + FT_UINT16, BASE_DEC, VALS(fb_types), MINI_FEEDBACK_TYPE_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_mini_fb_content, + { + "Feedback Content", "wmx.genericExtSubhd.MiniFbContent", + FT_UINT16, BASE_DEC, NULL, MINI_FEEDBACK_CONTENT_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_pdu_sn_short, + { + "PDU Sequence Number", "wmx.genericExtSubhd.PduSnShort", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_ext_subheader_pdu_sn_long, + { + "PDU Sequence Number", "wmx.genericExtSubhd.PduSnLong", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + } + }; + + /* Mesh Subheader display */ + static hf_register_info hf_mesh[] = + { + { + &hf_mac_header_generic_mesh_subheader, + { + "Xmt Node Id", "wmx.genericMeshSubhd", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + } + }; + + /* Fragmentation Subheader display */ + static hf_register_info hf_frag[] = + { + { + &hf_mac_header_generic_frag_subhd_fc, + { + "Fragment Type", "wmx.genericFragSubhd.Fc", + FT_UINT8, BASE_DEC, VALS(frag_types), FRAGMENTATION_SUBHEADER_FC_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_fc_ext, + { + "Fragment Type", "wmx.genericFragSubhd.FcExt", + FT_UINT16, BASE_DEC, VALS(frag_types), FRAGMENTATION_SUBHEADER_FC_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_bsn, + { + "Block Sequence Number (BSN)", "wmx.genericFragSubhd.Bsn", + FT_UINT16, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_BSN_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_fsn, + { + "Fragment Sequence Number (FSN)", "wmx.genericFragSubhd.Fsn", + FT_UINT8, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_FSN_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_fsn_ext, + { + "Fragment Sequence Number (FSN)", "wmx.genericFragSubhd.FsnExt", + FT_UINT16, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_BSN_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_rsv, + { + "Reserved", "wmx.genericFragSubhd.Rsv", + FT_UINT8, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_RSV_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_frag_subhd_rsv_ext, + { + "Reserved", "wmx.genericFragSubhd.RsvExt", + FT_UINT16, BASE_DEC, NULL, FRAGMENTATION_SUBHEADER_RSV_EXT_MASK, + NULL, HFILL + } + } + }; + + /* Packing Subheader display */ + static hf_register_info hf_pack[] = + { + { + &hf_mac_header_generic_packing_subhd_fc, + { + "Fragment Type", "wmx.genericPackSubhd.Fc", + FT_UINT16, BASE_DEC, VALS(frag_types), PACKING_SUBHEADER_FC_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_fc_ext, + { + "Fragment Type", "wmx.genericPackSubhd.FcExt", + FT_UINT24, BASE_HEX, VALS(frag_types), PACKING_SUBHEADER_FC_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_bsn, + { + "First Block Sequence Number", "wmx.genericPackSubhd.Bsn", + FT_UINT24, BASE_DEC, NULL, PACKING_SUBHEADER_BSN_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_fsn, + { + "Fragment Number", "wmx.genericPackSubhd.Fsn", + FT_UINT16, BASE_DEC, NULL, PACKING_SUBHEADER_FSN_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_fsn_ext, + { + "Fragment Number", "wmx.genericPackSubhd.FsnExt", + FT_UINT24, BASE_DEC, NULL, PACKING_SUBHEADER_BSN_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_len, + { + "Length", "wmx.genericPackSubhd.Len", + FT_UINT16, BASE_DEC, NULL, PACKING_SUBHEADER_LENGTH_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_packing_subhd_len_ext, + { + "Length", "wmx.genericPackSubhd.LenExt", + FT_UINT24, BASE_DEC, NULL, PACKING_SUBHEADER_LENGTH_EXT_MASK, + NULL, HFILL + } + } + }; + + /* Fast-feedback Allocation Subheader display */ + static hf_register_info hf_fast[] = + { + { + &hf_mac_header_generic_fast_fb_subhd_alloc_offset, + { + "Allocation Offset", "wmx.genericFastFbSubhd.AllocOffset", + FT_UINT8, BASE_DEC, NULL, FAST_FEEDBACK_ALLOCATION_OFFSET_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_fast_fb_subhd_fb_type, + { + "Feedback Type", "wmx.genericFastFbSubhd.FbType", + FT_UINT8, BASE_DEC, VALS(fast_fb_types), FAST_FEEDBACK_FEEDBACK_TYPE_MASK, + NULL, HFILL + } + } + }; + + /* Grant Management Subheader display */ + static hf_register_info hf_grant[] = + { + { + &hf_mac_header_generic_grant_mgmt_ext_pbr_tree, + { + "Scheduling Service Type (Default)", + "wmx.genericGrantSubhd.Default", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_pbr, + { + "PiggyBack Request", "wmx.genericGrantSubhd.Pbr", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_ugs_tree, + { + "Scheduling Service Type (UGS)", "wmx.genericGrantSubhd.UGS", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_si, + { + "Slip Indicator", "wmx.genericGrantSubhd.Si", + FT_UINT16, BASE_DEC, VALS(si_msgs), GRANT_MGMT_SUBHEADER_UGS_SI_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_pm, + { + "Poll-Me", "wmx.genericGrantSubhd.Pm", + FT_UINT16, BASE_DEC, VALS(pm_msgs), GRANT_MGMT_SUBHEADER_UGS_PM_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_fli, + { + "Frame Latency Indication", "wmx.genericGrantSubhd.Fli", + FT_UINT16, BASE_DEC, VALS(fli_msgs), GRANT_MGMT_SUBHEADER_UGS_FLI_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_fl, + { + "Frame Latency", "wmx.genericGrantSubhd.Fl", + FT_UINT16, BASE_DEC, NULL, GRANT_MGMT_SUBHEADER_UGS_FL_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ugs_rsv, + { + "Reserved", "wmx.genericGrantSubhd.Rsv", + FT_UINT16, BASE_DEC, NULL, GRANT_MGMT_SUBHEADER_UGS_RSV_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_ext_rtps_tree, + { + "Scheduling Service Type (Extended rtPS)", + "wmx.genericGrantSubhd.ExtendedRTPS", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ext_pbr, + { + "Extended PiggyBack Request", "wmx.genericGrantSubhd.ExtPbr", + FT_UINT16, BASE_DEC, NULL, GRANT_MGMT_SUBHEADER_EXT_PBR_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ext_fli, + { + "Frame Latency Indication", "wmx.genericGrantSubhd.ExtFli", + FT_UINT16, BASE_DEC, VALS(fli_msgs), GRANT_MGMT_SUBHEADER_EXT_FLI_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_grant_mgmt_subhd_ext_fl, + { + "Frame Latency", "wmx.genericGrantSubhd.ExtFl", + FT_UINT16, BASE_DEC, NULL, GRANT_MGMT_SUBHEADER_EXT_FL_MASK, + NULL, HFILL + } + } + }; + + /* ARQ Feedback Payload display */ + static hf_register_info hf_arq[] = + { + { + &hf_mac_header_generic_arq_fb_ie_cid, + { + "CID", "wmx.genericArq.FbIeCid", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_last, + { + "Last IE", "wmx.genericArq.FbIeLast", + FT_UINT16, BASE_DEC, VALS(last_ie_msgs), ARQ_FB_IE_LAST_BIT_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_ack_type, + { + "ACK Type", "wmx.genericArq.FbIeAckType", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_ACK_TYPE_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_bsn, + { + "BSN", "wmx.genericArq.FbIeBsn", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_BSN_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_num_maps, + { + "Number of ACK Maps", "wmx.genericArq.FbIeMaps", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_NUM_MAPS_MASK, + NULL, HFILL + } + }, + { + &hf_ack_type_reserved, + { + "Reserved", "wmx.genericArq.FbIeRsvd", FT_UINT16, BASE_DEC, NULL, 0x03, NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_sel_ack_map, + { + "Selective ACK Map", "wmx.genericArq.FbIeSelAckMap", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq_format, + { + "Sequence Format", "wmx.genericArq.FbIeSeqFmt", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ_FORMAT_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq_ack_map, + { + "Sequence ACK Map", "wmx.genericArq.FbIeSeqAckMap", + FT_UINT16, BASE_HEX, NULL, ARQ_FB_IE_SEQ_ACK_MAP_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq1_length, + { + "Sequence 1 Length", "wmx.genericArq.FbIeSeq1Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ1_LENGTH_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq2_length, + { + "Sequence 2 Length", "wmx.genericArq.FbIeSeq2Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ2_LENGTH_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq3_length, + { + "Sequence 3 Length", "wmx.genericArq.FbIeSeq3Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ3_LENGTH_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq_ack_map_2, + { + "Sequence ACK Map", "wmx.genericArq.FbIeSeqAckMap2", + FT_UINT16, BASE_HEX, NULL, ARQ_FB_IE_SEQ_ACK_MAP_2_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq1_length_6, + { + "Sequence 1 Length", "wmx.genericArq.FbIeSeq1Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ1_LENGTH_6_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_seq2_length_6, + { + "Sequence 2 Length", "wmx.genericArq.FbIeSeq2Len", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_SEQ2_LENGTH_6_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_generic_arq_fb_ie_rsv, + { + "Reserved", "wmx.genericArq.FbIeRsv", + FT_UINT16, BASE_DEC, NULL, ARQ_FB_IE_RSV_MASK, + NULL, HFILL + } + }, + { + &hf_mac_header_payload_fragment, + { + "Payload Fragment", "wmx.payload_fragment", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_header_generic_decoder, + /* &ett_mac_subheader_decoder, */ + &ett_mac_mesh_subheader_decoder, + &ett_mac_frag_subheader_decoder, + &ett_mac_grant_mgmt_subheader_decoder, + &ett_mac_pkt_subheader_decoder, + &ett_mac_fast_fb_subheader_decoder, + &ett_mac_ext_subheader_decoder, + &ett_mac_ext_subheader_dl_decoder, + &ett_mac_ext_subheader_ul_decoder, + &ett_mac_arq_fb_payload_decoder, + &ett_mac_data_pdu_decoder, + }; + + static ei_register_info ei[] = { + { &ei_mac_crc_malformed, { "wmx.genericCrc.missing", PI_MALFORMED, PI_ERROR, "CRC missing - the frame is too short", EXPFILL }}, + { &ei_mac_crc_missing, { "wmx.genericCrc.missing", PI_PROTOCOL, PI_NOTE, "CRC is not included in this frame!", EXPFILL }}, + { &ei_mac_header_generic_crc, { "wmx.genericCrc.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, + }; + + expert_module_t* expert_mac_header_generic; + + proto_mac_header_generic_decoder = proto_register_protocol ( + "WiMax Generic/Type1/Type2 MAC Header Messages", /* name */ + "WiMax Generic/Type1/Type2 MAC Header (hdr)", /* short name */ + "wmx.hdr" /* abbrev */ + ); + + /* register the field display messages */ + proto_register_field_array(proto_mac_header_generic_decoder, hf, array_length(hf)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_ext, array_length(hf_ext)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_mesh, array_length(hf_mesh)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_frag, array_length(hf_frag)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_pack, array_length(hf_pack)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_fast, array_length(hf_fast)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_grant, array_length(hf_grant)); + proto_register_field_array(proto_mac_header_generic_decoder, hf_arq, array_length(hf_arq)); + proto_register_subtree_array(ett, array_length(ett)); + + expert_mac_header_generic = expert_register_protocol(proto_mac_header_generic_decoder); + expert_register_field_array(expert_mac_header_generic, ei, array_length(ei)); + + /* register the generic mac header dissector */ + register_dissector("mac_header_generic_handler", dissect_mac_header_generic_decoder, proto_mac_header_generic_decoder); + + /* Register the payload fragment table init routine */ + register_init_routine(wimax_defragment_init); + register_cleanup_routine(wimax_defragment_cleanup); + reassembly_table_register(&payload_reassembly_table, + &addresses_reassembly_table_functions); +} + +void +wimax_proto_reg_handoff_mac_header_generic(void) +{ + mac_mgmt_msg_decoder_handle = find_dissector("wmx_mac_mgmt_msg_decoder"); + mac_ip_handle = find_dissector("ip"); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/mac_hd_type1_decoder.c b/plugins/epan/wimax/mac_hd_type1_decoder.c new file mode 100644 index 00000000..6713e920 --- /dev/null +++ b/plugins/epan/wimax/mac_hd_type1_decoder.c @@ -0,0 +1,560 @@ +/* mac_hd_type1_decoder.c + * WiMax MAC Type I Signaling Header decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* TODO: Add FT_UINT24 and FT_INT24 cases to gtk_widget_get_toplevel() + * to prevent having to make all the changes from BASE_DEC to BASE_HEX + * made to this file today: 10/20/06. + */ + +/* Include files */ + +#include "config.h" + +/* +#define DEBUG +*/ + +#include +#include "wimax-int.h" + +extern gint proto_mac_header_generic_decoder; + +static gint proto_mac_header_type_1_decoder = -1; +static gint ett_mac_header_type_1_decoder = -1; +static gint hf_mac_header_type_1_value_bytes = -1; + +#define WIMAX_MAC_HEADER_SIZE 6 + +/* WiMax MAC Header Type I Sub Types */ +typedef enum +{ + BR_INCREMENTAL, /* 0 */ + BR_AGGREGATE, /* 1 */ + PHY_CHANNEL_REPORT, /* 2 */ + BR_WITH_UL_TX_POWER_REPORT,/* 3 */ + BR_AND_CINR_REPORT, /* 4 */ + BR_WITH_UL_SLEEP_CONTROL, /* 5 */ + SN_REPORT, /* 6 */ + CQICH_ALLOCATION_REQUEST, /* 7 */ + TYPE_I_SUBTYPE_MAX +} TYPE_I_SUBTYPE_e; + +static const char *type1_subtype_abbrv[TYPE_I_SUBTYPE_MAX] = +{ + "BR INCREMENTAL", /* 0 */ + "BR AGGREGATE", /* 1 */ + "PHY CHANNEL_REPORT", /* 2 */ + "BR WITH UL TX POWER_REPORT",/* 3 */ + "BR AND CINR REPORT", /* 4 */ + "BR WITH UL SLEEP CONTROL", /* 5 */ + "SN REPORT", /* 6 */ + "CQICH ALLOCATION REQUEST" /* 7 */ +}; + +#define WIMAX_MAC_HEADER_TYPE_1_SUB_TYPE_MASK 0x38 + +/* WIMAX MAC HEADER TYPE I FILEDS */ +/* 1st to 3rd bytes */ +/* Common Fields */ +#define WIMAX_MAC_HEADER_TYPE_1_HT 0x800000 +#define WIMAX_MAC_HEADER_TYPE_1_EC 0x400000 +#define WIMAX_MAC_HEADER_TYPE_1_TYPE 0x380000 +/* Bandwidth Request Incremental Header (type 0) & + Bandwidth Request Aggregate Header (type 1) only */ +#define WIMAX_MAC_HEADER_TYPE_1_BR 0x07FFFF +/* PHY Channel Report Header (type 2) only */ +#define WIMAX_MAC_HEADER_TYPE_1_DIUC 0x078000 +#define WIMAX_MAC_HEADER_TYPE_1_UL_TX_PWR 0x007F80 +#define WIMAX_MAC_HEADER_TYPE_1_UL_HDRM 0x00007E +#define WIMAX_MAC_HEADER_TYPE_1_RSV_2 0x000001 +/* Bandwidth Request and UL TX Power Report Header (type 3), + Bandwidth Request and CINR Report Header (type 4), & + Bandwidth Request and Uplink Sleep Control Header (type 5) only */ +#define WIMAX_MAC_HEADER_TYPE_1_BR_3 0x07FF00 +/* Bandwidth Request and UL TX Power Report Header (type 3) only */ +#define WIMAX_MAC_HEADER_TYPE_1_UL_TX_PWR_3 0x0000FF +/* Bandwidth Request and CINR Report Header (type 4) only */ +#define WIMAX_MAC_HEADER_TYPE_1_CINR 0x0000FE +#define WIMAX_MAC_HEADER_TYPE_1_DCI 0x000001 +/* Bandwidth Request and Uplink Sleep Control Header (type 5) only */ +#define WIMAX_MAC_HEADER_TYPE_1_PSCID 0x0000FC +#define WIMAX_MAC_HEADER_TYPE_1_OP 0x000002 +#define WIMAX_MAC_HEADER_TYPE_1_RSV_5 0x000001 +/* SN Report Header (type 6) only */ +#define WIMAX_MAC_HEADER_TYPE_1_LAST 0x040000 +#define WIMAX_MAC_HEADER_TYPE_1_SDU_SN1 0x03F000 +#define WIMAX_MAC_HEADER_TYPE_1_SDU_SN2 0x000FC0 +#define WIMAX_MAC_HEADER_TYPE_1_SDU_SN3 0x00003F +/* CQICH Allocation Request (type 7) only */ +#define WIMAX_MAC_HEADER_TYPE_1_FB_TYPE 0x070000 +#define WIMAX_MAC_HEADER_TYPE_1_FBSSI 0x008000 +#define WIMAX_MAC_HEADER_TYPE_1_PERIOD 0x007000 +#define WIMAX_MAC_HEADER_TYPE_1_RSV_7 0x000FFF +/* 4th to 6th bytes */ +/*#define WIMAX_MAC_HEADER_TYPE_1_CID 0xFFFF + *#define WIMAX_MAC_HEADER_TYPE_1_HCS 0xFF + */ +/* Common Fields */ +static int hf_mac_header_type_1_ht = -1; +static int hf_mac_header_type_1_ec = -1; +static int hf_mac_header_type_1_type = -1; +/* type 0 & type 1 only */ +static int hf_mac_header_type_1_br = -1; +/* type 3, type 4, & type 5 only */ +static int hf_mac_header_type_1_br_3 = -1; +/* type 2 only */ +static int hf_mac_header_type_1_diuc = -1; +static int hf_mac_header_type_1_ultxpwr = -1; +static int hf_mac_header_type_1_ulhdrm = -1; +static int hf_mac_header_type_1_rsv_2 = -1; +/* type 3 only */ +static int hf_mac_header_type_1_ultxpwr_3 = -1; +/* type 4 only */ +static int hf_mac_header_type_1_cinr = -1; +static int hf_mac_header_type_1_dci = -1; +/* type 5 only */ +static int hf_mac_header_type_1_pscid = -1; +static int hf_mac_header_type_1_op = -1; +static int hf_mac_header_type_1_rsv_5 = -1; +/* type 6 only */ +static int hf_mac_header_type_1_last = -1; +static int hf_mac_header_type_1_sdu_sn1 = -1; +static int hf_mac_header_type_1_sdu_sn2 = -1; +static int hf_mac_header_type_1_sdu_sn3 = -1; +/* type 7 only */ +static int hf_mac_header_type_1_fb_type = -1; +static int hf_mac_header_type_1_fbssi = -1; +static int hf_mac_header_type_1_period = -1; +static int hf_mac_header_type_1_rsv_7 = -1; +/* Common Fields */ +static int hf_mac_header_type_1_cid = -1; +static int hf_mac_header_type_1_hcs = -1; + +/* MAC Header Type I Sub-Types */ +static const value_string sub_types[] = +{ + { BR_INCREMENTAL, "Bandwidth Request Incremental" }, + { BR_AGGREGATE, "Bandwidth Request Aggregate" }, + { PHY_CHANNEL_REPORT, "PHY Channel Report" }, + { BR_WITH_UL_TX_POWER_REPORT, "Bandwidth Request with UL TX Power Report" }, + { BR_AND_CINR_REPORT, "Bandwidth Request and CINR Report" }, + { BR_WITH_UL_SLEEP_CONTROL, "Bandwidth Request with Sleep Control" }, + { SN_REPORT, "SN Report" }, + { CQICH_ALLOCATION_REQUEST, "CQICH Allocation Request" }, + { 0, NULL} +}; + +/* Feedback Types (need to be changed for type I) */ +static const value_string fb_types[] = +{ + { 0, "CQI and MIMO Feedback" }, + { 1, "DL average CINR" }, + { 2, "MIMO Coefficients Feedback" }, + { 3, "Preferred DL Channel DIUC Feedback" }, + { 4, "UL Transmission Power" }, + { 5, "PHY Channel Feedback" }, + { 6, "AMC Band Indication Bitmap" }, + { 7, "Life Span of Short-term Precoding Feedback" }, + { 0, NULL} +}; + +/* DCD Change Indication messages */ +static const value_string dci_msgs[] = +{ + { 0, "Match DCD Change Count" }, + { 1, "Mismatch DCD Change Count" }, + { 0, NULL} +}; + +/* Operation messages */ +static const value_string op_msgs[] = +{ + { 0, "Deactivate Power Saving Class" }, + { 1, "Activate Power Saving Class" }, + { 0, NULL} +}; + +/* Last ARQ BSN or SDU SN Indication messages */ +static const value_string last_msgs[] = +{ + { 0, "First three connections" }, + { 1, "Last three connections" }, + { 0, NULL} +}; + +static int dissect_mac_header_type_1_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + gint tvb_len, offset = 0; + guint first_byte, sub_type; + proto_item *parent_item = NULL; + proto_item *ti = NULL; + proto_tree *ti_tree = NULL; + + if (tree) + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display the MAC Type I Header message */ + ti = proto_tree_add_protocol_format(tree, proto_mac_header_type_1_decoder, tvb, offset, tvb_len, "Mac Type I Header (%u bytes)", WIMAX_MAC_HEADER_SIZE); + /* add subtree */ + ti_tree = proto_item_add_subtree(ti, ett_mac_header_type_1_decoder); + if(tvb_len < WIMAX_MAC_HEADER_SIZE) + { + /* display the MAC Type I Header in Hex */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_value_bytes, tvb, offset, tvb_len, ENC_NA); + return tvb_captured_length(tvb); + } +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, type1_subtype_abbrv[]); +#endif + /* get the parent */ + parent_item = proto_tree_get_parent(tree); + /* Decode and display the first 3 bytes of the header */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_ht, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_mac_header_type_1_ec, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_mac_header_type_1_type, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Get the first byte */ + first_byte = tvb_get_guint8(tvb, offset); + /* get the sub Type */ + sub_type = ((first_byte & WIMAX_MAC_HEADER_TYPE_1_SUB_TYPE_MASK)>>3); + if(sub_type < TYPE_I_SUBTYPE_MAX) + { + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, type1_subtype_abbrv[sub_type]); + } + else + { + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Unknown type 1 subtype"); + /* display MAC Header Type I Subtype */ + proto_tree_add_protocol_format(ti_tree, proto_mac_header_type_1_decoder, tvb, offset, tvb_len, "Unknown type 1 subtype: %u", sub_type); + /* display the MAC Type I Header in Hex */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_value_bytes, tvb, offset, tvb_len, ENC_NA); + return tvb_captured_length(tvb); + } + /* add the MAC header info */ + proto_item_append_text(parent_item, "%s", type1_subtype_abbrv[sub_type]); + switch (sub_type) + { + case BR_INCREMENTAL: + case BR_AGGREGATE: + /* Decode and display the Bandwidth Request */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_br, tvb, offset, 3, ENC_BIG_ENDIAN); + break; + case PHY_CHANNEL_REPORT: + /* Decode and display the Preferred-DIUC */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_diuc, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the UL TX Power */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_ultxpwr, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the UL Headroom */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_ulhdrm, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the reserved filed */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_rsv_2, tvb, offset, 3, ENC_BIG_ENDIAN); + break; + case BR_WITH_UL_TX_POWER_REPORT: + /* Decode and display the Bandwidth Request */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_br_3, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the UL TX Power */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_ultxpwr_3, tvb, offset, 3, ENC_BIG_ENDIAN); + break; + case BR_AND_CINR_REPORT: + /* Decode and display the Bandwidth Request */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_br_3, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the CINR */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_cinr, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the DCD Change Indication */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_dci, tvb, offset, 3, ENC_BIG_ENDIAN); + break; + case BR_WITH_UL_SLEEP_CONTROL: + /* Decode and display the Bandwidth Request */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_br_3, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the Power Saving Class ID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_pscid, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the Operation */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_op, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the reserved filed */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_rsv_5, tvb, offset, 3, ENC_BIG_ENDIAN); + break; + case SN_REPORT: + /* Decode and display the Last field */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_last, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the SDU SN1 */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_sdu_sn1, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the SDU SN2 */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_sdu_sn2, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the SDU SN3 */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_sdu_sn3, tvb, offset, 3, ENC_BIG_ENDIAN); + break; + case CQICH_ALLOCATION_REQUEST: + /* Decode and display the Feedback Type */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_fb_type, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the FBSSI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_fbssi, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the Prreferred-period */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_period, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the reserved filed */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_rsv_7, tvb, offset, 3, ENC_BIG_ENDIAN); + break; + } + /* Decode and display the CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_cid, tvb, (offset+3), 2, ENC_BIG_ENDIAN); + /* Decode and display the HCS */ + proto_tree_add_item(ti_tree, hf_mac_header_type_1_hcs, tvb, (offset+5), 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Header Type II Protocol and Dissector */ +void wimax_proto_register_mac_header_type_1(void) +{ + /* TLV display */ + static hf_register_info hf[] = + { + { + &hf_mac_header_type_1_value_bytes, + { + "Values", "wmx.type1ValueBytes", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_ht, + { + "MAC Header Type", "wmx.type1Ht", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_HT, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_ec, + { + "MAC Encryption Control", "wmx.type1Ec", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_EC, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_type, + { + "MAC Sub-Type", "wmx.type1Type", + FT_UINT24, BASE_HEX, VALS(sub_types), WIMAX_MAC_HEADER_TYPE_1_TYPE, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_br, + { + "Bandwidth Request", "wmx.type1Br", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_BR, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_br_3, + { + "Bandwidth Request", "wmx.type1Br3", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_BR_3, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_fb_type, + { + "Feedback Type", "wmx.type1FbType", + FT_UINT24, BASE_HEX, VALS(fb_types), WIMAX_MAC_HEADER_TYPE_1_FB_TYPE, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_diuc, + { + "Preferred DIUC Index", "wmx.type1Diuc", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_DIUC, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_ultxpwr, + { + "UL TX Power", "wmx.type1UlTxPwr", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_UL_TX_PWR, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_ultxpwr_3, + { + "UL TX Power", "wmx.type1UlTxPwr3", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_UL_TX_PWR_3, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_ulhdrm, + { + "Headroom to UL Max Power Level", "wmx.type1HdRm", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_UL_HDRM, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_cinr, + { + "CINR Value", "wmx.type1Cinr", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_CINR, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_dci, + { + "DCD Change Indication", "wmx.type1Dci", + FT_UINT24, BASE_HEX, VALS(dci_msgs), WIMAX_MAC_HEADER_TYPE_1_DCI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_pscid, + { + "Power Saving Class ID", "wmx.type1PsCid", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_PSCID, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_op, + { + "Operation", "wmx.type1Op", + FT_UINT24, BASE_HEX, VALS(op_msgs), WIMAX_MAC_HEADER_TYPE_1_OP, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_last, + { + "Last ARQ BSN or SDU SN", "wmx.type1Last", + FT_UINT24, BASE_HEX, VALS(last_msgs), WIMAX_MAC_HEADER_TYPE_1_LAST, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_sdu_sn1, + { + "ARQ BSN or MAC SDU SN (1)", "wmx.type1SduSn1", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_SDU_SN1, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_sdu_sn2, + { + "ARQ BSN or MAC SDU SN (2)", "wmx.type1SduSn2", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_SDU_SN2, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_sdu_sn3, + { + "ARQ BSN or MAC SDU SN (3)", "wmx.type1SduSn3", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_SDU_SN3, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_fbssi, + { + "FBSS Indicator", "wmx.type1Fbssi", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_FBSSI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_period, + { + "Preferred CQICH Allocation Period", "wmx.type1Period", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_PERIOD, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_rsv_2, + { + "Reserved", "wmx.type1Rsv2", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_RSV_2, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_rsv_5, + { + "Reserved", "wmx.type1Rsv5", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_RSV_5, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_rsv_7, + { + "Reserved", "wmx.type1Rsv7", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_1_RSV_7, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_cid, + { + "Connection ID", "wmx.type1Cid", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_type_1_hcs, + { + "Header Check Sequence", "wmx.type1Hcs", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_header_type_1_decoder, + }; + + proto_mac_header_type_1_decoder = proto_mac_header_generic_decoder; + + proto_register_field_array(proto_mac_header_type_1_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("mac_header_type_1_handler", dissect_mac_header_type_1_decoder, proto_mac_header_type_1_decoder); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/mac_hd_type2_decoder.c b/plugins/epan/wimax/mac_hd_type2_decoder.c new file mode 100644 index 00000000..466b4b20 --- /dev/null +++ b/plugins/epan/wimax/mac_hd_type2_decoder.c @@ -0,0 +1,1370 @@ +/* mac_hd_type2_decoder.c + * WiMax MAC Type II Signaling Header decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* TODO: Add FT_UINT24 and FT_INT24 cases to gtk_widget_get_toplevel() + * to prevent having to make all the changes from BASE_DEC to BASE_HEX + * made to this file today: 10/20/06. + */ + +/* +#define DEBUG +*/ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax-int.h" + +extern gint proto_mac_header_generic_decoder; + +static gint proto_mac_header_type_2_decoder = -1; +static gint ett_mac_header_type_2_decoder = -1; +static gint hf_mac_header_type_2_value_bytes = -1; + +#define WIMAX_MAC_HEADER_SIZE 6 + +/* WiMax MAC Header Type II Feedback Types */ +typedef enum +{ + CQI_MIMO_FB, /* 0 */ + DL_AVG_CINR, /* 1 */ + MIMO_COEF_FB, /* 2 */ + PREF_DL_CHAN_DIUC_FB,/* 3 */ + UL_TX_PWR, /* 4 */ + PHY_CHAN_FB, /* 5 */ + AMC_BAND_BITMAP, /* 6 */ + SHORT_PRECODE_FB, /* 7 */ + MULTI_TYPES_FB, /* 8 */ + LONG_PRECODE_FB, /* 9 */ + COMB_DL_AVG_CINR, /* 10 */ + MIMO_CHAN_FB, /* 11 */ + CINR_FB, /* 12 */ + CL_MIMO_FB, /* 13 */ + TYPE_II_FB_TYPE_MAX +} TYPE_II_FB_TYPE_e; + +static const char *type2_fb_type_abbrv[TYPE_II_FB_TYPE_MAX] = +{ + "CQI and MIMO Feedback", + "DL average CINR", + "MIMO Coefficients Feedback", + "Preferred DL Channel DIUC Feedback", + "UL Transmission Power", + "PHY Channel Feedback", + "AMC Band Indication Bitmap", + "Life Span of Short-term Precoding Feedback", + "Multiple Types of Feedback", + "Long-term Precoding Feedback", + "Combined DL Average CINR of Active BSs", + "MIMO Channel Feedback", + "CINR Feedback", + "Close-loop MIMO Feedback" +}; + +/* WIMAX MAC HEADER TYPE II FILEDS */ +/* first byte */ +#define WIMAX_MAC_HEADER_TYPE_2_HT 0x80 +#define WIMAX_MAC_HEADER_TYPE_2_EC 0x40 +#define WIMAX_MAC_HEADER_TYPE_2_TYPE 0x20 +#define WIMAX_MAC_HEADER_TYPE_2_CII 0x10 +#define WIMAX_MAC_HEADER_TYPE_2_FB_TYPE 0x0F +static int hf_mac_header_type_2_ht = -1; +static int hf_mac_header_type_2_ec = -1; +static int hf_mac_header_type_2_type = -1; +static int hf_mac_header_type_2_cii = -1; +static int hf_mac_header_type_2_fb_type = -1; + +/* 2nd to 5th bytes (varies by different fb types) */ +static int hf_mac_header_type_2_cid = -1; +static int hf_mac_header_type_2_no_cid = -1; +/* CQI and MIMO Feedback */ +/* 2nd & 3rd bytes */ +#define WIMAX_MAC_HEADER_TYPE_2_CQI_FB_TYPE 0xE000 +#define WIMAX_MAC_HEADER_TYPE_2_CQI_PAYLOAD 0x1F80 +#define WIMAX_MAC_HEADER_TYPE_2_CQI_RSV 0x007F +static int hf_mac_header_type_2_cqi_fb_type = -1; +static int hf_mac_header_type_2_cqi_payload = -1; +static int hf_mac_header_type_2_cqi_rsv = -1; +/* 4th & 5th without CID */ +/*#define WIMAX_MAC_HEADER_TYPE_2_NO_CID 0xFFFF*/ + +/* DL average CINR */ +/* 2nd byte */ +#define WIMAX_MAC_HEADER_TYPE_2_DL_AVE_CINR 0xF800 +#define WIMAX_MAC_HEADER_TYPE_2_DL_AVE_RSV 0x07FF +static int hf_mac_header_type_2_dl_ave_cinr = -1; +static int hf_mac_header_type_2_dl_ave_rsv = -1; + +/* MIMO Coefficients Feedback */ +/* 2nd & 3rd bytes */ +#define WIMAX_MAC_HEADER_TYPE_2_MIMO_COEF_NI 0xC000 +#define WIMAX_MAC_HEADER_TYPE_2_MIMO_COEF_AI 0x3000 +#define WIMAX_MAC_HEADER_TYPE_2_MIMO_COEF 0x0F80 +#define WIMAX_MAC_HEADER_TYPE_2_MIMO_COEF_RSV 0x007F +static int hf_mac_header_type_2_mimo_coef_ni = -1; +static int hf_mac_header_type_2_mimo_coef_ai = -1; +static int hf_mac_header_type_2_mimo_coef = -1; +static int hf_mac_header_type_2_mimo_coef_rsv = -1; + +/* Preferred DL Channel DIUC Feedback */ +/* 2nd byte */ +#define WIMAX_MAC_HEADER_TYPE_2_DL_CHAN_DIUC 0xF000 +#define WIMAX_MAC_HEADER_TYPE_2_DL_CHAN_DCD 0x0F00 +#define WIMAX_MAC_HEADER_TYPE_2_DL_CHAN_RSV 0x00FF +static int hf_mac_header_type_2_dl_chan_diuc = -1; +static int hf_mac_header_type_2_dl_chan_dcd = -1; +static int hf_mac_header_type_2_dl_chan_rsv = -1; + +/* UL Transmission Power */ +/* 2nd byte */ +#define WIMAX_MAC_HEADER_TYPE_2_UL_TX_PWR 0xFF00 +#define WIMAX_MAC_HEADER_TYPE_2_UL_TX_PWR_RSV 0x00FF +static int hf_mac_header_type_2_ul_tx_pwr = -1; +static int hf_mac_header_type_2_ul_tx_pwr_rsv = -1; + +/* PHY Channel Feedback */ +/* 2nd to 4th bytes */ +#define WIMAX_MAC_HEADER_TYPE_2_PHY_DIUC 0xF00000 +#define WIMAX_MAC_HEADER_TYPE_2_PHY_UL_TX_PWR 0x0FF000 +#define WIMAX_MAC_HEADER_TYPE_2_PHY_UL_HDRM 0x000FC0 +#define WIMAX_MAC_HEADER_TYPE_2_PHY_RSV 0x00003F +static int hf_mac_header_type_2_phy_diuc = -1; +static int hf_mac_header_type_2_phy_ul_tx_pwr = -1; +static int hf_mac_header_type_2_phy_ul_hdrm = -1; +static int hf_mac_header_type_2_phy_rsv = -1; + +/* AMC Band Indication Bitmap */ +/* 2nd to 5th bytes */ +#define WIMAX_MAC_HEADER_TYPE_2_AMC_BITMAP 0xFFF00000 +#define WIMAX_MAC_HEADER_TYPE_2_AMC_CQI_1 0x000F8000 +#define WIMAX_MAC_HEADER_TYPE_2_AMC_CQI_2 0x00007C00 +#define WIMAX_MAC_HEADER_TYPE_2_AMC_CQI_3 0x000003E0 +#define WIMAX_MAC_HEADER_TYPE_2_AMC_CQI_4 0x0000001F +static int hf_mac_header_type_2_amc_bitmap = -1; +static int hf_mac_header_type_2_amc_cqi_1 = -1; +static int hf_mac_header_type_2_amc_cqi_2 = -1; +static int hf_mac_header_type_2_amc_cqi_3 = -1; +static int hf_mac_header_type_2_amc_cqi_4 = -1; + +/* Life Span of Short-term Precoding Feedback */ +/* 2nd byte */ +#define WIMAX_MAC_HEADER_TYPE_2_LIFE_SPAN 0xF000 +#define WIMAX_MAC_HEADER_TYPE_2_LIFE_SPAN_RSV 0x0FFF +static int hf_mac_header_type_2_life_span = -1; +static int hf_mac_header_type_2_life_span_rsv = -1; + +/* Multiple Types of Feedback */ +/* 2nd to 5th bytes ??? */ +#define WIMAX_MAC_HEADER_TYPE_2_MT_NUM_FB_TYPES 0xC0000000 +#define WIMAX_MAC_HEADER_TYPE_2_MT_OCCU_FB_TYPE 0x3C000000 +#define WIMAX_MAC_HEADER_TYPE_2_MT_FB_CONTENTS 0x03FFFFFF +static int hf_mac_header_type_2_mt_num_fb_types = -1; +static int hf_mac_header_type_2_mt_occu_fb_type = -1; +static int hf_mac_header_type_2_mt_fb_contents = -1; + +/* Long-term Precoding Feedback */ +/* 2nd & 3rd bytes */ +#define WIMAX_MAC_HEADER_TYPE_2_LT_ID_FB 0xFC00 +#define WIMAX_MAC_HEADER_TYPE_2_LT_RANK 0x0300 +#define WIMAX_MAC_HEADER_TYPE_2_LT_FEC_QAM 0x00FC +#define WIMAX_MAC_HEADER_TYPE_2_LT_RSV 0x0003 +static int hf_mac_header_type_2_lt_id_fb = -1; +static int hf_mac_header_type_2_lt_rank = -1; +static int hf_mac_header_type_2_lt_fec_qam = -1; +static int hf_mac_header_type_2_lt_rsv = -1; + +/* Combined DL Average CINR of Active BSs */ +/* 2nd & 3rd bytes */ +#define WIMAX_MAC_HEADER_TYPE_2_COMB_DL_AVE 0xF800 +#define WIMAX_MAC_HEADER_TYPE_2_COMB_DL_RSV 0x0EFF +static int hf_mac_header_type_2_comb_dl_ave = -1; +static int hf_mac_header_type_2_comb_dl_rsv = -1; + +/* MIMO Channel Feedback */ +/* 2nd byte */ +#define WIMAX_MAC_HEADER_TYPE_2_DIUC 0xF0 +#define WIMAX_MAC_HEADER_TYPE_2_PBWI 0x0F +/* 3rd to 5th bytes with CID */ +#define WIMAX_MAC_HEADER_TYPE_2_SLPB 0xFE0000 +#define WIMAX_MAC_HEADER_TYPE_2_PBRI_CID 0x010000 +#define WIMAX_MAC_HEADER_TYPE_2_CID 0x00FFFF +/* 3rd to 5th bytes without CID */ +#define WIMAX_MAC_HEADER_TYPE_2_PBRI 0x018000 +#define WIMAX_MAC_HEADER_TYPE_2_CTI 0x007000 +#define WIMAX_MAC_HEADER_TYPE_2_AI_0 0x000800 +#define WIMAX_MAC_HEADER_TYPE_2_AI_1 0x000400 +#define WIMAX_MAC_HEADER_TYPE_2_AI_2 0x000200 +#define WIMAX_MAC_HEADER_TYPE_2_AI_3 0x000100 +#define WIMAX_MAC_HEADER_TYPE_2_MI 0x0000C0 +#define WIMAX_MAC_HEADER_TYPE_2_CT 0x000020 +#define WIMAX_MAC_HEADER_TYPE_2_CQI 0x00001F +static int hf_mac_header_type_2_mimo_diuc = -1; +static int hf_mac_header_type_2_mimo_pbwi = -1; +static int hf_mac_header_type_2_mimo_slpb = -1; +static int hf_mac_header_type_2_mimo_bpri = -1; +static int hf_mac_header_type_2_mimo_bpri_cid = -1; +static int hf_mac_header_type_2_mimo_cid = -1; +static int hf_mac_header_type_2_mimo_cti = -1; +static int hf_mac_header_type_2_mimo_ai_0 = -1; +static int hf_mac_header_type_2_mimo_ai_1 = -1; +static int hf_mac_header_type_2_mimo_ai_2 = -1; +static int hf_mac_header_type_2_mimo_ai_3 = -1; +static int hf_mac_header_type_2_mimo_mi = -1; +static int hf_mac_header_type_2_mimo_ct = -1; +static int hf_mac_header_type_2_mimo_cqi = -1; + +/* CINR Feedback */ +/* 2nd byte */ +/*#define WIMAX_MAC_HEADER_TYPE_2_CINR_MEAN 0xFF*/ +/* 3rd byte */ +/*#define WIMAX_MAC_HEADER_TYPE_2_CINR_DEVI 0xFF*/ +static int hf_mac_header_type_2_cinr_mean = -1; +static int hf_mac_header_type_2_cinr_devi = -1; + +/* Close-loop MIMO Feedback */ +/* 2nd & 3rd bytes */ +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_TYPE 0xC000 +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_ANT_ID 0x3C00 +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_CQI 0x03E0 +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_RSV 0x008F +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_STREAMS 0x3000 +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_ANT_SEL 0x0E00 +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_CQI_1 0x01F0 +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_RSV_1 0x000F +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_CODEBOOK_ID 0x3F00 +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_CQI_2 0x00F8 +#define WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_RSV_2 0x000E +static int hf_mac_header_type_2_cl_mimo_type = -1; +static int hf_mac_header_type_2_cl_mimo_ant_id = -1; +static int hf_mac_header_type_2_cl_mimo_cqi = -1; +static int hf_mac_header_type_2_cl_mimo_cqi_1 = -1; +static int hf_mac_header_type_2_cl_mimo_cqi_2 = -1; +static int hf_mac_header_type_2_cl_mimo_rsv = -1; +static int hf_mac_header_type_2_cl_mimo_rsv_1 = -1; +static int hf_mac_header_type_2_cl_mimo_rsv_2 = -1; +static int hf_mac_header_type_2_cl_mimo_streams = -1; +static int hf_mac_header_type_2_cl_mimo_ant_sel = -1; +static int hf_mac_header_type_2_cl_mimo_codebook_id = -1; + +/* last byte */ +/*#define WIMAX_MAC_HEADER_TYPE_2_HCS 0xFF*/ +static int hf_mac_header_type_2_hcs = -1; + +/* CID Inclusion Indication messages */ +static const value_string cii_msgs[] = +{ + { 0, "without CID" }, + { 1, "with CID" }, + { 0, NULL} +}; + +/* Feedback Types */ +static const value_string fb_types[] = +{ + { 0, "CQI and MIMO Feedback" }, + { 1, "DL average CINR" }, + { 2, "MIMO Coefficients Feedback" }, + { 3, "Preferred DL Channel DIUC Feedback" }, + { 4, "UL Transmission Power" }, + { 5, "PHY Channel Feedback" }, + { 6, "AMC Band Indication Bitmap" }, + { 7, "Life Span of Short-term Precoding Feedback" }, + { 8, "Multiple Types of Feedback" }, + { 9, "Long-term Precoding Feedback" }, + { 10, "Combined DL Average CINR of Active BSs" }, + { 11, "MIMO Channel Feedback" }, + { 12, "CINR Feedback" }, + { 13, "Close-loop MIMO Feedback" }, + { 14, "Reserved" }, + { 15, "Reserved" }, + { 0, NULL} +}; + +/* Table of the Preferred Bandwidth Ratio of bandwidth over used channel bandwidth */ +static const value_string pbwi_table[] = +{ + { 0, "1" }, + { 1, "3/4" }, + { 2, "2/3" }, + { 3, "1/2" }, + { 4, "1/3" }, + { 5, "1/4" }, + { 6, "1/5" }, + { 7, "1/6" }, + { 8, "1/8" }, + { 9, "1/10" }, + { 10, "1/12" }, + { 11, "1/16" }, + { 12, "1/24" }, + { 13, "1/32" }, + { 14, "1/48" }, + { 15, "1/64" }, + { 0, NULL} +}; + +/* Burst Profile Ranking Indicator table */ +static const value_string bpri_table[] = +{ + { 0, "1st preferred burst profile" }, + { 1, "2nd preferred burst profile" }, + { 2, "3rd preferred burst profile" }, + { 3, "4th preferred burst profile" }, + { 0, NULL} +}; + +/* Coherent Time Index Table */ +static const value_string cti_table[] = +{ + { 0, "Infinite" }, + { 1, "1 frame" }, + { 2, "2 frames" }, + { 3, "3 frames" }, + { 4, "4 frames" }, + { 5, "8 frames" }, + { 6, "14 frames" }, + { 7, "24 frames" }, + { 0, NULL} +}; + +/* The MS Matrix Index Table */ +static const value_string mi_table[] = +{ + { 0, "No STC" }, + { 1, "Matrix A" }, + { 2, "Matrix B" }, + { 3, "Matrix C" }, + { 0, NULL} +}; + +/* CQI Feedback Types */ +static const value_string ct_msgs[] = +{ + { 0, "DL average feedback" }, + { 1, "CQI feedback" }, + { 0, NULL} +}; + +/* Antenna Indication messages */ +static const value_string ai_msgs[] = +{ + { 0, "Not applicable" }, + { 1, "Applicable" }, + { 0, NULL} +}; + + +static int dissect_mac_header_type_2_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + gint tvb_len, offset = 0; + guint cii_bit, first_byte, fb_type, mimo_type; + proto_item *parent_item = NULL; + proto_item *ti = NULL; + proto_tree *ti_tree = NULL; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display the MAC Type II Header message */ + ti = proto_tree_add_protocol_format(tree, proto_mac_header_type_2_decoder, tvb, offset, tvb_len, "Mac Type II Header (6 bytes)"); + /* add subtree */ + ti_tree = proto_item_add_subtree(ti, ett_mac_header_type_2_decoder); + if(tvb_len < WIMAX_MAC_HEADER_SIZE) + { + /* display the error message */ + proto_tree_add_protocol_format(ti_tree, proto_mac_header_type_2_decoder, tvb, offset, tvb_len, "Error: the size of Mac Header Type II tvb is too small! (%u bytes)", tvb_len); + /* display the MAC Type II Header in Hex */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_value_bytes, tvb, offset, tvb_len, ENC_NA); + return tvb_captured_length(tvb); + } +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "MAC Signaling Header Type II"); +#endif + /* get the parent */ + parent_item = proto_tree_get_parent(tree); + /* Decode and display the first byte of the header */ + /* header type */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_ht, tvb, offset, 1, ENC_BIG_ENDIAN); + /* encryption control */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_ec, tvb, offset, 1, ENC_BIG_ENDIAN); + /* sub-type */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_type, tvb, offset, 1, ENC_BIG_ENDIAN); + /* CID inclusion indication */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cii, tvb, offset, 1, ENC_BIG_ENDIAN); + /* feedback type */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_fb_type, tvb, offset, 1, ENC_BIG_ENDIAN); + /* Get the first byte */ + first_byte = tvb_get_guint8(tvb, offset); + /* get the CII field */ + cii_bit = ((first_byte & WIMAX_MAC_HEADER_TYPE_2_CII)?1:0); + /* check the Type field */ + if(!(first_byte & WIMAX_MAC_HEADER_TYPE_2_TYPE)) + { + /* Get the feedback type */ + fb_type = (first_byte & WIMAX_MAC_HEADER_TYPE_2_FB_TYPE); + if(fb_type < TYPE_II_FB_TYPE_MAX) + { + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, type2_fb_type_abbrv[fb_type]); + } + else + { + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Unknown type 2 fb type"); + /* display the MAC Type I Header in Hex */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_value_bytes, tvb, offset, tvb_len, ENC_NA); + return tvb_captured_length(tvb); + } + /* move to the second byte */ + offset++; + /* add the MAC header info */ + proto_item_append_text(parent_item, "%s", type2_fb_type_abbrv[fb_type]); + /* process the feedback header based on the fb type */ + switch (fb_type) + { + case CQI_MIMO_FB: + /* Decode and display the CQI and MIMO feedback */ + /* CQI feedback type */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cqi_fb_type, tvb, offset, 2, ENC_BIG_ENDIAN); + /* CQI payload */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cqi_payload, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cqi_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case DL_AVG_CINR: + /* Decode and display the DL average CINR feedback */ + /* DL average CINR payload */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_dl_ave_cinr, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_dl_ave_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case MIMO_COEF_FB: + /* Decode and display the MIMO coefficients feedback */ + /* number of index */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_coef_ni, tvb, offset, 2, ENC_BIG_ENDIAN); + /* occurrences of antenna index */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_coef_ai, tvb, offset, 2, ENC_BIG_ENDIAN); + /* MIMO coefficients */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_coef, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_coef_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* Decode and display the CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case PREF_DL_CHAN_DIUC_FB: + /* Decode and display the Preffed DL Channel DIUC feedback */ + /* Preferred DIUC */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_dl_chan_diuc, tvb, offset, 2, ENC_BIG_ENDIAN); + /* DCD Change Count */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_dl_chan_dcd, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_dl_chan_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case UL_TX_PWR: + /* Decode and display the UL TX Power feedback */ + /* UL TX Power */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_ul_tx_pwr, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_ul_tx_pwr_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case PHY_CHAN_FB: + /* Decode and display the PHY Channel feedback */ + /* Preffed DIUC */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_phy_diuc, tvb, offset, 2, ENC_BIG_ENDIAN); + /* UL TX Power */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_phy_ul_tx_pwr, tvb, offset, 2, ENC_BIG_ENDIAN); + /* UL Headroom */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_phy_ul_hdrm, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_phy_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case AMC_BAND_BITMAP: + /* Decode and display the AMC Band CQIs feedback */ + /* AMC Band Indication Bitmap */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_amc_bitmap, tvb, offset, 2, ENC_BIG_ENDIAN); + /* AMC CQI 1 */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_amc_cqi_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* AMC CQI 2 */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_amc_cqi_2, tvb, offset, 2, ENC_BIG_ENDIAN); + /* AMC CQI 3 */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_amc_cqi_3, tvb, offset, 2, ENC_BIG_ENDIAN); + /* AMC CQI 4 */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_amc_cqi_4, tvb, offset, 2, ENC_BIG_ENDIAN); +#if 0 + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } +#endif + break; + case SHORT_PRECODE_FB: + /* Decode and display the Life Span of Short-term precoding feedback */ + /* Life Span */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_life_span, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_life_span_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case MULTI_TYPES_FB: + /* Decode and display the Multi types of feedback */ + /* Number of feedback types */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mt_num_fb_types, tvb, offset, 4, ENC_BIG_ENDIAN); + /* Occurrences of feedback type */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mt_occu_fb_type, tvb, offset, 4, ENC_BIG_ENDIAN); + /* feedback contents */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mt_fb_contents, tvb, offset, 4, ENC_BIG_ENDIAN); +#if 0 + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } +#endif + break; + case LONG_PRECODE_FB: + /* Decode and display the Long-term precoding feedback */ + /* Feedback of index */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_lt_id_fb, tvb, offset, 2, ENC_BIG_ENDIAN); + /* rank of prrecoding codebook */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_lt_rank, tvb, offset, 2, ENC_BIG_ENDIAN); + /* EFC and QAM feedback */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_lt_fec_qam, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_lt_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case COMB_DL_AVG_CINR: + /* Decode and display the Combined DL Average CINR feedback */ + /* Combined DL average CINR of Active BSs */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_comb_dl_ave, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_comb_dl_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case MIMO_CHAN_FB: + /* Decode and display the second byte of the header */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_diuc, tvb, (offset+1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_pbwi, tvb, (offset+1), 1, ENC_BIG_ENDIAN); + /* Decode and display the 3rd to 5th bytes of the header */ + /* Decode and display the SLPB */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_slpb, tvb, offset, 3, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* Decode and display the BPRI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_bpri_cid, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_cid, tvb, offset, 3, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* Decode and display the BPRI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_bpri, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the CTI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_cti, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the AI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_ai_0, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_ai_1, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_ai_2, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_ai_3, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the MI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_mi, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the CT */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_ct, tvb, offset, 3, ENC_BIG_ENDIAN); + /* Decode and display the CQI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_mimo_cqi, tvb, offset, 3, ENC_BIG_ENDIAN); + } + break; + case CINR_FB: + /* Decode and display the CINRC feedback */ + /* CINR Mean */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cinr_mean, tvb, offset, 2, ENC_BIG_ENDIAN); + /* CINR Standard Deviation */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cinr_devi, tvb, offset, 2, ENC_BIG_ENDIAN); + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* Decode and display the CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + case CL_MIMO_FB: + /* Get the MIMO type */ + mimo_type = ((tvb_get_guint8(tvb, offset) & 0xC0) >> 6); + /* Decode and display the MIMO type */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_type, tvb, offset, 2, ENC_BIG_ENDIAN); + if(mimo_type == 1) + { + /* Decode and display the umber of streams */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_streams, tvb, offset, 2, ENC_BIG_ENDIAN); + /* Decode and display the antenna selection option index */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_ant_sel, tvb, offset, 2, ENC_BIG_ENDIAN); + /* Decode and display the average CQI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_cqi_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_rsv_1, tvb, offset, 2, ENC_BIG_ENDIAN); + } + else if(mimo_type == 2) + { + /* Decode and display the umber of streams */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_streams, tvb, offset, 2, ENC_BIG_ENDIAN); + /* Decode and display the antenna selection option index */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_codebook_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* Decode and display the average CQI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_cqi_2, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_rsv_2, tvb, offset, 2, ENC_BIG_ENDIAN); + } + else + { + /* Decode and display the antenna grouping index */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_ant_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* Decode and display the average CQI */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_cqi, tvb, offset, 2, ENC_BIG_ENDIAN); + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cl_mimo_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + } + /* check the CII field */ + if(cii_bit) + { /* with CID */ + /* Decode and display the CID */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + else + { /* without CID */ + /* reserved */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_no_cid, tvb, (offset+2), 2, ENC_BIG_ENDIAN); + } + break; + default: + break; + } + /* Decode and display the HCS */ + proto_tree_add_item(ti_tree, hf_mac_header_type_2_hcs, tvb, (offset+4), 1, ENC_BIG_ENDIAN); + } + else + { + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Error - Undefined Type"); + } + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Header Type II Protocol and Dissector */ +void wimax_proto_register_mac_header_type_2(void) +{ + /* MAC HEADER TYPE II display */ + static hf_register_info hf[] = + { + { + &hf_mac_header_type_2_value_bytes, + { + "Values", "wmx.type2ValueBytes", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_ht, + { + "MAC Header Type", "wmx.type2Ht", + FT_UINT8, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_HT, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_ec, + { + "MAC Encryption Control", "wmx.type2Ec", + FT_UINT8, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_EC, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_type, + { + "MAC Sub-Type", "wmx.type2Type", + FT_UINT8, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_TYPE, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cii, + { + "CID Inclusion Indication", "wmx.type2Cii", + FT_UINT8, BASE_DEC, VALS(cii_msgs), WIMAX_MAC_HEADER_TYPE_2_CII, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_fb_type, + { + "Feedback Type", "wmx.type2FbType", + FT_UINT8, BASE_DEC, VALS(fb_types), WIMAX_MAC_HEADER_TYPE_2_FB_TYPE, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cqi_fb_type, + { + "Mimo Feedback Type", "wmx.type2MimoFbType", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CQI_FB_TYPE, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cqi_payload, + { + "CQI and Mimo Feedback Payload", "wmx.type2MimoFbPayload", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CQI_PAYLOAD, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cqi_rsv, + { + "Reserved", "wmx.type2MimoFbRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CQI_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_dl_ave_cinr, + { + "DL Average CINR", "wmx.type2DlAveCinr", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_DL_AVE_CINR, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_dl_ave_rsv, + { + "Reserved", "wmx.type2DlAveRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_DL_AVE_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_coef_ni, + { + "Number of Index", "wmx.type2MimoCoefNi", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_MIMO_COEF_NI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_coef_ai, + { + "Occurrences of Antenna Index", "wmx.type2MimoCoefAi", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_MIMO_COEF_AI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_coef, + { + "MIMO Coefficients", "wmx.type2MimoCoef", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_MIMO_COEF, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_coef_rsv, + { + "Reserved", "wmx.type2MimoCoefRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_MIMO_COEF_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_dl_chan_diuc, + { + "Preferred DIUC", "wmx.type2DlChanDiuc", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_DL_CHAN_DIUC, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_dl_chan_dcd, + { + "DCD Change Count", "wmx.type2DlChanDcd", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_DL_CHAN_DCD, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_dl_chan_rsv, + { + "Reserved", "wmx.type2DlChanRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_DL_CHAN_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_ul_tx_pwr, + { + "UL TX Power", "wmx.type2UlTxPwr", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_UL_TX_PWR, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_ul_tx_pwr_rsv, + { + "Reserved", "wmx.type2UlTxPwrRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_UL_TX_PWR_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_phy_diuc, + { + "Preferred DIUC Index", "wmx.type2PhyDiuc", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_PHY_DIUC, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_phy_ul_tx_pwr, + { + "UL TX Power", "wmx.type2PhyUlTxPwr", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_PHY_UL_TX_PWR, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_phy_ul_hdrm, + { + "UL Headroom", "wmx.type2PhyHdRm", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_PHY_UL_HDRM, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_phy_rsv, + { + "Reserved", "wmx.type2PhyRsv", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_PHY_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_amc_bitmap, + { + "AMC Band Indication Bitmap", "wmx.type2AmcBitmap", + FT_UINT32, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_AMC_BITMAP, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_amc_cqi_1, + { + "CQI 1", "wmx.type2AmcCqi1", + FT_UINT32, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_AMC_CQI_1, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_amc_cqi_2, + { + "CQI 2", "wmx.type2AmcCqi2", + FT_UINT32, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_AMC_CQI_2, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_amc_cqi_3, + { + "CQI 3", "wmx.type2AmcCqi3", + FT_UINT32, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_AMC_CQI_3, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_amc_cqi_4, + { + "CQI 4", "wmx.type2AmcCqi4", + FT_UINT32, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_AMC_CQI_4, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_life_span, + { + "Life Span of Short-term", "wmx.type2LifeSpan", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_LIFE_SPAN, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_life_span_rsv, + { + "Reserved", "wmx.type2LifeSpanRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_LIFE_SPAN_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mt_num_fb_types, + { + "Number of Feedback Types", "wmx.type2MtNumFbTypes", + FT_UINT32, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_MT_NUM_FB_TYPES, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mt_occu_fb_type, + { + "Occurrences of Feedback Type", "wmx.type2MtOccuFbType", + FT_UINT32, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_MT_OCCU_FB_TYPE, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mt_fb_contents, + { + "Number of Feedback Types", "wmx.type2MtNumFbTypes", + FT_UINT32, BASE_HEX, NULL, WIMAX_MAC_HEADER_TYPE_2_MT_FB_CONTENTS, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_lt_id_fb, + { + "Long-term Feedback Index", "wmx.type2LtFbId", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_LT_ID_FB, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_lt_rank, + { + "Rank of Precoding Codebook", "wmx.type2LtRank", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_LT_RANK, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_lt_fec_qam, + { + "FEC and QAM", "wmx.type2LtFecQam", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_LT_FEC_QAM, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_lt_rsv, + { + "Reserved", "wmx.type2LtFbId", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_LT_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_comb_dl_ave, + { + "Combined DL Average CINR of Active BSs", "wmx.type2CombDlAve", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_COMB_DL_AVE, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_comb_dl_rsv, + { + "Reserved", "wmx.type2CombDlRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_COMB_DL_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_diuc, + { + "Preferred DIUC Index", "wmx.type2MimoDiuc", + FT_UINT8, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_DIUC, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_pbwi, + { + "Preferred Bandwidth Index", "wmx.type2MimoPbwi", + FT_UINT8, BASE_DEC, VALS(pbwi_table), WIMAX_MAC_HEADER_TYPE_2_PBWI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_slpb, + { + "Starting Location of Preferred Bandwidth", "wmx.type2MimoSlpb", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_SLPB, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_bpri_cid, + { + "Burst Profile Ranking Indicator with CID", "wmx.type2MimoBpriCid", + FT_UINT24, BASE_HEX, VALS(bpri_table), WIMAX_MAC_HEADER_TYPE_2_PBRI_CID, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_cid, + { + "Connection ID", "wmx.type2MimoCid", + FT_UINT24, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CID, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_bpri, + { + "Burst Profile Ranking Indicator without CID", "wmx.type2MimoBpri", + FT_UINT24, BASE_HEX, VALS(bpri_table), WIMAX_MAC_HEADER_TYPE_2_PBRI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_cti, + { + "Coherent Time Index", "wmx.type2MimoCti", + FT_UINT24, BASE_HEX, VALS(cti_table), WIMAX_MAC_HEADER_TYPE_2_CTI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_ai_0, + { + "Antenna 0 Indication", "wmx.type2MimoAi", + FT_UINT24, BASE_HEX, VALS(ai_msgs), WIMAX_MAC_HEADER_TYPE_2_AI_0, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_ai_1, + { + "Antenna 1 Indication", "wmx.type2MimoAi", + FT_UINT24, BASE_HEX, VALS(ai_msgs), WIMAX_MAC_HEADER_TYPE_2_AI_1, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_ai_2, + { + "Antenna 2 Indication", "wmx.type2MimoAi", + FT_UINT24, BASE_HEX, VALS(ai_msgs), WIMAX_MAC_HEADER_TYPE_2_AI_2, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_ai_3, + { + "Antenna 3 Indication", "wmx.type2MimoAi", + FT_UINT24, BASE_HEX, VALS(ai_msgs), WIMAX_MAC_HEADER_TYPE_2_AI_3, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_mi, + { + "MS Matrix Indicator", "wmx.type2MimoMi", + FT_UINT24, BASE_HEX, VALS(mi_table), WIMAX_MAC_HEADER_TYPE_2_MI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_ct, + { + "CQI Type", "wmx.type2MimoCt", + FT_UINT24, BASE_HEX, VALS(ct_msgs), WIMAX_MAC_HEADER_TYPE_2_CT, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_mimo_cqi, + { + "CQI Feedback", "wmx.type2MimoCqi", + FT_UINT24, BASE_HEX, NULL, WIMAX_MAC_HEADER_TYPE_2_CQI, + NULL, HFILL + } + }, + { &hf_mac_header_type_2_cinr_mean, + { + "CINR Mean", "wmx.type2CinrMean", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cinr_devi, + { + "CINR Standard Deviation", "wmx.type2CinrDevi", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_type, + { + "Closed-Loop MIMO Type", "wmx.type2ClMimoType", + FT_UINT16, BASE_HEX, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_TYPE, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_ant_id, + { + "Antenna Grouping Index", "wmx.type2ClMimoAntId", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_ANT_ID, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_cqi, + { + "Average CQI", "wmx.type2ClMimoCqi", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_CQI, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_cqi_1, + { + "Average CQI", "wmx.type2ClMimoCqi", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_CQI_1, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_cqi_2, + { + "Average CQI", "wmx.type2ClMimoCqi", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_CQI_2, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_rsv, + { + "Reserved", "wmx.type2ClMimoRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_RSV, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_rsv_1, + { + "Reserved", "wmx.type2ClMimoRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_RSV_1, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_rsv_2, + { + "Reserved", "wmx.type2ClMimoRsv", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_RSV_2, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_streams, + { + "Number of Streams", "wmx.type2ClMimoStreams", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_STREAMS, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_ant_sel, + { + "Antenna Selection Option Index", "wmx.type2ClMimoAntSel", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_ANT_SEL, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cl_mimo_codebook_id, + { + "Codebook Index", "wmx.type2ClMimoCodeBkId", + FT_UINT16, BASE_DEC, NULL, WIMAX_MAC_HEADER_TYPE_2_CL_MIMO_CODEBOOK_ID, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_cid, + { + "Connection ID", "wmx.type2Cid", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_no_cid, + { + "Reserved", "wmx.type2NoCid", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_header_type_2_hcs, + { + "Header Check Sequence", "wmx.type2Hcs", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_header_type_2_decoder, + }; + + proto_mac_header_type_2_decoder = proto_mac_header_generic_decoder; + + proto_register_field_array(proto_mac_header_type_2_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("mac_header_type_2_handler", dissect_mac_header_type_2_decoder, proto_mac_header_type_2_decoder); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/mac_mgmt_msg_decoder.c b/plugins/epan/wimax/mac_mgmt_msg_decoder.c new file mode 100644 index 00000000..57c03977 --- /dev/null +++ b/plugins/epan/wimax/mac_mgmt_msg_decoder.c @@ -0,0 +1,367 @@ +/* mac_mgmt_msg_decoder.c + * WiMax MAC Management Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include +#include "wimax_mac.h" + +void proto_register_mac_mgmt_msg(void); +void proto_reg_handoff_mac_mgmt_msg(void); + +static gint proto_mac_mgmt_msg_decoder = -1; +static gint ett_mac_mgmt_msg_decoder = -1; + +static gint hf_mac_mgmt_msg_type = -1; +static gint hf_mac_mgmt_msg_values = -1; + +static expert_field ei_empty_payload = EI_INIT; + +static dissector_table_t subdissector_message_table; + +/* WIMAX MAC Management message type info */ +static const value_string mgt_msg_abbrv_vals[] = { + { MAC_MGMT_MSG_UCD, "UCD" }, + { MAC_MGMT_MSG_DCD, "DCD" }, + { MAC_MGMT_MSG_DL_MAP, "DL-MAP" }, + { MAC_MGMT_MSG_UL_MAP, "UL-MAP" }, + { MAC_MGMT_MSG_RNG_REQ, "RNG-REQ" }, + { MAC_MGMT_MSG_RNG_RSP, "RNG-RSP" }, + { MAC_MGMT_MSG_REG_REQ, "REG-REQ" }, + { MAC_MGMT_MSG_REG_RSP, "REG-RSP" }, + { 8, "Reserved8" }, + { MAC_MGMT_MSG_PKM_REQ, "PKM-REQ" }, + { MAC_MGMT_MSG_PKM_RSP, "PKM-RSP" }, + { MAC_MGMT_MSG_DSA_REQ, "DSA-REQ" }, + { MAC_MGMT_MSG_DSA_RSP, "DSA-RSP" }, + { MAC_MGMT_MSG_DSA_ACK, "DSA-ACK" }, + { MAC_MGMT_MSG_DSC_REQ, "DSC-REQ" }, + { MAC_MGMT_MSG_DSC_RSP, "DSC-RSP" }, + { MAC_MGMT_MSG_DSC_ACK, "DSC-ACK" }, + { MAC_MGMT_MSG_DSD_REQ, "DSD-REQ" }, + { MAC_MGMT_MSG_DSD_RSP, "DSD-RSP" }, + { 19, "Reserved19" }, + { 20, "Reserved20" }, + { MAC_MGMT_MSG_MCA_REQ, "MCA-REQ" }, + { MAC_MGMT_MSG_MCA_RSP, "MCA-RSP" }, + { MAC_MGMT_MSG_DBPC_REQ, "DBPC-REQ" }, + { MAC_MGMT_MSG_DBPC_RSP, "DBPC-RSP" }, + { MAC_MGMT_MSG_RES_CMD, "RES-CMD" }, + { MAC_MGMT_MSG_SBC_REQ, "SBC-REQ" }, + { MAC_MGMT_MSG_SBC_RSP, "SBC-RSP" }, + { MAC_MGMT_MSG_CLK_CMP, "CLK-CMP" }, + { MAC_MGMT_MSG_DREG_CMD, "DREG-CMD" }, + { MAC_MGMT_MSG_DSX_RVD, "DSX-RVD" }, + { MAC_MGMT_MSG_TFTP_CPLT, "TFTP-CPLT" }, + { MAC_MGMT_MSG_TFTP_RSP, "TFTP-RSP" }, + { MAC_MGMT_MSG_ARQ_FEEDBACK, "ARQ-FEEDBACK" }, + { MAC_MGMT_MSG_ARQ_DISCARD, "ARQ-DISCARD" }, + { MAC_MGMT_MSG_ARQ_RESET, "ARQ-RESET" }, + { MAC_MGMT_MSG_REP_REQ, "REP-REQ" }, + { MAC_MGMT_MSG_REP_RSP, "REP-RSP" }, + { MAC_MGMT_MSG_FPC, "FPC" }, + { MAC_MGMT_MSG_MSH_NCFG, "MSH-NCFG" }, + { MAC_MGMT_MSG_MSH_NENT, "MSH-NENT" }, + { MAC_MGMT_MSG_MSH_DSCH, "MSH-DSCH" }, + { MAC_MGMT_MSG_MSH_CSCH, "MSH-CSCH" }, + { MAC_MGMT_MSG_MSH_CSCF, "MSH-CSCF" }, + { MAC_MGMT_MSG_AAS_FBCK_REQ, "AAS-FBCK_REQ" }, + { MAC_MGMT_MSG_AAS_FBCK_RSP, "AAS-FBCK_RSP" }, + { MAC_MGMT_MSG_AAS_BEAM_SELECT, "AAS-BEAM_SELECT" }, + { MAC_MGMT_MSG_AAS_BEAM_REQ, "AAS-BEAM_REQ" }, + { MAC_MGMT_MSG_AAS_BEAM_RSP, "AAS-BEAM_RSP" }, + { MAC_MGMT_MSG_DREG_REQ, "DREG-REQ" }, + { MAC_MGMT_MSG_MOB_SLP_REQ, "MOB-SLP-REQ" }, + { MAC_MGMT_MSG_MOB_SLP_RSP, "MOB-SLP-RSP" }, + { MAC_MGMT_MSG_MOB_TRF_IND, "MOB-TRF-IND" }, + { MAC_MGMT_MSG_MOB_NBR_ADV, "MOB-NBR-ADV" }, + { MAC_MGMT_MSG_MOB_SCN_REQ, "MOB-SCN-REQ" }, + { MAC_MGMT_MSG_MOB_SCN_RSP, "MOB-SCN-RSP" }, + { MAC_MGMT_MSG_MOB_BSHO_REQ, "MOB-BSHO-REQ" }, + { MAC_MGMT_MSG_MOB_MSHO_REQ, "MOB-MSHO-REQ" }, + { MAC_MGMT_MSG_MOB_BSHO_RSP, "MOB-BSHO-RSP" }, + { MAC_MGMT_MSG_MOB_HO_IND, "MOB-HO-IND" }, + { MAC_MGMT_MSG_MOB_SCN_REP, "MOB-SCN-REP" }, + { MAC_MGMT_MSG_MOB_PAG_ADV, "MOB-PAG-ADV" }, + { MAC_MGMT_MSG_MBS_MAP, "MBS-MAP" }, + { MAC_MGMT_MSG_PMC_REQ, "PMC-REQ" }, + { MAC_MGMT_MSG_PMC_RSP, "PMC-RSP" }, + { MAC_MGMT_MSG_PRC_LT_CTRL, "PRC-LT-CTRL" }, + { MAC_MGMT_MSG_MOB_ASC_REP, "MOB-ASC-REP" }, + + { 0, NULL } +}; + +static value_string_ext mgt_msg_abbrv_vals_ext = VALUE_STRING_EXT_INIT(mgt_msg_abbrv_vals); + +static int dissect_mac_mgmt_msg_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint message_type; + proto_item *message_item; + proto_tree *message_tree; + const char* mgt_msg_str; + + message_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_decoder, tvb, offset, -1, + "MAC Management Message Type (%u bytes)", tvb_reported_length(tvb)); + message_tree = proto_item_add_subtree(message_item, ett_mac_mgmt_msg_decoder); + + if (tvb_reported_length(tvb) == 0) + { + expert_add_info(pinfo, message_item, &ei_empty_payload); + return tvb_captured_length(tvb); + } + + /* Get the payload type */ + message_type = tvb_get_guint8(tvb, offset); + proto_tree_add_item(message_tree, hf_mac_mgmt_msg_type, tvb, offset, 1, ENC_NA); + mgt_msg_str = val_to_str_ext_const(message_type, &mgt_msg_abbrv_vals_ext, "Unknown"); + + /* Display message type in Info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", mgt_msg_str); + + /* add the payload type into the info column */ + if (try_val_to_str_ext(message_type, &mgt_msg_abbrv_vals_ext) == NULL) + { + /* display the MAC payload in Hex */ + proto_tree_add_item(message_tree, hf_mac_mgmt_msg_values, tvb, offset, -1, ENC_NA); + return 1; + } + + /* add the MAC header info to parent*/ + proto_item_append_text(proto_tree_get_parent(tree), ", %s", mgt_msg_str); + + /* Decode and display the MAC payload */ + if (!dissector_try_uint(subdissector_message_table, message_type, + tvb_new_subset_remaining(tvb, 1), pinfo, tree)) + { + proto_tree_add_item(message_tree, hf_mac_mgmt_msg_values, tvb, offset, -1, ENC_NA); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg(void) +{ + /* Payload display */ + static hf_register_info hf[] = + { + { + &hf_mac_mgmt_msg_type, + { + "MAC Management Message Type", "wmx.macmgtmsgtype", + FT_UINT8, BASE_DEC | BASE_EXT_STRING, &mgt_msg_abbrv_vals_ext, 0x0, + NULL, HFILL + } + }, + { + &hf_mac_mgmt_msg_values, + { + "Values", "wmx.values", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_decoder, + }; + + static ei_register_info ei[] = { + { &ei_empty_payload, { "wmx.empty_payload", PI_PROTOCOL, PI_ERROR, "Error: Mac payload tvb is empty !", EXPFILL }}, + }; + + expert_module_t* expert_mac_mgmt; + + proto_mac_mgmt_msg_decoder = proto_register_protocol ( + "WiMax MAC Management Message", /* name */ + "MGMT MSG", /* short name */ + "wmx.mgmt" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_mac_mgmt = expert_register_protocol(proto_mac_mgmt_msg_decoder); + expert_register_field_array(expert_mac_mgmt, ei, array_length(ei)); + + subdissector_message_table = register_dissector_table("wmx.mgmtmsg", + "WiMax MAC Management Message", proto_mac_mgmt_msg_decoder, FT_UINT8, BASE_DEC); + + /* Register dissector by name */ + register_dissector("wmx_mac_mgmt_msg_decoder", dissect_mac_mgmt_msg_decoder, + proto_mac_mgmt_msg_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg(void) +{ + dissector_handle_t mgt_msg_handle; + + /* Find the dissectors that appear to be supported through a third-party plugin + Keep here until third-party plugin can register through the new "wmx.mgmtmsg" + subdissector */ + + /* find the Multicast Assignment request message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mca_req_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MCA_REQ, mgt_msg_handle ); + + /* find the Multicast Assignment response message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mca_rsp_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MCA_RSP, mgt_msg_handle ); + + /* find the DL Burst Profile Change request message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_dbpc_req_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_DBPC_REQ, mgt_msg_handle ); + + /* find the DL Burst Profile Change response message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_dbpc_rsp_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_DBPC_RSP, mgt_msg_handle ); + + /* find the Config File TFTP Complete message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_tftp_cplt_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_TFTP_CPLT, mgt_msg_handle ); + + /* find the Config File TFTP Complete response message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_tftp_rsp_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_TFTP_RSP, mgt_msg_handle ); + + /* find the Mesh Network Configuration message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_ncfg_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MSH_NCFG, mgt_msg_handle ); + + /* find the Mesh Network Entry message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_nent_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MSH_NENT, mgt_msg_handle ); + + /* find the Mesh Distributed Schedule message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_dsch_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MSH_DSCH, mgt_msg_handle ); + + /* find the Mesh Centralized Schedule message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_csch_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MSH_CSCH, mgt_msg_handle ); + + /* find the Mesh Centralized Schedule Configuration message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_cscf_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MSH_CSCF, mgt_msg_handle ); + + /* find the AAS Beam request message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_aas_beam_req_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_AAS_BEAM_REQ, mgt_msg_handle ); + + /* find the AAS Beam response message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_aas_beam_rsp_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_AAS_BEAM_RSP, mgt_msg_handle ); + + /* find the Sleep Request message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_slp_req_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_SLP_REQ, mgt_msg_handle ); + + /* find the Sleep Response message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_slp_rsp_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_SLP_RSP, mgt_msg_handle ); + + /* find the Traffic Indication message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_trf_ind_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_TRF_IND, mgt_msg_handle ); + + /* find the Neighbor Advertisement message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_nbr_adv_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_NBR_ADV, mgt_msg_handle ); + + /* find the Scanning Interval Allocation Request message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_scn_req_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_SCN_REQ, mgt_msg_handle ); + + /* find the Scanning Interval Allocation Response message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_scn_rsp_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_SCN_RSP, mgt_msg_handle ); + + /* find the BS HO Request message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_bsho_req_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_BSHO_REQ, mgt_msg_handle ); + + /* find the MS HO Request message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_msho_req_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_MSHO_REQ, mgt_msg_handle ); + + /* find the BS HO Response message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_bsho_rsp_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_BSHO_RSP, mgt_msg_handle ); + + /* find the HO Indication message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_ho_ind_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_HO_IND, mgt_msg_handle ); + + /* find the Scanning Result Report message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_scn_rep_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_SCN_REP, mgt_msg_handle ); + + /* find the BS Broadcast Paging message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_pag_adv_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_PAG_ADV, mgt_msg_handle ); + + /* find the MBS MAP message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mbs_map_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MBS_MAP, mgt_msg_handle ); + + /* find the Association Result Report message handler */ + mgt_msg_handle = find_dissector("mac_mgmt_msg_mob_asc_rep_handler"); + if (mgt_msg_handle) + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_MOB_ASC_REP, mgt_msg_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: + */ diff --git a/plugins/epan/wimax/msg_aas_beam.c b/plugins/epan/wimax/msg_aas_beam.c new file mode 100644 index 00000000..1e6166fd --- /dev/null +++ b/plugins/epan/wimax/msg_aas_beam.c @@ -0,0 +1,340 @@ +/* msg_aas_beam.c + * WiMax MAC Management AAS-BEAM-SELECT/REQ/RSP Messages decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#define OFDM /* disable it if not supporting OFDM */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_mac.h" + +extern gint proto_mac_mgmt_msg_aas_fbck_decoder; + +#define AAS_BEAM_SELECT_AAS_BEAM_INDEX_MASK 0xFC +#define AAS_BEAM_SELECT_RESERVED_MASK 0x03 +#define AAS_BEAM_FEEDBACK_REQUEST_NUMBER_MASK 0xE0 +#define AAS_BEAM_MEASUREMENT_REPORT_TYPE_MASK 0x18 +#define AAS_BEAM_RESOLUTION_PARAMETER_MASK 0x07 + +#define AAS_BEAM_BEAM_BIT_MASK_MASK 0xF0 +#define AAS_BEAM_RESERVED_MASK 0x0F + +void proto_register_mac_mgmt_msg_aas_beam(void); +void proto_reg_handoff_mac_mgmt_msg_aas_beam(void); + +static dissector_handle_t aas_handle; + +static gint proto_mac_mgmt_msg_aas_beam_decoder = -1; +static gint ett_mac_mgmt_msg_aas_beam_select_decoder = -1; +static gint ett_mac_mgmt_msg_aas_beam_req_decoder = -1; +static gint ett_mac_mgmt_msg_aas_beam_rsp_decoder = -1; + +#ifdef OFDM +static const value_string vals_report_types[] = +{ + {0, "BEAM_REP_IE"}, + {0, NULL} +}; + +static const value_string vals_resolution_parameter[] = +{ + {0, "report every 4th subcarrier"}, + {1, "report every 8th subcarrier"}, + {2, "report every 16th subcarrier"}, + {3, "report every 32nd subcarrier"}, + {4, "report every 64th subcarrier"}, + {0, NULL} +}; +#endif + +/* fix fields */ +/* static gint hf_aas_beam_unknown_type = -1; */ +static gint hf_aas_beam_select_index = -1; +static gint hf_aas_beam_select_reserved = -1; +#ifdef OFDM +static gint hf_aas_beam_frame_number = -1; +static gint hf_aas_beam_feedback_request_number = -1; +static gint hf_aas_beam_measurement_report_type = -1; +static gint hf_aas_beam_resolution_parameter = -1; +static gint hf_aas_beam_beam_bit_mask = -1; +static int hf_aas_beam_freq_value_re = -1; +static int hf_aas_beam_freq_value_im = -1; +static int hf_aas_beam_rssi_value = -1; +static int hf_aas_beam_cinr_value = -1; +#endif + + +static int dissect_mac_mgmt_msg_aas_beam_select_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *aas_beam_item; + proto_tree *aas_beam_tree; + + { /* we are being asked for details */ + + /* display MAC message type */ + aas_beam_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_aas_beam_decoder, tvb, offset, -1, "AAS Beam Select (AAS-BEAM-SELECT)"); + /* add subtree */ + aas_beam_tree = proto_item_add_subtree(aas_beam_item, ett_mac_mgmt_msg_aas_beam_select_decoder); + + /* Decode and display the AAS-BEAM-SELECT message body */ + /* display the AAS Beam Index */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_select_index, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the reserved fields */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_select_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +#ifdef OFDM +static int dissect_mac_mgmt_msg_aas_beam_req_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *aas_beam_item; + proto_tree *aas_beam_tree; + + { /* we are being asked for details */ + + /* display MAC message type */ + aas_beam_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_aas_beam_decoder, tvb, offset, -1, "AAS Beam Request (AAS-BEAM-REQ)"); + /* add subtree */ + aas_beam_tree = proto_item_add_subtree(aas_beam_item, ett_mac_mgmt_msg_aas_beam_req_decoder); + + /* Decode and display the AAS-BEAM-REQ message body */ + /* display the Frame Number */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the Feedback Request Number */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_feedback_request_number, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Measurement Report Type */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_measurement_report_type, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Resolution Parameter */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_resolution_parameter, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the Beam Bit mask */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_beam_bit_mask, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the reserved fields */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_select_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +static int dissect_mac_mgmt_msg_aas_beam_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len, report_type; + guint number_of_frequencies, indx; + proto_item *aas_beam_item; + proto_tree *aas_beam_tree; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC message type */ + aas_beam_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_aas_beam_decoder, tvb, offset, -1, "AAS Beam Response (AAS-BEAM-RSP)"); + /* add subtree */ + aas_beam_tree = proto_item_add_subtree(aas_beam_item, ett_mac_mgmt_msg_aas_beam_rsp_decoder); + + /* Decode and display the AAS-BEAM-RSP message body */ + /* display the Frame Number */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* get the Measurement Report Type */ + report_type = tvb_get_guint8(tvb, offset); + /* display the Feedback Request Number */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_feedback_request_number, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Measurement Report Type */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_measurement_report_type, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Resolution Parameter */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_resolution_parameter, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the Beam Bit mask */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_beam_bit_mask, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the reserved fields */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_select_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* check the Measurement Report Type */ + if((report_type & AAS_BEAM_MEASUREMENT_REPORT_TYPE_MASK) == 0) + { + /* calculate the total number of frequencies */ + number_of_frequencies = (tvb_len - offset) / 2 - 1; + /* display the frequency */ + for(indx = 0; indx < number_of_frequencies; indx++) + { /* display the Frequency Value (real part) */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_freq_value_re, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the Frequency Value (imaginary part) */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_freq_value_im, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + } + } + /* display the RSSI Mean Value */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_rssi_value, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the CINR Mean Value */ + proto_tree_add_item(aas_beam_tree, hf_aas_beam_cinr_value, tvb, offset, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} +#endif + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_aas_beam(void) +{ + /* AAS-BEAM display */ + static hf_register_info hf_aas_beam[] = + { + { + &hf_aas_beam_select_index, + { + "AAS Beam Index", "wmx.aas_beam.aas_beam_index", + FT_UINT8, BASE_DEC, NULL, AAS_BEAM_SELECT_AAS_BEAM_INDEX_MASK, NULL, HFILL + } + }, + { + &hf_aas_beam_beam_bit_mask, + { + "Beam Bit Mask", "wmx.aas_beam.beam_bit_mask", + FT_UINT8, BASE_HEX, NULL, AAS_BEAM_BEAM_BIT_MASK_MASK, NULL, HFILL + } + }, +#ifdef OFDM + { + &hf_aas_beam_cinr_value, + { + "CINR Mean Value", "wmx.aas_beam.cinr_mean_value", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_aas_beam_feedback_request_number, + { + "Feedback Request Number", "wmx.aas_beam.feedback_request_number", + FT_UINT8, BASE_DEC, NULL, AAS_BEAM_FEEDBACK_REQUEST_NUMBER_MASK, NULL, HFILL + } + }, + { + &hf_aas_beam_frame_number, + { + "Frame Number", "wmx.aas_beam.frame_number", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_aas_beam_freq_value_im, + { + "Frequency Value (imaginary part)", "wmx.aas_beam.freq_value_im", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_aas_beam_freq_value_re, + { + "Frequency Value (real part)", "wmx.aas_beam.freq_value_re", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_aas_beam_measurement_report_type, + { + "Measurement Report Type", "wmx.aas_beam.measurement_report_type", + FT_UINT8, BASE_DEC, VALS(vals_report_types), AAS_BEAM_MEASUREMENT_REPORT_TYPE_MASK, NULL, HFILL + } + }, + { + &hf_aas_beam_select_reserved, + { + "Reserved", "wmx.aas_beam.reserved", + FT_UINT8, BASE_HEX, NULL, AAS_BEAM_SELECT_RESERVED_MASK, NULL, HFILL + } + }, + { + &hf_aas_beam_resolution_parameter, + { + "Resolution Parameter", "wmx.aas_beam.resolution_parameter", + FT_UINT8, BASE_DEC, VALS(vals_resolution_parameter), AAS_BEAM_RESOLUTION_PARAMETER_MASK, NULL, HFILL + } + }, + { + &hf_aas_beam_rssi_value, + { + "RSSI Mean Value", "wmx.aas_beam.rssi_mean_value", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#endif +#if 0 + { + &hf_aas_beam_unknown_type, + { + "Unknown TLV type", "wmx.aas_beam.unknown_type", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + } +#endif + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_aas_beam_select_decoder, + &ett_mac_mgmt_msg_aas_beam_req_decoder, + &ett_mac_mgmt_msg_aas_beam_rsp_decoder, + }; + + proto_mac_mgmt_msg_aas_beam_decoder = proto_register_protocol ( + "WiMax AAS-BEAM Messages", /* name */ + "WiMax AAS-BEAM", /* short name */ + "wmx.aas_beam" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_aas_beam_decoder, hf_aas_beam, array_length(hf_aas_beam)); + proto_register_subtree_array(ett, array_length(ett)); + + aas_handle = register_dissector("mac_mgmt_msg_aas_beam_select_handler", dissect_mac_mgmt_msg_aas_beam_select_decoder, proto_mac_mgmt_msg_aas_beam_decoder); +#ifdef OFDM + register_dissector("mac_mgmt_msg_aas_beam_req_handler", dissect_mac_mgmt_msg_aas_beam_req_decoder, proto_mac_mgmt_msg_aas_beam_decoder); + register_dissector("mac_mgmt_msg_aas_beam_rsp_handler", dissect_mac_mgmt_msg_aas_beam_rsp_decoder, proto_mac_mgmt_msg_aas_beam_decoder); +#endif +} + +void +proto_reg_handoff_mac_mgmt_msg_aas_beam(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_AAS_BEAM_SELECT, aas_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: + */ diff --git a/plugins/epan/wimax/msg_aas_fbck.c b/plugins/epan/wimax/msg_aas_fbck.c new file mode 100644 index 00000000..31162822 --- /dev/null +++ b/plugins/epan/wimax/msg_aas_fbck.c @@ -0,0 +1,349 @@ +/* msg_aas_beam.c + * WiMax MAC Management AAS-BEAM-SELECT/REQ/RSP Messages decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_mac.h" + +#define OFDMA_AAS_FBCK_REQ_NUMBER_OF_FRAME_MASK 0xFE +#define OFDMA_AAS_FBCK_REQ_DATA_TYPE_MASK 0x01 +#define OFDMA_AAS_FBCK_REQ_FB_REQ_COUNTER_MASK 0xE0 +#define OFDMA_AAS_FBCK_REQ_FB_REQ_RESOLUTION_MASK 0x18 +#define OFDMA_AAS_FBCK_REQ_FB_REQ_RESERVED_MASK 0x07 + +#define OFDMA_AAS_FBCK_REQ_FB_RSP_RESERVED_MASK 0xC0 +#define OFDMA_AAS_FBCK_RSP_DATA_TYPE_MASK 0x20 +#define OFDMA_AAS_FBCK_REQ_FB_RSP_COUNTER_MASK 0x1C +#define OFDMA_AAS_FBCK_REQ_FB_RSP_RESOLUTION_MASK 0x03 + +void proto_register_mac_mgmt_msg_aas_fbck(void); +void proto_reg_handoff_mac_mgmt_msg_aas(void); + +static dissector_handle_t aas_req_handle; +static dissector_handle_t aas_rsp_handle; + +static gint proto_mac_mgmt_msg_aas_fbck_decoder = -1; +static gint ett_mac_mgmt_msg_aas_fbck_req_decoder = -1; +static gint ett_mac_mgmt_msg_aas_fbck_rsp_decoder = -1; + +static const value_string vals_data_types[] = +{ + {0, "measure on downlink preamble only"}, + {1, "measure on downlink data (for this SS) only"}, + {0, NULL} +}; + +static const value_string vals_resolutions_0[] = +{ + {0, "32 subcarriers"}, + {1, "64 subcarriers"}, + {2, "128 subcarriers"}, + {3, "256 subcarriers"}, + {0, NULL} +}; + +static const value_string vals_resolutions_1[] = +{ + {0, "1 subcarrier"}, + {1, "4 subcarriers"}, + {2, "8 subcarriers"}, + {3, "16 subcarriers"}, + {0, NULL} +}; + +/* fix fields */ +/* static int hf_aas_fbck_unknown_type = -1; */ +static int hf_aas_fbck_frame_number = -1; +static int hf_aas_fbck_number_of_frames = -1; +static int hf_aas_fbck_req_data_type = -1; +static int hf_aas_fbck_rsp_data_type = -1; +static int hf_aas_fbck_req_counter = -1; +static int hf_aas_fbck_rsp_counter = -1; +static int hf_aas_fbck_req_resolution_0 = -1; +static int hf_aas_fbck_rsp_resolution_0 = -1; +static int hf_aas_fbck_req_resolution_1 = -1; +static int hf_aas_fbck_rsp_resolution_1 = -1; +static int hf_aas_fbck_req_reserved = -1; +static int hf_aas_fbck_rsp_reserved = -1; +static int hf_aas_fbck_freq_value_re = -1; +static int hf_aas_fbck_freq_value_im = -1; +static int hf_aas_fbck_rssi_value = -1; +static int hf_aas_fbck_cinr_value = -1; + + +static int dissect_mac_mgmt_msg_aas_fbck_req_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint data_type; + proto_item *aas_fbck_item; + proto_tree *aas_fbck_tree; + + { /* we are being asked for details */ + + /* display MAC message type */ + aas_fbck_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_aas_fbck_decoder, tvb, offset, -1, "AAS Channel Feedback Request (AAS-FBCK-REQ)"); + /* add subtree */ + aas_fbck_tree = proto_item_add_subtree(aas_fbck_item, ett_mac_mgmt_msg_aas_fbck_req_decoder); + /* Display the AAS-FBCK-REQ message type */ + + /* Decode and display the AAS-FBCK-REQ message body */ + /* display the Frame Number */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* get the data type */ + data_type = tvb_get_guint8(tvb, offset); + /* display the number of Frames */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_number_of_frames, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Data Type */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_req_data_type, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the Feedback Request Counter */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_req_counter, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Frequency Measurement Resolution */ + if(data_type & OFDMA_AAS_FBCK_REQ_DATA_TYPE_MASK) + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_req_resolution_1, tvb, offset, 1, ENC_BIG_ENDIAN); + else + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_req_resolution_0, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the reserved fields */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_req_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +static int dissect_mac_mgmt_msg_aas_fbck_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len, data_type; + proto_item *aas_fbck_item; + proto_tree *aas_fbck_tree; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC message type */ + aas_fbck_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_aas_fbck_decoder, tvb, offset, -1, "AAS Channel Feedback Response (AAS-FBCK-RSP)"); + /* add subtree */ + aas_fbck_tree = proto_item_add_subtree(aas_fbck_item, ett_mac_mgmt_msg_aas_fbck_rsp_decoder); + /* Display the AAS-FBCK-RSP message type */ + + /* get the data type */ + data_type = tvb_get_guint8(tvb, offset); + /* Decode and display the AAS-FBCK-RSP message body */ + /* display the reserved fields */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_rsp_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Data Type */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_rsp_data_type, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Feedback Request Counter */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_rsp_counter, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Frequency Measurement Resolution */ + if(data_type & OFDMA_AAS_FBCK_RSP_DATA_TYPE_MASK) + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_rsp_resolution_1, tvb, offset, 1, ENC_BIG_ENDIAN); + else + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_rsp_resolution_0, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + for(; offset < (tvb_len - 2); ) + { + /* display the Frequency Value (real part) */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_freq_value_re, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the Frequency Value (imaginary part) */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_freq_value_im, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + } + /* display the RSSI Mean Value */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_rssi_value, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the CINR Mean Value */ + proto_tree_add_item(aas_fbck_tree, hf_aas_fbck_cinr_value, tvb, offset, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_aas_fbck(void) +{ + /* AAS-FBCK display */ + static hf_register_info hf_aas_fbck[] = + { + { + &hf_aas_fbck_cinr_value, + { + "CINR Mean Value", "wmx.aas_fbck.cinr_mean_value", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_aas_fbck_req_counter, + { + "Feedback Request Counter", "wmx.aas_fbck.counter", + FT_UINT8, BASE_DEC, NULL, OFDMA_AAS_FBCK_REQ_FB_REQ_COUNTER_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_frame_number, + { + "Frame Number", "wmx.aas_fbck.frame_number", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_aas_fbck_freq_value_re, + { + "Frequency Value (real part)", "wmx.aas_fbck.freq_value_re", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_aas_fbck_freq_value_im, + { + "Frequency Value (imaginary part)", "wmx.aas_fbck.freq_value_im", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_aas_fbck_number_of_frames, + { + "Number Of Frames", "wmx.aas_fbck.number_of_frames", + FT_UINT8, BASE_DEC, NULL, OFDMA_AAS_FBCK_REQ_NUMBER_OF_FRAME_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_req_resolution_0, + { + "Frequency Measurement Resolution", "wmx.aas_fbck.resolution", + FT_UINT8, BASE_DEC, VALS(vals_resolutions_0), OFDMA_AAS_FBCK_REQ_FB_REQ_RESOLUTION_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_req_resolution_1, + { + "Frequency Measurement Resolution", "wmx.aas_fbck.resolution", + FT_UINT8, BASE_DEC, VALS(vals_resolutions_1), OFDMA_AAS_FBCK_REQ_FB_REQ_RESOLUTION_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_rssi_value, + { + "RSSI Mean Value", "wmx.aas_fbck.rssi_mean_value", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#if 0 + { + &hf_aas_fbck_unknown_type, + { + "Unknown TLV type", "wmx.aas_fbck.unknown_type", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, +#endif + { + &hf_aas_fbck_req_data_type, + { + "Measurement Data Type", "wmx.aas_fbck_req.data_type", + FT_UINT8, BASE_DEC, VALS(vals_data_types), OFDMA_AAS_FBCK_REQ_DATA_TYPE_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_req_reserved, + { + "Reserved", "wmx.aas_fbck_req.reserved", + FT_UINT8, BASE_HEX, NULL, OFDMA_AAS_FBCK_REQ_FB_REQ_RESERVED_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_rsp_counter, + { + "Feedback Request Counter", "wmx.aas_fbck_rsp.counter", + FT_UINT8, BASE_DEC, NULL, OFDMA_AAS_FBCK_REQ_FB_RSP_COUNTER_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_rsp_data_type, + { + "Measurement Data Type", "wmx.aas_fbck_rsp.data_type", + FT_UINT8, BASE_DEC, VALS(vals_data_types), OFDMA_AAS_FBCK_RSP_DATA_TYPE_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_rsp_reserved, + { + "Reserved", "wmx.aas_fbck_rsp.reserved", + FT_UINT8, BASE_HEX, NULL, OFDMA_AAS_FBCK_REQ_FB_RSP_RESERVED_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_rsp_resolution_0, + { + "Frequency Measurement Resolution", "wmx.aas_fbck_rsp.resolution", + FT_UINT8, BASE_DEC, VALS(vals_resolutions_0), OFDMA_AAS_FBCK_REQ_FB_RSP_RESOLUTION_MASK, NULL, HFILL + } + }, + { + &hf_aas_fbck_rsp_resolution_1, + { + "Frequency Measurement Resolution", "wmx.aas_fbck_rsp.resolution", + FT_UINT8, BASE_DEC, VALS(vals_resolutions_1), OFDMA_AAS_FBCK_REQ_FB_RSP_RESOLUTION_MASK, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_aas_fbck_req_decoder, + &ett_mac_mgmt_msg_aas_fbck_rsp_decoder, + }; + + proto_mac_mgmt_msg_aas_fbck_decoder = proto_register_protocol ( + "WiMax AAS-FEEDBACK Messages", /* name */ + "WiMax AAS-FEEDBACK (aas)", /* short name */ + "wmx.aas" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_aas_fbck_decoder, hf_aas_fbck, array_length(hf_aas_fbck)); + proto_register_subtree_array(ett, array_length(ett)); + aas_req_handle = register_dissector("mac_mgmt_msg_aas_feedback_req_handler", dissect_mac_mgmt_msg_aas_fbck_req_decoder, proto_mac_mgmt_msg_aas_fbck_decoder); + aas_rsp_handle = register_dissector("mac_mgmt_msg_aas_feedback_rsp_handler", dissect_mac_mgmt_msg_aas_fbck_rsp_decoder, proto_mac_mgmt_msg_aas_fbck_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_aas(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_AAS_FBCK_REQ, aas_req_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_AAS_FBCK_RSP, aas_rsp_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: + */ diff --git a/plugins/epan/wimax/msg_arq.c b/plugins/epan/wimax/msg_arq.c new file mode 100644 index 00000000..c99a66a2 --- /dev/null +++ b/plugins/epan/wimax/msg_arq.c @@ -0,0 +1,446 @@ +/* msg_arq.c + * WiMax MAC Management ARQ Feedback, Discard, Reset Message decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + + +#include +#include "wimax_mac.h" + +void proto_register_mac_mgmt_msg_arq_feedback(void); +void proto_reg_handoff_mac_mgmt_msg_arq(void); +static int dissect_mac_mgmt_msg_arq_feedback_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); +static int dissect_mac_mgmt_msg_arq_discard_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); +static int dissect_mac_mgmt_msg_arq_reset_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); + +static dissector_handle_t arq_feedback_handle; +static dissector_handle_t arq_discard_handle; +static dissector_handle_t arq_reset_handle; + +static gint proto_mac_mgmt_msg_arq_decoder = -1; + +static gint ett_mac_mgmt_msg_arq_decoder = -1; + +/* Setup protocol subtree array */ +static gint *ett[] = +{ + &ett_mac_mgmt_msg_arq_decoder, +}; + + +/* ARQ fields */ +static gint hf_arq_cid = -1; +static gint hf_arq_last = -1; +static gint hf_arq_ack_type = -1; +static gint hf_ack_type_reserved = -1; +static gint hf_arq_bsn = -1; +static gint hf_arq_num_ack_maps = -1; +static gint hf_arq_selective_map = -1; +static gint hf_arq_seq_format = -1; +static gint hf_arq_0seq_ack_map = -1; +static gint hf_arq_0seq1_len = -1; +static gint hf_arq_0seq2_len = -1; +static gint hf_arq_1seq_ack_map = -1; +static gint hf_arq_1seq1_len = -1; +static gint hf_arq_1seq2_len = -1; +static gint hf_arq_1seq3_len = -1; +static gint hf_arq_reserved = -1; + +static gint hf_arq_discard_cid = -1; +static gint hf_arq_discard_reserved = -1; +static gint hf_arq_discard_bsn = -1; + +static gint hf_arq_reset_cid = -1; +static gint hf_arq_reset_type = -1; +static gint hf_arq_reset_direction = -1; +static gint hf_arq_reset_reserved = -1; + +/* STRING RESOURCES */ + +#if 0 +static const true_false_string tfs_present = { + "present", + "absent" +}; +#endif + +#if 0 +static const true_false_string tfs_rng_req_aas_broadcast = { + "SS cannot receive broadcast messages", + "SS can receive broadcast messages" +}; +#endif + +static const true_false_string tfs_arq_last = { + "Last ARQ feedback IE in the list", + "More ARQ feedback IE in the list" +}; + +static const value_string vals_arq_ack_type[] = { + {0, "Selective ACK entry"}, + {1, "Cumulative ACK entry"}, + {2, "Cumulative with Selective ACK entry"}, + {3, "Cumulative ACK with Block Sequence Ack entry"}, + {0, NULL} +}; + +static const value_string vals_arq_reset_type[] = { + {0, "Original message from Initiator"}, + {1, "Acknowledgment from Responder"}, + {2, "Confirmation from Initiator"}, + {3, "Reserved"}, + {0, NULL} +}; + +static const value_string vals_arq_reset_direction[] = { + {0, "Uplink or downlink"}, + {1, "Uplink"}, + {2, "Downlink"}, + {3, "Reserved"}, + {0, NULL} +}; + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_arq_feedback(void) +{ + /* ARQ fields display */ + static hf_register_info hf[] = + { + { + &hf_arq_ack_type, + { + "ACK Type", "wmx.arq.ack_type", + FT_UINT8, BASE_DEC, VALS(vals_arq_ack_type), 0x60, NULL, HFILL + } + }, + { + &hf_arq_bsn, + { + "BSN", "wmx.arq.bsn", + FT_UINT16, BASE_DEC, NULL, 0x1FFC, NULL, HFILL + } + }, + { + &hf_arq_cid, + { + "Connection ID", "wmx.arq.cid", + FT_UINT16, BASE_DEC, NULL, 0x00, "The ID of the connection being referenced", HFILL + } + }, + { + &hf_arq_discard_bsn, + { + "BSN", "wmx.arq.discard_bsn", + FT_UINT16, BASE_DEC, NULL, 0x07FF, NULL, HFILL + } + }, + { + &hf_arq_discard_cid, + { + "Connection ID", "wmx.arq.discard_cid", + FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_arq_discard_reserved, + { + "Reserved", "wmx.arq.discard_reserved", + FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL + } + }, + { + &hf_arq_last, + { + "LAST", "wmx.arq.last", + FT_BOOLEAN, 8, TFS(&tfs_arq_last), 0x80, NULL, HFILL + } + }, + { + &hf_arq_num_ack_maps, + { + "Number of ACK Maps", "wmx.arq.num_maps", + FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL + } + }, + { + &hf_arq_reserved, + { + "Reserved", "wmx.arq.reserved", + FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_arq_reset_cid, + { + "Connection ID", "wmx.arq.reset_cid", + FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_arq_reset_direction, + { + "Direction", "wmx.arq.reset_direction", + FT_UINT8, BASE_DEC, VALS(vals_arq_reset_direction), 0x30, NULL, HFILL + } + }, + { + &hf_arq_reset_reserved, + { + "Reserved", "wmx.arq.reset_reserved", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, + { + &hf_arq_reset_type, + { + "Type", "wmx.arq.reset_type", + FT_UINT8, BASE_DEC, VALS(vals_arq_reset_type), 0xC0, NULL, HFILL + } + }, + { + &hf_arq_selective_map, + { + "Selective ACK Map", "wmx.arq.selective_map", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_arq_0seq_ack_map, + { + "Sequence ACK Map", "wmx.arq.seq_ack_map", + FT_UINT8, BASE_HEX, NULL, 0x60, NULL, HFILL + } + }, + { + &hf_arq_1seq_ack_map, + { + "Sequence ACK Map", "wmx.arq.seq_ack_map", + FT_UINT8, BASE_HEX, NULL, 0x70, NULL, HFILL + } + }, + { + &hf_arq_seq_format, + { + "Sequence Format", "wmx.arq.seq_format", + FT_UINT8, BASE_DEC, NULL, 0x80, NULL, HFILL + } + }, + { + &hf_arq_0seq1_len, + { + "Sequence 1 Length", "wmx.arq.seq1_len", + FT_UINT16, BASE_DEC, NULL, 0x1F80, NULL, HFILL + } + }, + { + &hf_arq_0seq2_len, + { + "Sequence 2 Length", "wmx.arq.seq2_len", + FT_UINT16, BASE_DEC, NULL, 0x007E, NULL, HFILL + } + }, + { + &hf_arq_1seq1_len, + { + "Sequence 1 Length", "wmx.arq.seq1_len", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, + { + &hf_arq_1seq2_len, + { + "Sequence 2 Length", "wmx.arq.seq2_len", + FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_arq_1seq3_len, + { + "Sequence 3 Length", "wmx.arq.seq3_len", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, + { + &hf_ack_type_reserved, + { + "Reserved", "wmx.ack_type.reserved", + FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL + } + } + }; + + proto_mac_mgmt_msg_arq_decoder = proto_register_protocol ( + "WiMax ARQ Feedback/Discard/Reset Messages", /* name */ + "WiMax ARQ Feedback/Discard/Reset (arq)", /* short name */ + "wmx.arq" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_arq_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + arq_feedback_handle = register_dissector("mac_mgmt_msg_arq_feedback_handler", dissect_mac_mgmt_msg_arq_feedback_decoder, proto_mac_mgmt_msg_arq_decoder); + arq_discard_handle = register_dissector("mac_mgmt_msg_arq_discard_handler", dissect_mac_mgmt_msg_arq_discard_decoder, proto_mac_mgmt_msg_arq_decoder); + arq_reset_handle = register_dissector("mac_mgmt_msg_arq_reset_handler", dissect_mac_mgmt_msg_arq_reset_decoder, proto_mac_mgmt_msg_arq_decoder); +} + +/* Decode ARQ-Feedback messages. */ +static int dissect_mac_mgmt_msg_arq_feedback_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint arq_feedback_ie_count = 0; + guint arq_cid; + gboolean arq_last = FALSE; + guint arq_ack_type; + guint arq_bsn; + guint arq_num_ack_maps; + guint tvb_len; + proto_item *arq_feedback_item; + proto_tree *arq_feedback_tree; + proto_item *arq_fb_item = NULL; + proto_tree *arq_fb_tree = NULL; + proto_item *ti = NULL; + guint i, seq_format; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type ARQ-Feedback */ + arq_feedback_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_arq_decoder, tvb, offset, -1, "MAC Management Message, ARQ-Feedback"); + /* add MAC ARQ Feedback subtree */ + arq_feedback_tree = proto_item_add_subtree(arq_feedback_item, ett_mac_mgmt_msg_arq_decoder); + + while(offset < tvb_len && !arq_last) + { + arq_feedback_ie_count++; + arq_cid = tvb_get_ntohs(tvb, offset); + arq_last = ((tvb_get_guint8(tvb, offset + 2) & 0x80) != 0); + arq_ack_type = (tvb_get_guint8(tvb, offset + 2) & 0x60) >> 5; + arq_bsn = (tvb_get_ntohs(tvb, offset + 2) & 0x1FFC) >> 2; + arq_num_ack_maps = 1 + (tvb_get_guint8(tvb, offset + 3) & 0x03); + + arq_fb_item = proto_tree_add_protocol_format(arq_feedback_tree, proto_mac_mgmt_msg_arq_decoder, tvb, offset, tvb_len, "ARQ_Feedback_IE"); + proto_item_append_text(arq_fb_item, ", CID: %u, %s ARQ feedback IE, %s, BSN: %u", + arq_cid, arq_last ? "Last" : "More", val_to_str_const(arq_ack_type, vals_arq_ack_type, ""), arq_bsn); + if (arq_ack_type != ARQ_CUMULATIVE_ACK_ENTRY) { + proto_item_append_text(arq_fb_item, ", %u ACK Map(s)", arq_num_ack_maps); + } + /* add ARQ Feedback IE subtree */ + arq_fb_tree = proto_item_add_subtree(arq_fb_item, ett_mac_mgmt_msg_arq_decoder); + proto_tree_add_item(arq_fb_tree, hf_arq_cid, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_last, tvb, offset + 2, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_ack_type, tvb, offset + 2, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_bsn, tvb, offset + 2, 2, ENC_BIG_ENDIAN); + if (arq_ack_type != ARQ_CUMULATIVE_ACK_ENTRY) { + ti = proto_tree_add_item(arq_fb_tree, hf_arq_num_ack_maps, tvb, offset + 3, 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti, " (%d map(s))", arq_num_ack_maps); + offset += 2; + + for (i = 0; i < arq_num_ack_maps; i++) { + /* Each ACK Map is 16 bits. */ + offset += 2; + if (arq_ack_type != 3) { + proto_tree_add_item(arq_fb_tree, hf_arq_selective_map, tvb, offset, 2, ENC_BIG_ENDIAN); + } else { + proto_tree_add_item(arq_fb_tree, hf_arq_seq_format, tvb, offset, 1, ENC_BIG_ENDIAN); + seq_format = (tvb_get_guint8(tvb, offset) & 0x80) >> 7; + if (seq_format == 0) { + proto_tree_add_item(arq_fb_tree, hf_arq_0seq_ack_map, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_0seq1_len, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_0seq2_len, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_reserved, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + } else { + proto_tree_add_item(arq_fb_tree, hf_arq_1seq_ack_map, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_1seq1_len, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_1seq2_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_fb_tree, hf_arq_1seq3_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN); + } + } + } + } else { + /* Number of ACK Maps bits are reserved when ACK TYPE == 1 */ + proto_tree_add_item(arq_fb_tree, hf_ack_type_reserved, tvb, offset + 3, 1, ENC_BIG_ENDIAN); + /* update the offset */ + offset += 2; + } + /* update the offset */ + offset += 2; + } + proto_item_append_text(arq_feedback_item, ", %u ARQ_feedback_IE(s)", arq_feedback_ie_count); + } + return tvb_captured_length(tvb); +} + +/* Decode ARQ-Discard messages. */ +static int dissect_mac_mgmt_msg_arq_discard_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + proto_item *arq_discard_item; + proto_tree *arq_discard_tree; + + { /* we are being asked for details */ + + /* display MAC payload type ARQ-Discard */ + arq_discard_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_arq_decoder, tvb, 0, -1, "MAC Management Message, ARQ-Discard"); + /* add MAC ARQ Discard subtree */ + arq_discard_tree = proto_item_add_subtree(arq_discard_item, ett_mac_mgmt_msg_arq_decoder); + + proto_tree_add_item(arq_discard_tree, hf_arq_discard_cid, tvb, 1, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_discard_tree, hf_arq_discard_reserved, tvb, 3, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_discard_tree, hf_arq_discard_bsn, tvb, 3, 2, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +/* Decode ARQ-Reset messages. */ +static int dissect_mac_mgmt_msg_arq_reset_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + proto_item *arq_reset_item; + proto_tree *arq_reset_tree; + + { /* we are being asked for details */ + + /* display MAC payload type ARQ-Reset */ + arq_reset_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_arq_decoder, tvb, 0, -1, "MAC Management Message, ARQ-Reset"); + /* add MAC ARQ Reset subtree */ + arq_reset_tree = proto_item_add_subtree(arq_reset_item, ett_mac_mgmt_msg_arq_decoder); + + proto_tree_add_item(arq_reset_tree, hf_arq_reset_cid, tvb, 1, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_reset_tree, hf_arq_reset_type, tvb, 3, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_reset_tree, hf_arq_reset_direction, tvb, 3, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(arq_reset_tree, hf_arq_reset_reserved, tvb, 3, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +void +proto_reg_handoff_mac_mgmt_msg_arq(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_ARQ_FEEDBACK, arq_feedback_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_ARQ_DISCARD, arq_discard_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_ARQ_RESET, arq_reset_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: + */ diff --git a/plugins/epan/wimax/msg_clk_cmp.c b/plugins/epan/wimax/msg_clk_cmp.c new file mode 100644 index 00000000..3fac08db --- /dev/null +++ b/plugins/epan/wimax/msg_clk_cmp.c @@ -0,0 +1,150 @@ +/* msg_clk_cmp.c + * WiMax MAC Management CLK_CMP Message decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_mac.h" + +void proto_register_mac_mgmt_msg_clk_cmp(void); +void proto_reg_handoff_mac_mgmt_msg_clk_cmp(void); + +static dissector_handle_t clk_cmp_handle; + +static gint proto_mac_mgmt_msg_clk_cmp_decoder = -1; + +static gint ett_mac_mgmt_msg_clk_cmp_decoder = -1; + +/* CLK_CMP fields */ +static gint hf_clk_cmp_clock_count = -1; +static gint hf_clk_cmp_clock_id = -1; +static gint hf_clk_cmp_seq_number = -1; +static gint hf_clk_cmp_comparison_value = -1; +/* static gint hf_clk_cmp_invalid_tlv = -1; */ + + +/* Decode CLK_CMP messages. */ +static int dissect_mac_mgmt_msg_clk_cmp_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint i; + guint clock_count; + proto_item *clk_cmp_item; + proto_tree *clk_cmp_tree; + + { /* we are being asked for details */ + /* display MAC payload type CLK_CMP */ + clk_cmp_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_clk_cmp_decoder, tvb, offset, -1, "Clock Comparison (CLK-CMP)"); + /* add MAC CLK_CMP subtree */ + clk_cmp_tree = proto_item_add_subtree(clk_cmp_item, ett_mac_mgmt_msg_clk_cmp_decoder); + /* get the clock count */ + clock_count = tvb_get_guint8(tvb, offset); + /* display the clock count */ + proto_tree_add_item(clk_cmp_tree, hf_clk_cmp_clock_count, tvb, offset, 1, ENC_BIG_ENDIAN); + /* set the offset for clock comparison */ + offset++; + for (i = 0; i < clock_count; i++ ) + { /* display the Clock ID */ + proto_tree_add_item(clk_cmp_tree, hf_clk_cmp_clock_id, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the sequence number */ + proto_tree_add_item(clk_cmp_tree, hf_clk_cmp_seq_number, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the comparison value */ + proto_tree_add_item(clk_cmp_tree, hf_clk_cmp_comparison_value, tvb, offset++, 1, ENC_BIG_ENDIAN); + } + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_clk_cmp(void) +{ + /* CLK_CMP fields display */ + static hf_register_info hf_clk_cmp[] = + { + { + &hf_clk_cmp_clock_count, + { + "Clock Count", "wmx.clk_cmp.clock_count", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_clk_cmp_clock_id, + { + "Clock ID", "wmx.clk_cmp.clock_id", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_clk_cmp_comparison_value, + { + "Comparison Value", "wmx.clk_cmp.comparison_value", + FT_INT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#if 0 + { + &hf_clk_cmp_invalid_tlv, + { + "Invalid TLV", "wmx.clk_cmp.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, +#endif + { + &hf_clk_cmp_seq_number, + { + "Sequence Number", "wmx.clk_cmp.seq_number", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_clk_cmp_decoder, + }; + + proto_mac_mgmt_msg_clk_cmp_decoder = proto_register_protocol ( + "WiMax CLK-CMP Message", /* name */ + "WiMax CLK-CMP (clk)", /* short name */ + "wmx.clk" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_clk_cmp_decoder, hf_clk_cmp, array_length(hf_clk_cmp)); + proto_register_subtree_array(ett, array_length(ett)); + clk_cmp_handle = register_dissector("mac_mgmt_msg_clk_cmp_handler", dissect_mac_mgmt_msg_clk_cmp_decoder, proto_mac_mgmt_msg_clk_cmp_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_clk_cmp(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_CLK_CMP, clk_cmp_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: + */ diff --git a/plugins/epan/wimax/msg_dcd.c b/plugins/epan/wimax/msg_dcd.c new file mode 100644 index 00000000..167e0742 --- /dev/null +++ b/plugins/epan/wimax/msg_dcd.c @@ -0,0 +1,1257 @@ +/* msg_dcd.c + * WiMax MAC Management DCD Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +/* +#define DEBUG +*/ + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +/* Delete the following variable as soon as possible */ +extern gboolean include_cor2_changes; + +void proto_register_mac_mgmt_msg_dcd(void); +void proto_reg_handoff_mac_mgmt_msg_dcd(void); + +static dissector_handle_t dcd_handle; + +static gint proto_mac_mgmt_msg_dcd_decoder = -1; +static gint ett_mac_mgmt_msg_dcd_decoder = -1; + +/* fix fields */ +static gint hf_dcd_downlink_channel_id = -1; +static gint hf_dcd_config_change_count = -1; +static gint hf_dcd_dl_burst_profile_rsv = -1; +static gint hf_dcd_dl_burst_profile_diuc = -1; + +static gint hf_dcd_bs_eirp = -1; +static gint hf_dcd_frame_duration = -1; +static gint hf_dcd_phy_type = -1; +static gint hf_dcd_power_adjustment = -1; +static gint hf_dcd_channel_nr = -1; +static gint hf_dcd_ttg = -1; +static gint hf_dcd_rtg = -1; +#ifdef WIMAX_16D_2004 +static gint hf_dcd_rss = -1; +#endif +static gint hf_dcd_channel_switch_frame_nr = -1; +static gint hf_dcd_frequency = -1; +static gint hf_dcd_bs_id = -1; +static gint hf_dcd_frame_duration_code = -1; +static gint hf_dcd_frame_nr = -1; +#ifdef WIMAX_16D_2004 +static gint hf_dcd_size_cqich_id = -1; +static gint hf_dcd_h_arq_ack_delay_dl = -1; +#else +static gint hf_dcd_h_arq_ack_delay_ul = -1; +#endif +static gint hf_dcd_mac_version = -1; +static gint hf_dcd_restart_count = -1; + +/* static gint hf_dl_burst_reserved = -1; */ +/* static gint hf_dl_burst_diuc = -1; */ +static gint hf_dcd_burst_freq = -1; +static gint hf_dcd_burst_fec = -1; +static gint hf_dcd_burst_diuc_exit_threshold = -1; +static gint hf_dcd_burst_diuc_entry_threshold = -1; +static gint hf_dcd_burst_tcs = -1; +static gint hf_dcd_tlv_t_19_permutation_type_for_broadcast_regions_in_harq_zone = -1; +static gint hf_dcd_tlv_t_20_maximum_retransmission = -1; +static gint hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter = -1; +static gint hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_physical_cinr_measurements = -1; +static gint hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_rssi_measurements = -1; +static gint hf_dcd_tlv_t_22_dl_amc_allocated_physical_bands_bitmap = -1; + +static gint hf_dcd_tlv_t_34_dl_region_definition = -1; +static gint hf_dcd_tlv_t_34_dl_region_definition_num_region = -1; +static gint hf_dcd_tlv_t_34_dl_region_definition_reserved = -1; +static gint hf_dcd_tlv_t_34_dl_region_definition_symbol_offset = -1; +static gint hf_dcd_eirxp = -1; +static gint hf_dcd_tlv_t_34_dl_region_definition_subchannel_offset = -1; +static gint hf_dcd_tlv_t_34_dl_region_definition_num_symbols = -1; +static gint hf_dcd_tlv_t_34_dl_region_definition_num_subchannels = -1; +static gint hf_dcd_tlv_t_50_ho_type_support = -1; +static gint hf_dcd_tlv_t_50_ho_type_support_ho = -1; +static gint hf_dcd_tlv_t_50_ho_type_support_mdho = -1; +static gint hf_dcd_tlv_t_50_ho_type_support_fbss_ho = -1; +static gint hf_dcd_tlv_t_50_ho_type_support_reserved = -1; +static gint hf_dcd_tlv_t_31_h_add_threshold = -1; +static gint hf_dcd_tlv_t_45_paging_interval_length = -1; +static gint hf_dcd_tlv_t_45_paging_interval_reserved = -1; +static gint hf_dcd_tlv_t_32_h_delete_threshold = -1; +static gint hf_dcd_tlv_t_33_asr = -1; +static gint hf_dcd_tlv_t_33_asr_m = -1; +static gint hf_dcd_tlv_t_33_asr_l = -1; +static gint hf_dcd_tlv_t_35_paging_group_id = -1; +static gint hf_dcd_tlv_t_36_tusc1_permutation_active_subchannels_bitmap = -1; +static gint hf_dcd_tlv_t_37_tusc2_permutation_active_subchannels_bitmap = -1; +static gint hf_dcd_tlv_t_51_hysteresis_margin = -1; +static gint hf_dcd_tlv_t_52_time_to_trigger_duration = -1; +static gint hf_dcd_tlv_t_60_noise_interference = -1; +static gint hf_dcd_tlv_t_153_downlink_burst_profile_for_mutiple_fec_types = -1; + +static gint hf_dcd_tlv_t_541_type_function_action = -1; +static gint hf_dcd_tlv_t_541_type = -1; +static gint hf_dcd_tlv_t_541_function = -1; +static gint hf_dcd_tlv_t_541_action = -1; +static gint hf_dcd_tlv_t_542_trigger_value = -1; +static gint hf_dcd_tlv_t_543_trigger_averaging_duration = -1; + +static gint hf_dcd_unknown_type = -1; +static gint hf_dcd_invalid_tlv = -1; + +/* DCD DIUC messages (table 143) */ +static const value_string diuc_msgs[] = +{ + { 0, "Downlink Burst Profile 1"}, + { 1, "Downlink Burst Profile 2"}, + { 2, "Downlink Burst Profile 3"}, + { 3, "Downlink Burst Profile 4"}, + { 4, "Downlink Burst Profile 5"}, + { 5, "Downlink Burst Profile 6"}, + { 6, "Downlink Burst Profile 7"}, + { 7, "Downlink Burst Profile 8"}, + { 8, "Downlink Burst Profile 9"}, + { 9, "Downlink Burst Profile 10"}, + {10, "Downlink Burst Profile 11"}, + {11, "Downlink Burst Profile 12"}, + {12, "Downlink Burst Profile 13"}, + {13, "Reserved"}, + {14, "Gap"}, + {15, "End of DL-MAP"}, + {0, NULL} +}; + +static const value_string vals_dcd_type[] = +{ + {0, "CINR metric"}, + {1, "RSSI metric"}, + {2, "RTD metric"}, + {3, "Reserved"}, + {0, NULL} +}; + +static const value_string vals_dcd_function[] = +{ + {0, "Reserved"}, + {1, "Metric of neighbor BS is greater than absolute value"}, + {2, "Metric of neighbor BS is less than absolute value"}, + {3, "Metric of neighbor BS is greater than serving BS metric by relative value"}, + {4, "Metric of neighbor BS is less than serving BS metric by relative value"}, + {5, "Metric of serving BS greater than absolute value"}, + {6, "Metric of serving BS less than absolute value"}, + {7, "Reserved"}, + {0, NULL} +}; + +static const value_string vals_dcd_action[] = +{ + {0, "Reserved"}, + {1, "Respond on trigger with MOB_SCN-REP after the end of each scanning interval"}, + {2, "Respond on trigger with MOB_MSH-REQ"}, + {3, "On trigger, MS starts neighbor BS scanning process by sending MOB_SCN-REQ"}, + {4, "Reserved"}, + {0, NULL} +}; + +static const value_string vals_dcd_power_adjustmnt[] = +{ + {0, "Preserve Peak Power"}, + {1, "Preserve Mean Power"}, + {0, NULL} +}; + +#if 0 +static const true_false_string tfs_dcd_power_adjustment = +{ + "Preserve Mean Power", + "Preserve Peak Power" +}; +#endif + +#if 0 +static const value_string vals_reg_rsp_status[] = +{ + {0, "OK"}, + {1, "Message authentication failure"}, + {0, NULL} +}; +#endif + +static const value_string vals_dcd_burst_tcs[] = +{ + {0, "TCS disabled"}, + {1, "TCS enabled"}, + {0, NULL} +}; + +#if 0 +static const true_false_string tfs_dcd_burst_tcs = +{ + "TCS enabled", + "TCS disabled" +}; +#endif + +static const value_string vals_dcd_frame_duration[] = +{ + {0, "2.5"}, + {1, "4"}, + {2, "5"}, + {3, "8"}, + {4, "10"}, + {5, "12.5"}, + {6, "20"}, + {0, NULL} +}; + +#ifdef WIMAX_16D_2004 +static const value_string vals_dcd_size_of_cqich_id[] = +{ + {0, "Reserved"}, + {1, "3 bits"}, + {2, "4 bits"}, + {3, "5 bits"}, + {4, "6 bits"}, + {5, "7 bits"}, + {6, "8 bits"}, + {7, "9 bits"}, + {0, NULL} +}; +#endif + +static const value_string vals_dcd_mac_version[] = +{ + { 1, "Conformance with IEEE Std 802.16-2001"}, + { 2, "Conformance with IEEE Std 802.16c-2002 and its predecessors"}, + { 3, "Conformance with IEEE Std 802.16a-2003 and its predecessors"}, + { 4, "Conformance with IEEE Std 802.16-2004"}, + { 5, "Conformance with IEEE Std 802.16-2004 and IEEE Std 802.16e-2005"}, + { 6, "Conformance with IEEE Std 802.16-2004, IEEE Std 802.16e-2005 and IEEE Std 802.16f-2005"}, + { 7, "Conformance with IEEE Std 802.16-2004, IEEE Std 802.16e-2005, IEEE Std 802.16f-2005 and IEEE Std 802.16g-2007"}, + { 8, "Conformance with IEEE Std 802.16-2009"}, + { 9, "Conformance with IEEE Std 802.16-2009 and IEEE Std 802.16j-2009"}, + {10, "Reserved"}, + {0, NULL} +}; + +/* table 363 */ +static const value_string vals_dcd_burst_fec_ofdma[] = +{ + { 0, "QPSK (CC) 1/2"}, + { 1, "QPSK (CC) 3/4"}, + { 2, "16-QAM (CC) 1/2"}, + { 3, "16-QAM (CC) 3/4"}, + { 4, "64-QAM (CC) 1/2"}, + { 5, "64-QAM (CC) 2/3"}, + { 6, "64-QAM (CC) 3/4"}, + { 7, "QPSK (BTC) 1/2"}, + { 8, "QPSK (BTC) 3/4 or 2/3"}, + { 9, "16-QAM (BTC) 3/5"}, + {10, "16-QAM (BTC) 4/5"}, + {11, "64-QAM (BTC) 2/3 or 5/8"}, + {12, "64-QAM (BTC) 5/6 or 4/5"}, + {13, "QPSK (CTC) 1/2"}, + {14, "Reserved"}, + {15, "QPSK (CTC) 3/4"}, + {16, "16-QAM (CTC) 1/2"}, + {17, "16-QAM (CTC) 3/4"}, + {18, "64-QAM (CTC) 1/2"}, + {19, "64-QAM (CTC) 2/3"}, + {20, "64-QAM (CTC) 3/4"}, + {21, "64-QAM (CTC) 5/6"}, + {22, "QPSK (ZT CC) 1/2"}, + {23, "QPSK (ZT CC) 3/4"}, + {24, "16-QAM (ZT CC) 1/2"}, + {25, "16-QAM (ZT CC) 3/4"}, + {26, "64-QAM (ZT CC) 1/2"}, + {27, "64-QAM (ZT CC) 2/3"}, + {28, "64-QAM (ZT CC) 3/4"}, + {29, "QPSK (LDPC) 1/2"}, + {30, "QPSK (LDPC) 2/3 A code"}, + {31, "16-QAM (LDPC) 3/4 A code"}, + {32, "16-QAM (LDPC) 1/2"}, + {33, "16-QAM (LDPC) 2/3 A code"}, + {34, "16-QAM (LDPC) 3/4 A code"}, + {35, "64-QAM (LDPC) 1/2"}, + {36, "64-QAM (LDPC) 2/3 A code"}, + {37, "64-QAM (LDPC) 3/4 A code"}, + {38, "QPSK (LDPC) 2/3 B code"}, + {39, "QPSK (LDPC) 3/4 B code"}, + {40, "16-QAM (LDPC) 2/3 B code"}, + {41, "16-QAM (LDPC) 3/4 B code"}, + {42, "64-QAM (LDPC) 2/3 B code"}, + {43, "64-QAM (LDPC) 3/4 B code"}, + {44, "QPSK (CC with optional interleaver) 1/2"}, + {45, "QPSK (CC with optional interleaver) 3/4"}, + {46, "16-QAM (CC with optional interleaver) 1/2"}, + {47, "16-QAM (CC optional interleaver) 3/4"}, + {48, "64-QAM (CC with optional interleaver) 2/3"}, + {49, "64-QAM (CC with optional interleaver) 3/4"}, + {50, "QPSK (LDPC) 5/6"}, + {51, "16-QAM (LDPC) 5/6"}, + {52, "64-QAM (LDPC) 5/6"}, + {0, NULL} +}; + +static const value_string vals_dcd_permutation_type[] = +{ + {0, "PUSC"}, + {1, "FUSC"}, + {2, "optional FUSC"}, + {3, "AMC"}, + {0, NULL} +}; + +static const value_string tfs_support[] = +{ + {0, "not supported"}, + {1, "supported"}, + {0, NULL} +}; + + +/* WiMax MAC Management DCD message (table 15) dissector */ +static int dissect_mac_mgmt_msg_dcd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len, length; + gint tlv_type, tlv_len, tlv_offset, tlv_value_offset; + guint dl_burst_diuc, dl_num_regions; + proto_item *dcd_item, *tlv_item, *sub_item; + proto_tree *dcd_tree, *tlv_tree, *sub_tree; + tlv_info_t tlv_info; + gchar* proto_str; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type DCD */ + dcd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, tvb_len, "Downlink Channel Descriptor (DCD)"); + /* add MAC DCD subtree */ + dcd_tree = proto_item_add_subtree(dcd_item, ett_mac_mgmt_msg_dcd_decoder); + /* Decode and display the Downlink Channel Descriptor (DCD) */ + /* display the Downlink Channel ID */ + proto_tree_add_item(dcd_tree, hf_dcd_downlink_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN); + /* set the offset for the Configuration Change Count */ + offset++; + /* display the Configuration Change Count */ + proto_tree_add_item(dcd_tree, hf_dcd_config_change_count, tvb, offset, 1, ENC_BIG_ENDIAN); + /* set the offset for the TLV Encoded info */ + offset++; + /* process the DCD TLV Encoded information (table 358) */ + while(offset < tvb_len) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DCD TLV error"); + proto_tree_add_item(dcd_tree, hf_dcd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset, (tlv_len + tlv_value_offset), "DCD Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len); +#endif + /* update the offset */ + offset += tlv_value_offset; + /* process DCD TLVs */ + switch (tlv_type) + { + case DCD_DOWNLINK_BURST_PROFILE: + { /* Downlink Burst Profile TLV (table 363)*/ + /* get the DIUC */ + dl_burst_diuc = (tvb_get_guint8(tvb, offset) & 0x0F); + /* display TLV info */ + /* add TLV subtree */ + proto_str = wmem_strdup_printf(pinfo->pool, "Downlink_Burst_Profile (DIUC=%u)", dl_burst_diuc); + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset-tlv_value_offset, tlv_len, proto_str); + /* detail display */ + proto_tree_add_item(tlv_tree, hf_dcd_dl_burst_profile_rsv, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_dl_burst_profile_diuc, tvb, offset, 1, ENC_BIG_ENDIAN); + /* process subTLVs */ + for (tlv_offset = 1; tlv_offset < tlv_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset+tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DL Burst Profile TLV error"); + proto_tree_add_item(tlv_tree, hf_dcd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + + switch (tlv_type) + { + case DCD_BURST_FREQUENCY: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_dcd_burst_freq, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); + break; + } + case DCD_BURST_FEC_CODE_TYPE: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_dcd_burst_fec, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); + break; + } + case DCD_BURST_DIUC_EXIT_THRESHOLD: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_dcd_burst_diuc_exit_threshold, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); + break; + } + case DCD_BURST_DIUC_ENTRY_THRESHOLD: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_dcd_burst_diuc_entry_threshold, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); + break; + } + case DCD_BURST_TCS_ENABLE: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_dcd_burst_tcs, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); + break; + } + default: + /* ??? */ + break; + } + tlv_offset += (length+get_tlv_value_offset(&tlv_info)); + } + break; + } + case DCD_BS_EIRP: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_bs_eirp, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_FRAME_DURATION: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_frame_duration, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_PHY_TYPE: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_phy_type, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_POWER_ADJUSTMENT: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_power_adjustment, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_CHANNEL_NR: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_channel_nr, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TTG: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_ttg, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_RTG: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_rtg, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } +#ifdef WIMAX_16D_2004 + case DCD_RSS: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_rss, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } +#else + case DCD_EIRXP: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_eirxp, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } +#endif + case DCD_CHANNEL_SWITCH_FRAME_NR: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_channel_switch_frame_nr, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_FREQUENCY: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_frequency, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_BS_ID: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_bs_id, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_FRAME_DURATION_CODE: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_frame_duration_code, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_FRAME_NR: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_frame_nr, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } +#ifdef WIMAX_16D_2004 + case DCD_SIZE_CQICH_ID: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_size_cqich_id, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } +#endif + case DCD_H_ARQ_ACK_DELAY: + { +#ifdef WIMAX_16D_2004 + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_h_arq_ack_delay_dl, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); +#else + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_h_arq_ack_delay_ul, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); +#endif + break; + } + case DCD_MAC_VERSION: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_mac_version, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_19_PERMUTATION_TYPE_FOR_BROADCAST_REGION_IN_HARQ_ZONE: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_19_permutation_type_for_broadcast_regions_in_harq_zone, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_20_MAXIMUM_RETRANSMISSION: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_20_maximum_retransmission, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_21_DEFAULT_RSSI_AND_CINR_AVERAGING_PARAMETER: + { + tlv_item = add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_dcd_decoder); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_physical_cinr_measurements, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_rssi_measurements, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_22_DL_AMC_ALLOCATED_PHYSICAL_BANDS_BITMAP: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_22_dl_amc_allocated_physical_bands_bitmap, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + case DCD_TLV_T_34_DL_REGION_DEFINITION: + { + tlv_item = add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_34_dl_region_definition, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_dcd_decoder); + dl_num_regions = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_region, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + tlv_offset = offset; + for(length = 0; length < dl_num_regions; length++) + { + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_symbol_offset, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_subchannel_offset, tvb, (tlv_offset+1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_symbols, tvb, (tlv_offset+2), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_34_dl_region_definition_num_subchannels, tvb, (tlv_offset+3), 1, ENC_BIG_ENDIAN); + tlv_offset += 4; + } + break; + } + case DCD_TLV_T_50_HO_TYPE_SUPPORT: + { + tlv_item = add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_50_ho_type_support, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_dcd_decoder); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_ho, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_mdho, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_fbss_ho, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_50_ho_type_support_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_31_H_ADD_THRESHOLD: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_31_h_add_threshold, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_32_H_DELETE_THRESHOLD: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_32_h_delete_threshold, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_33_ASR: + { + tlv_item = add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_33_asr, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_dcd_decoder); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_33_asr_m, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_dcd_tlv_t_33_asr_l, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_35_PAGING_GROUP_ID: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_35_paging_group_id, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_36_TUSC1_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_36_tusc1_permutation_active_subchannels_bitmap, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_37_TUSC2_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_37_tusc2_permutation_active_subchannels_bitmap, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_51_HYSTERSIS_MARGIN: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_51_hysteresis_margin, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_52_TIME_TO_TRIGGER_DURATION: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_52_time_to_trigger_duration, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_54_TRIGGER: + { /* Trigger TLV (table 358a & 358b) */ + /* add TLV subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dcd_decoder, dcd_tree, proto_mac_mgmt_msg_dcd_decoder, tvb, offset-tlv_value_offset, tlv_len, "DCD Trigger"); + for (tlv_offset = 0; tlv_offset < tlv_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Trigger TLV error"); + proto_tree_add_item(tlv_tree, hf_dcd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + /* update the offset */ + tlv_offset += get_tlv_value_offset(&tlv_info); + /* table 358a */ + switch (tlv_type) + { + case DCD_TLV_T_541_TYPE_FUNCTION_ACTION: + { /* table 358b */ + sub_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_dcd_tlv_t_541_type_function_action, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_mac_mgmt_msg_dcd_decoder); + proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_type, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_function, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_dcd_tlv_t_541_action, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + } + break; + case DCD_TLV_T542_TRIGGER_VALUE: + add_tlv_subtree(&tlv_info, tlv_tree, hf_dcd_tlv_t_542_trigger_value, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case DCD_TLV_T_543_TRIGGER_AVERAGING_DURATION: + add_tlv_subtree(&tlv_info, tlv_tree, hf_dcd_tlv_t_543_trigger_averaging_duration, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + } + tlv_offset += length; + } + break; + } + case DCD_TLV_T_60_NOISE_AND_INTERFERENCE: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_60_noise_interference, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_153_DOWNLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_153_downlink_burst_profile_for_mutiple_fec_types, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_RESTART_COUNT: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_restart_count, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case DCD_TLV_T_45_PAGING_INTERVAL_LENGTH: + { + if (include_cor2_changes) { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_45_paging_interval_reserved, tvb, offset-tlv_value_offset, ENC_NA); + } else { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_tlv_t_45_paging_interval_length, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + break; + } + default: + { + add_tlv_subtree(&tlv_info, dcd_tree, hf_dcd_unknown_type, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + } + offset += tlv_len; + } /* end of TLV process while loop */ + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_dcd(void) +{ + /* DCD display */ + static hf_register_info hf[] = + { + { + &hf_dcd_tlv_t_33_asr, + { + "ASR (Anchor Switch Report) Slot Length (M) and Switching Period (L)", "wmx.dcd.asr", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_33_asr_l, + { + "ASR Switching Period (L)", "wmx.dcd.asr.l", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_frame_frames, 0x0f, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_33_asr_m, + { + "ASR Slot Length (M)", "wmx.dcd.asr.m", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_frame_frames, 0xf0, NULL, HFILL + } + }, + { + &hf_dcd_bs_eirp, + { + "BS EIRP", "wmx.dcd.bs_eirp", + FT_INT16, BASE_DEC|BASE_UNIT_STRING, &wimax_units_dbm, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_bs_id, + { + "Base Station ID", "wmx.dcd.bs_id", + FT_ETHER, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_restart_count, + { + "BS Restart Count", "wmx.dcd.bs_restart_count", + FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, +#if 0 + { + &hf_dl_burst_diuc, + { + "DIUC", "wmx.dcd.burst.diuc", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, +#endif + { + &hf_dcd_burst_diuc_entry_threshold, + { + "DIUC Minimum Entry Threshold (in 0.25 dB units)", "wmx.dcd.burst.diuc_entry_threshold", + FT_FLOAT, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_burst_diuc_exit_threshold, + { + "DIUC Mandatory Exit Threshold (in 0.25 dB units)", "wmx.dcd.burst.diuc_exit_threshold", + FT_FLOAT, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_burst_fec, + { + "FEC Code Type", "wmx.dcd.burst.fec", + FT_UINT8, BASE_DEC, VALS(vals_dcd_burst_fec_ofdma), 0x00, NULL, HFILL + } + }, + { + &hf_dcd_burst_freq, + { + "Frequency", "wmx.dcd.burst.freq", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_khz, 0x00, NULL, HFILL + } + }, +#if 0 + { + &hf_dl_burst_reserved, + { + "Reserved", "wmx.dcd.burst.reserved", + FT_UINT8, BASE_HEX, NULL, 0xF0, NULL, HFILL + } + }, +#endif + { + &hf_dcd_burst_tcs, + { + "TCS", "wmx.dcd.burst.tcs", + FT_UINT8, BASE_DEC, VALS(vals_dcd_burst_tcs), 0x00, NULL, HFILL + } + }, + { + &hf_dcd_channel_nr, + { + "Channel Nr", "wmx.dcd.channel_nr", + FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_config_change_count, + { + "Configuration Change Count", "wmx.dcd.config_change_count", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_physical_cinr_measurements, + { + "Default Averaging Parameter for Physical CINR Measurements (in multiples of 1/16)", "wmx.dcd.default_physical_cinr_meas_averaging_parameter", + FT_UINT8, BASE_HEX, NULL, 0xf0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter, + { + "Default RSSI and CINR Averaging Parameter", "wmx.dcd.default_rssi_and_cinr_averaging_parameter", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_21_default_rssi_and_cinr_averaging_parameter_rssi_measurements, + { + "Default Averaging Parameter for RSSI Measurements (in multiples of 1/16)", "wmx.dcd.default_rssi_meas_averaging_parameter", + FT_UINT8, BASE_HEX, NULL, 0x0f, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_22_dl_amc_allocated_physical_bands_bitmap, + { + "DL AMC Allocated Physical Bands Bitmap", "wmx.dcd.dl_amc_allocated_phy_bands_bitmap", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_dl_burst_profile_diuc, + { + "DIUC", "wmx.dcd.dl_burst_profile_diuc", + FT_UINT8, BASE_DEC, VALS(diuc_msgs), 0x0F, NULL, HFILL + } + }, + { + &hf_dcd_dl_burst_profile_rsv, + { + "Reserved", "wmx.dcd.dl_burst_profile_rsv", + FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_dcd_downlink_channel_id, + { + "Reserved", "wmx.dcd.dl_channel_id", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_153_downlink_burst_profile_for_mutiple_fec_types, + { + "Downlink Burst Profile for Multiple FEC Types","wmx.dcd.dl_burst_profile_multiple_fec_types", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_34_dl_region_definition, + { + "DL Region Definition", "wmx.dcd.dl_region_definition", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_34_dl_region_definition_num_region, + { + "Number of Regions", "wmx.dcd.dl_region_definition.num_region", + FT_UINT8, BASE_DEC, NULL, 0xFC, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_34_dl_region_definition_num_subchannels, + { + "Number of Subchannels", "wmx.dcd.dl_region_definition.num_subchannels", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_34_dl_region_definition_num_symbols, + { + "Number of OFDMA Symbols", "wmx.dcd.dl_region_definition.num_symbols", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_34_dl_region_definition_reserved, + { + "Reserved", "wmx.dcd.dl_region_definition.reserved", + FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_34_dl_region_definition_subchannel_offset, + { + "Subchannel Offset", "wmx.dcd.dl_region_definition.subchannel_offset", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_34_dl_region_definition_symbol_offset, + { + "OFDMA Symbol Offset", "wmx.dcd.dl_region_definition.symbol_offset", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, +#ifndef WIMAX_16D_2004 + { + &hf_dcd_eirxp, + { + "EIRXP (IR, max)", "wmx.dcd.eirxp", + FT_INT16, BASE_DEC|BASE_UNIT_STRING, &wimax_units_dbm, 0x00, NULL, HFILL + } + }, +#endif + { + &hf_dcd_frame_duration, + { + "Frame Duration", "wmx.dcd.frame_duration", + FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_frame_duration_code, + { + "Frame Duration Code", "wmx.dcd.frame_duration_code", + FT_UINT8, BASE_HEX, VALS(vals_dcd_frame_duration), 0x00, NULL, HFILL + } + }, + { + &hf_dcd_frame_nr, + { + "Frame Number", "wmx.dcd.frame_nr", + FT_UINT24, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_frequency, + { + "Downlink Center Frequency", "wmx.dcd.frequency", + FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_khz, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_31_h_add_threshold, + { + "H_add Threshold", "wmx.dcd.h_add_threshold", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_db, 0x0, NULL, HFILL + } + }, +#ifdef WIMAX_16D_2004 + { + &hf_dcd_h_arq_ack_delay_dl, + { + "H-ARQ ACK Delay for DL Burst", "wmx.dcd.h_arq_ack_delay_dl_burst", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_frame_offset, 0x00, "", HFILL + } + }, +#else + { + &hf_dcd_h_arq_ack_delay_ul, + { + "H-ARQ ACK Delay for UL Burst", "wmx.dcd.h_arq_ack_delay_ul_burst", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_frame_offset, 0x00, NULL, HFILL + } + }, +#endif + { + &hf_dcd_tlv_t_32_h_delete_threshold, + { + "H_delete Threshold", "wmx.dcd.h_delete_threshold", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_db, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_50_ho_type_support, + { + "HO Type Support", "wmx.dcd.ho_type_support", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_50_ho_type_support_fbss_ho, + { + "FBSS HO", "wmx.dcd.ho_type_support.fbss_ho", + FT_UINT8, BASE_HEX, VALS(tfs_support), 0x20, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_50_ho_type_support_ho, + { + "HO", "wmx.dcd.ho_type_support.ho", + FT_UINT8, BASE_HEX, VALS(tfs_support), 0x80, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_50_ho_type_support_mdho, + { + "MDHO", "wmx.dcd.ho_type_support.mdho", + FT_UINT8, BASE_HEX, VALS(tfs_support), 0x40, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_50_ho_type_support_reserved, + { + "Reserved", "wmx.dcd.ho_type_support.reserved", + FT_UINT8, BASE_HEX, NULL, 0x1f, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_51_hysteresis_margin, + { + "Hysteresis Margin", "wmx.dcd.hysteresis_margin", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_db, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_invalid_tlv, + { + "Invalid TLV", "wmx.dcd.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_dcd_mac_version, + { + "MAC Version", "wmx.dcd.mac_version", + FT_UINT8, BASE_DEC, VALS(vals_dcd_mac_version), 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_20_maximum_retransmission, + { + "Maximum Retransmission", "wmx.dcd.maximum_retransmission", + FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_60_noise_interference, + { + "Noise and Interference", "wmx.dcd.noise_interference", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_35_paging_group_id, + { + "Paging Group ID", "wmx.dcd.paging_group_id", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_36_tusc1_permutation_active_subchannels_bitmap, + { + "TUSC1 permutation active subchannels bitmap", "wmx.dcd.tusc1", + FT_UINT16, BASE_HEX, NULL, 0xFF80, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_37_tusc2_permutation_active_subchannels_bitmap, + { + "TUSC2 permutation active subchannels bitmap", "wmx.dcd.tusc2", + FT_UINT16, BASE_HEX, NULL, 0xFFF8, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_45_paging_interval_length, + { + "Paging Interval Length", "wmx.dcd.paging_interval_length", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_45_paging_interval_reserved, + { + "Reserved", "wmx.dcd.paging_interval_reserved", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_19_permutation_type_for_broadcast_regions_in_harq_zone, + { + "Permutation Type for Broadcast Region in HARQ Zone", "wmx.dcd.permutation_type_broadcast_region_in_harq_zone", + FT_UINT8, BASE_DEC, VALS(vals_dcd_permutation_type), 0x00, NULL, HFILL + } + }, + { + &hf_dcd_phy_type, + { + "PHY Type", "wmx.dcd.phy_type", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_power_adjustment, + { + "Power Adjustment Rule", "wmx.dcd.power_adjustment", + FT_UINT8, BASE_HEX, VALS(vals_dcd_power_adjustmnt), 0x00, NULL, HFILL + } + }, +#ifdef WIMAX_16D_2004 + { + &hf_dcd_rss, + { + "RSS (IR, max)", "wmx.dcd.rss", + FT_INT16, BASE_DEC|BASE_UNIT_STRING, &wimax_units_dbm, 0x00, "", HFILL + } + }, +#endif + { + &hf_dcd_rtg, + { + "RTG", "wmx.dcd.rtg", + FT_UINT8, BASE_HEX|BASE_UNIT_STRING, &wimax_units_ps, 0x00, NULL, HFILL + } + }, +#ifdef WIMAX_16D_2004 + { + &hf_dcd_size_cqich_id, + { + "Size of CQICH-ID Field", "wmx.dcd.size_cqich_id", + FT_UINT8, BASE_DEC, VALS(vals_dcd_size_of_cqich_id), 0x00, "", HFILL + } + }, +#endif + { + &hf_dcd_channel_switch_frame_nr, + { + "Channel Switch Frame Number", "wmx.dcd.switch_frame", + FT_UINT24, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_52_time_to_trigger_duration, + { + "Time to Trigger Duration", "wmx.dcd.time_trigger_duration", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_ms, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_543_trigger_averaging_duration, + { + "Trigger Averaging Duration", "wmx.dcd.trigger_averaging_duration", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_542_trigger_value, + { + "Trigger Value", "wmx.dcd.trigger_value", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_ttg, + { + "TTG", "wmx.dcd.ttg", + FT_UINT16, BASE_HEX|BASE_UNIT_STRING, &wimax_units_ps, 0x00, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_541_type_function_action, + { + "Type/Function/Action", "wmx.dcd.type_function_action", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_541_action, + { + "Action", "wmx.dcd.type_function_action.action", + FT_UINT8, BASE_HEX, VALS(vals_dcd_action), 0x7, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_541_function, + { + "Function", "wmx.dcd.type_function_action.function", + FT_UINT8, BASE_HEX, VALS(vals_dcd_function), 0x38, NULL, HFILL + } + }, + { + &hf_dcd_tlv_t_541_type, + { + "Type", "wmx.dcd.type_function_action.type", + FT_UINT8, BASE_HEX, VALS(vals_dcd_type), 0xC0, NULL, HFILL + } + }, + { + &hf_dcd_unknown_type, + { + "Unknown DCD Type", "wmx.dcd.unknown_tlv_value", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_dcd_decoder, + }; + + proto_mac_mgmt_msg_dcd_decoder = proto_register_protocol ( + "WiMax DCD Messages", /* name */ + "WiMax DCD", /* short name */ + "wmx.dcd" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_dcd_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + dcd_handle = register_dissector("mac_mgmt_msg_dcd_handler", dissect_mac_mgmt_msg_dcd_decoder, proto_mac_mgmt_msg_dcd_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_dcd(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DCD, dcd_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: + */ diff --git a/plugins/epan/wimax/msg_dlmap.c b/plugins/epan/wimax/msg_dlmap.c new file mode 100644 index 00000000..4df5f213 --- /dev/null +++ b/plugins/epan/wimax/msg_dlmap.c @@ -0,0 +1,3482 @@ +/* msg_dlmap.c + * WiMax MAC Management DL-MAP Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Mike Harvey + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include +#include "wimax_mac.h" +#include "crc.h" +#include "wimax_bits.h" +#include "wimax_utils.h" + +extern gboolean include_cor2_changes; + +void proto_register_mac_mgmt_msg_dlmap(void); +void proto_reg_handoff_mac_mgmt_msg_dlmap(void); + +static dissector_handle_t dlmap_handle; + +#define MAC_MGMT_MSG_DLMAP 2 + +#define XBIT_HF(bits, hf) \ + proto_tree_add_bits_item(tree, hf, tvb, bit, bits, ENC_BIG_ENDIAN); bit += bits; + +#define XBIT_HF_VALUE(var, bits, hf) \ + do { \ + var = TVB_BIT_BITS(bit, tvb, bits); \ + proto_tree_add_bits_item(tree, hf, tvb, bit, bits, ENC_BIG_ENDIAN); \ + bit += bits; \ + } while(0) + +#define VBIT(var, bits, hf) \ + do { \ + var = TVB_BIT_BITS(bit, tvb, bits); \ + proto_tree_add_uint(tree, hf, tvb, BITHI(bit,bits), var); \ + bit += bits; \ + } while(0) + +#define VNIB(var, nibs, hf) \ + do { \ + var = TVB_NIB_NIBS(nib, tvb, nibs); \ + proto_tree_add_uint(tree, hf, tvb, NIBHI(nib, nibs), var); \ + nib += nibs; \ + } while(0) + +gint harq = 0; /* 1 if HARQ enabled (TODO) */ +gint fusc = 0; /* 1 if current zone permutation is FUSC or optional FUSC (TODO) */ +gint tusc = 0; /* 1 if current zone permutation is AMC, TUSC1 or TUSC2 (TODO) */ +gint ir_type = 0; /* reduced AAS map (TODO) */ +gint RCID_Type = 0; +gint N_layer = 0; +gint STC_Zone_Dedicated_Pilots = 0; +gint STC_Zone_Matrix = 0; +gint INC_CID = 0; +gint sub_dl_ul_map = 0; + +static gint proto_mac_mgmt_msg_dlmap_decoder = -1; + +static gint ett_dlmap = -1; +static gint ett_dlmap_ie = -1; +/* static gint ett_dlmap_c_ie = -1; */ +static gint ett_109x = -1; /* SUB-DL-UL-MAP */ +static gint ett_109x_dl = -1; +static gint ett_109x_ul = -1; +static gint ett_275_phy = -1; +static gint ett_275_1 = -1; +static gint ett_277 = -1; +static gint ett_277b = -1; +static gint ett_278 = -1; +static gint ett_279 = -1; +static gint ett_280 = -1; +static gint ett_281 = -1; +static gint ett_282 = -1; +static gint ett_283 = -1; +static gint ett_284 = -1; +static gint ett_285 = -1; +static gint ett_286 = -1; +static gint ett_286a = -1; +static gint ett_286b = -1; +static gint ett_286c = -1; +static gint ett_286d = -1; +static gint ett_286e = -1; +static gint ett_286f = -1; +static gint ett_286g = -1; +static gint ett_286h = -1; +static gint ett_286i = -1; +static gint ett_286j = -1; +static gint ett_286k = -1; +static gint ett_286l = -1; +static gint ett_286m = -1; +static gint ett_286n = -1; +static gint ett_286o = -1; +static gint ett_286p = -1; +static gint ett_286q = -1; +static gint ett_286r = -1; +static gint ett_286s = -1; +static gint ett_286t = -1; +static gint ett_286u = -1; +static gint ett_286v = -1; +static gint ett_286w = -1; +static gint ett_286x = -1; +static gint ett_286y = -1; +static gint ett_286z = -1; +static gint ett_305 = -1; +/* static gint ett_305_dl = -1; */ +static gint ett_308a = -1; + +#define DCD_DOWNLINK_BURST_PROFILE 1 +#define DCD_BS_EIRP 2 +#define DCD_FRAME_DURATION 3 +#define DCD_PHY_TYPE 4 +#define DCD_POWER_ADJUSTMENT 5 +#define DCD_CHANNEL_NR 6 +#define DCD_TTG 7 +#define DCD_RTG 8 +#define DCD_RSS 9 +#define DCD_CHANNEL_SWITCH_FRAME_NR 10 +#define DCD_FREQUENCY 12 +#define DCD_BS_ID 13 +#define DCD_FRAME_DURATION_CODE 14 +#define DCD_FRAME_NR 15 +#define DCD_SIZE_CQICH_ID 16 +#define DCD_H_ARQ_ACK_DELAY 17 +#define DCD_MAC_VERSION 148 +#define DCD_RESTART_COUNT 154 + +#define DCD_BURST_FREQUENCY 1 +#define DCD_BURST_FEC_CODE_TYPE 150 +#define DCD_BURST_DIUC_EXIT_THRESHOLD 151 +#define DCD_BURST_DIUC_ENTRY_THRESHOLD 152 +#define DCD_BURST_TCS_ENABLE 153 + +#define DCD_TLV_T_541_TYPE_FUNCTION_ACTION 1 +#define DCD_TLV_T542_TRIGGER_VALUE 2 +#define DCD_TLV_T_543_TRIGGER_AVERAGING_DURATION 3 +#define DCD_TLV_T_19_PERMUTATION_TYPE_FOR_BROADCAST_REGION_IN_HARQ_ZONE 19 +#define DCD_TLV_T_20_MAXIMUM_RETRANSMISSION 20 +#define DCD_TLV_T_21_DEFAULT_RSSI_AND_CINR_AVERAGING_PARAMETER 21 +#define DCD_TLV_T_22_DL_AMC_ALLOCATED_PHYSICAL_BANDS_BITMAP 22 +#define DCD_TLV_T_31_H_ADD_THRESHOLD 31 +#define DCD_TLV_T_32_H_DELETE_THRESHOLD 32 +#define DCD_TLV_T_33_ASR 33 +#define DCD_TLV_T_34_DL_REGION_DEFINITION 34 +#define DCD_TLV_T_35_PAGING_GROUP_ID 35 +#define DCD_TLV_T_36_TUSC1_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP 36 +#define DCD_TLV_T_37_TUSC2_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP 37 +#define DCD_TLV_T_45_PAGING_INTERVAL_LENGTH 45 +#define DCD_TLV_T_50_HO_TYPE_SUPPORT 50 +#define DCD_TLV_T_51_HYSTERSIS_MARGIN 51 +#define DCD_TLV_T_52_TIME_TO_TRIGGER_DURATION 52 +#define DCD_TLV_T_54_TRIGGER 54 +#define DCD_TLV_T_153_DOWNLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES 153 + +#define DL_MAP_NCT_PMP 0 +#define DL_MAP_NCT_DM 1 +#define DL_MAP_NCT_PTP 2 + +#if 0 +/* NCT messages */ +static const value_string nct_msgs[] = +{ + { DL_MAP_NCT_PMP, "PMP" }, + { DL_MAP_NCT_PMP, "DM" }, + { DL_MAP_NCT_PMP, "PTP" }, + { 0, NULL } +}; +#endif + +/* Repetition Coding Indications */ +static const value_string rep_msgs[] = +{ + { 0, "No Repetition Coding" }, + { 1, "Repetition Coding of 2 Used" }, + { 2, "Repetition Coding of 4 Used" }, + { 3, "Repetition Coding of 6 Used" }, + { 0, NULL } +}; + +/* DL Frame Prefix Coding Indications */ +static const value_string boost_msgs[] = +{ + { 0, "Normal (not boosted)" }, + { 1, "+6dB" }, + { 2, "-6dB" }, + { 3, "+9dB" }, + { 4, "+3dB" }, + { 5, "-3dB" }, + { 6, "-9dB" }, + { 7, "-12dB" }, + { 0, NULL } +}; + +/* OFDMA frame duration ms (Table 320)*/ +static const value_string frame_duration[] = +{ + { 0, "reserved"}, + { 1, "2 ms"}, + { 2, "2.5 ms"}, + { 3, "4 ms"}, + { 4, "5 ms"}, + { 5, "8 ms"}, + { 6, "10 ms"}, + { 7, "12.5 ms"}, + { 8, "20 ms"}, + { 0, NULL} +}; + +/* OFDMA frames per second (Table 320)*/ +static const value_string frames_per_second[] = +{ + { 0, "reserved"}, + { 1, "500"}, + { 2, "400"}, + { 3, "250"}, + { 4, "200"}, + { 5, "125"}, + { 6, "100"}, + { 7, "80"}, + { 8, "50"}, + { 0, NULL} +}; + +/* dl-map fields */ +static gint hf_dlmap_phy_fdur = -1; +static gint hf_dlmap_phy_fdur_ms = -1; +static gint hf_dlmap_phy_fdur_per_sec = -1; +static gint hf_dlmap_phy_fnum = -1; +/* static gint hf_dlmap_fch_expected = -1; */ +static gint hf_dlmap_dcd = -1; +static gint hf_dlmap_bsid = -1; +static gint hf_dlmap_ofdma_sym = -1; +/* static gint hf_dlmap_ie = -1; */ +static gint hf_dlmap_ie_diuc = -1; +static gint hf_dlmap_ie_reserved_extended2_duic = -1; +static gint hf_dlmap_ie_reserved_extended_duic = -1; +static gint hf_dlmap_ie_diuc_ext = -1; +static gint hf_dlmap_ie_diuc_ext2 = -1; +static gint hf_dlmap_ie_length = -1; +static gint hf_dlmap_ie_bitmap = -1; +static gint hf_dlmap_ie_bitmap_cqi = -1; +static gint hf_dlmap_ie_bitmap_pusc = -1; +static gint hf_dlmap_ie_bitmap_opt_pusc = -1; +static gint hf_dlmap_ie_bitmap_amc = -1; +static gint hf_dlmap_ie_bitmap_aas = -1; +static gint hf_dlmap_ie_bitmap_periodic_ranging = -1; +static gint hf_dlmap_ie_bitmap_sounding = -1; +static gint hf_dlmap_ie_bitmap_mimo = -1; +static gint hf_dlmap_ie_ncid = -1; +static gint hf_dlmap_ie_cid = -1; +static gint hf_dlmap_ie_offsym = -1; +static gint hf_dlmap_ie_offsub = -1; +static gint hf_dlmap_ie_boosting = -1; +static gint hf_dlmap_ie_numsym = -1; +static gint hf_dlmap_ie_numsub = -1; +static gint hf_dlmap_ie_rep = -1; +static gint hf_dlmap_ie_offsym2 = -1; +static gint hf_dlmap_ie_offsub2 = -1; +static gint hf_dlmap_ie_boosting2 = -1; +static gint hf_dlmap_ie_numsym2 = -1; +static gint hf_dlmap_ie_numsub2 = -1; +static gint hf_dlmap_ie_rep2 = -1; + +/* static gint hf_dlmap_xie_diuc = -1; */ +/* static gint hf_dlmap_xie_len = -1; */ + +static gint hf_dlmapc_compr = -1; +static gint hf_dlmapc_ulmap = -1; +static gint hf_dlmapc_rsv = -1; +static gint hf_dlmapc_len = -1; +/* static gint hf_dlmapc_sync = -1; */ +static gint hf_dlmapc_opid = -1; +static gint hf_dlmapc_secid = -1; +static gint hf_dlmapc_count = -1; + +#if 0 +static gint hf_109x_cmi = -1; +static gint hf_109x_len = -1; +static gint hf_109x_rcid = -1; +static gint hf_109x_haoi = -1; +static gint hf_109x_dl = -1; +static gint hf_109x_ul = -1; +static gint hf_109x_dlie = -1; +static gint hf_109x_symofs = -1; +static gint hf_109x_subofs = -1; +static gint hf_109x_rsv = -1; +#endif + +static gint hf_308a_cmi = -1; +static gint hf_308a_ulmap = -1; +static gint hf_308a_type = -1; +static gint hf_308a_mult = -1; +static gint hf_308a_rsv = -1; +static gint hf_mac_header_compress_dlmap_crc = -1; +static gint hf_mac_header_compress_dlmap_crc_status = -1; +static gint hf_crc16 = -1; +static gint hf_crc16_status = -1; +static gint hf_padding = -1; +static gint hf_cid_mask = -1; +static gint hf_reserved = -1; + +/* Generated via "one time" script to help create filterable fields */ +static int hf_dlmap_rcid_ie_cid = -1; +static int hf_dlmap_rcid_ie_prefix = -1; +static int hf_dlmap_rcid_ie_cid11 = -1; +static int hf_dlmap_rcid_ie_cid7 = -1; +static int hf_dlmap_rcid_ie_cid3 = -1; +static int hf_dlmap_dedicated_dl_control_length = -1; +static int hf_dlmap_dedicated_dl_control_control_header = -1; +static int hf_dlmap_dedicated_dl_control_num_sdma_layers = -1; +static int hf_dlmap_dedicated_mimo_dl_control_length = -1; +static int hf_dlmap_dedicated_mimo_dl_control_control_header_mimo_control_info = -1; +static int hf_dlmap_dedicated_mimo_dl_control_control_header_cqi_control_info = -1; +static int hf_dlmap_dedicated_mimo_dl_control_control_header_closed_mimo_control_info = -1; +static int hf_dlmap_dedicated_mimo_dl_control_n_layer = -1; +static int hf_dlmap_dedicated_mimo_dl_control_matrix = -1; +static int hf_dlmap_dedicated_mimo_dl_control_num_beamformed_streams = -1; +static int hf_dlmap_dedicated_mimo_dl_control_period = -1; +static int hf_dlmap_dedicated_mimo_dl_control_frame_offset = -1; +static int hf_dlmap_dedicated_mimo_dl_control_duration = -1; +static int hf_dlmap_dedicated_mimo_dl_control_allocation_index = -1; +static int hf_dlmap_dedicated_mimo_dl_control_cqich_num = -1; +static int hf_dlmap_dedicated_mimo_dl_control_feedback_type = -1; +static int hf_dlmap_dedicated_mimo_dl_control_antenna_grouping_index = -1; +static int hf_dlmap_dedicated_mimo_dl_control_num_stream = -1; +static int hf_dlmap_dedicated_mimo_dl_control_antenna_selection_index = -1; +static int hf_dlmap_dedicated_mimo_dl_control_codebook_precoding_index = -1; +static int hf_dlmap_n_sub_burst_isi = -1; +static int hf_dlmap_harq_chase_n_ack_channel = -1; +static int hf_dlmap_harq_chase_duration = -1; +static int hf_dlmap_harq_chase_sub_burst_diuc_indicator = -1; +static int hf_dlmap_reserved_uint = -1; +static int hf_dlmap_harq_chase_diuc = -1; +static int hf_dlmap_harq_chase_repetition_coding_indication = -1; +static int hf_dlmap_harq_chase_acid = -1; +static int hf_dlmap_harq_chase_ai_sn = -1; +static int hf_dlmap_harq_chase_ack_disable = -1; +static int hf_dlmap_harq_chase_dedicated_dl_control_indicator = -1; +static int hf_dlmap_harq_chase_allocation_index = -1; +static int hf_dlmap_harq_chase_period = -1; +static int hf_dlmap_harq_chase_frame_offset = -1; +static int hf_dlmap_harq_ir_ctc_n_ack_channel = -1; +static int hf_dlmap_harq_ir_ctc_nep = -1; +static int hf_dlmap_harq_ir_ctc_nsch = -1; +static int hf_dlmap_harq_ir_ctc_spid = -1; +static int hf_dlmap_harq_ir_ctc_acid = -1; +static int hf_dlmap_harq_ir_ctc_ai_sn = -1; +static int hf_dlmap_harq_ir_ctc_ack_disable = -1; +static int hf_dlmap_harq_ir_ctc_dedicated_dl_control_indicator = -1; +static int hf_dlmap_harq_ir_ctc_duration = -1; +static int hf_dlmap_harq_ir_ctc_allocation_index = -1; +static int hf_dlmap_harq_ir_ctc_period = -1; +static int hf_dlmap_harq_ir_ctc_frame_offset = -1; +static int hf_dlmap_harq_ir_cc_n_ack_channel = -1; +static int hf_dlmap_harq_ir_cc_duration = -1; +static int hf_dlmap_harq_ir_cc_sub_burst_diuc_indicator = -1; +static int hf_dlmap_harq_ir_cc_diuc = -1; +static int hf_dlmap_harq_ir_cc_repetition_coding_indication = -1; +static int hf_dlmap_harq_ir_cc_acid = -1; +static int hf_dlmap_harq_ir_cc_ai_sn = -1; +static int hf_dlmap_harq_ir_cc_spid = -1; +static int hf_dlmap_harq_ir_cc_ack_disable = -1; +static int hf_dlmap_harq_ir_cc_dedicated_dl_control_indicator = -1; +static int hf_dlmap_harq_ir_cc_allocation_index = -1; +static int hf_dlmap_harq_ir_cc_period = -1; +static int hf_dlmap_harq_ir_cc_frame_offset = -1; +static int hf_dlmap_mimo_dl_chase_harq_n_ack_channel = -1; +static int hf_dlmap_mimo_dl_chase_harq_mu_indicator = -1; +static int hf_dlmap_mimo_dl_chase_harq_dedicated_mimo_dl_control_indicator = -1; +static int hf_dlmap_mimo_dl_chase_harq_ack_disable = -1; +static int hf_dlmap_mimo_dl_chase_harq_duration = -1; +static int hf_dlmap_mimo_dl_chase_harq_diuc = -1; +static int hf_dlmap_mimo_dl_chase_harq_repetition_coding_indication = -1; +static int hf_dlmap_mimo_dl_chase_harq_acid = -1; +static int hf_dlmap_mimo_dl_chase_harq_ai_sn = -1; +static int hf_dlmap_mimo_dl_ir_harq_n_ack_channel = -1; +static int hf_dlmap_mimo_dl_ir_harq_mu_indicator = -1; +static int hf_dlmap_mimo_dl_ir_harq_dedicated_mimo_dl_control_indicator = -1; +static int hf_dlmap_mimo_dl_ir_harq_ack_disable = -1; +static int hf_dlmap_mimo_dl_ir_harq_nsch = -1; +static int hf_dlmap_mimo_dl_ir_harq_nep = -1; +static int hf_dlmap_mimo_dl_ir_harq_spid = -1; +static int hf_dlmap_mimo_dl_ir_harq_acid = -1; +static int hf_dlmap_mimo_dl_ir_harq_ai_sn = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_n_ack_channel = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_mu_indicator = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_dedicated_mimo_dl_control_indicator = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_ack_disable = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_duration = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_diuc = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_repetition_coding_indication = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_acid = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_ai_sn = -1; +static int hf_dlmap_mimo_dl_ir_harq_cc_spid = -1; +static int hf_dlmap_mimo_dl_stc_harq_n_ack_channel = -1; +static int hf_dlmap_mimo_dl_stc_harq_tx_count = -1; +static int hf_dlmap_mimo_dl_stc_harq_duration = -1; +static int hf_dlmap_mimo_dl_stc_harq_sub_burst_offset_indication = -1; +static int hf_dlmap_mimo_dl_stc_harq_sub_burst_offset = -1; +static int hf_dlmap_mimo_dl_stc_harq_ack_disable = -1; +static int hf_dlmap_mimo_dl_stc_harq_dedicated_mimo_dl_control_indicator = -1; +static int hf_dlmap_mimo_dl_stc_harq_diuc = -1; +static int hf_dlmap_mimo_dl_stc_harq_repetition_coding_indication = -1; +static int hf_dlmap_mimo_dl_stc_harq_acid = -1; +static int hf_dlmap_mbs_map_extended_2_diuc = -1; +static int hf_dlmap_mbs_map_mbs_zone_identifier = -1; +static int hf_dlmap_mbs_map_macro_diversity_enhanced = -1; +static int hf_dlmap_mbs_map_permutation = -1; +static int hf_dlmap_mbs_map_dl_permbase = -1; +static int hf_dlmap_mbs_map_prbs_id = -1; +static int hf_dlmap_mbs_map_ofdma_symbol_offset = -1; +static int hf_dlmap_mbs_map_diuc_change_indication = -1; +static int hf_dlmap_mbs_map_boosting = -1; +static int hf_dlmap_mbs_map_diuc = -1; +static int hf_dlmap_mbs_map_num_subchannels = -1; +static int hf_dlmap_mbs_map_num_ofdma_symbols = -1; +static int hf_dlmap_mbs_map_repetition_coding_indication = -1; +static int hf_dlmap_mbs_map_cid = -1; +static int hf_dlmap_mbs_map_ofdma_symbols_offset = -1; +static int hf_dlmap_mbs_map_subchannel_offset = -1; +static int hf_dlmap_mbs_map_slc_3_indication = -1; +static int hf_dlmap_mbs_map_next_mbs_map_ie_frame_offset = -1; +static int hf_dlmap_skip_extended_2_diuc = -1; +static int hf_dlmap_skip_mode = -1; +static int hf_dlmap_harq_dl_map_extended_2_diuc = -1; +static int hf_dlmap_harq_dl_map_rcid_type = -1; +static int hf_dlmap_harq_dl_map_boosting = -1; +static int hf_dlmap_harq_dl_map_region_id_use_indicator = -1; +static int hf_dlmap_harq_dl_map_ofdma_symbol_offset = -1; +static int hf_dlmap_harq_dl_map_subchannel_offset = -1; +static int hf_dlmap_harq_dl_map_number_of_ofdma_symbols = -1; +static int hf_dlmap_harq_dl_map_number_of_subchannels = -1; +static int hf_dlmap_harq_dl_map_rectangular_sub_burst_indicator = -1; +static int hf_dlmap_harq_dl_map_region_id = -1; +static int hf_dlmap_harq_dl_map_mode = -1; +static int hf_dlmap_harq_dl_map_sub_burst_ie_length = -1; +static int hf_dlmap_harq_dl_map_reserved_mode = -1; +static int hf_dlmap_harq_ack_bitmap_data = -1; +static int hf_dlmap_enhanced_dl_map_extended_2_diuc = -1; +static int hf_dlmap_enhanced_dl_map_num_assignment = -1; +static int hf_dlmap_enhanced_dl_map_n_cid = -1; +static int hf_dlmap_enhanced_dl_map_cid = -1; +static int hf_dlmap_enhanced_dl_map_diuc = -1; +static int hf_dlmap_enhanced_dl_map_boosting = -1; +static int hf_dlmap_enhanced_dl_map_repetition_coding_indication = -1; +static int hf_dlmap_enhanced_dl_map_region_id = -1; +static int hf_dlmap_aas_sdma_dl_extended_2_diuc = -1; +static int hf_dlmap_aas_sdma_dl_rcid_type = -1; +static int hf_dlmap_aas_sdma_dl_num_burst_region = -1; +static int hf_dlmap_aas_sdma_dl_ofdma_symbol_offset = -1; +static int hf_dlmap_aas_sdma_dl_subchannel_offset = -1; +static int hf_dlmap_aas_sdma_dl_num_ofdma_triple_symbols = -1; +static int hf_dlmap_aas_sdma_dl_num_subchannels = -1; +static int hf_dlmap_aas_sdma_dl_number_of_users = -1; +static int hf_dlmap_aas_sdma_dl_encoding_mode = -1; +static int hf_dlmap_aas_sdma_dl_cqich_allocation = -1; +static int hf_dlmap_aas_sdma_dl_ackch_allocation = -1; +static int hf_dlmap_aas_sdma_dl_pilot_pattern_modifier = -1; +static int hf_dlmap_aas_sdma_dl_preamble_modifier_index = -1; +static int hf_dlmap_aas_sdma_dl_pilot_pattern = -1; +static int hf_dlmap_aas_sdma_dl_diuc = -1; +static int hf_dlmap_aas_sdma_dl_repetition_coding_indication = -1; +static int hf_dlmap_aas_sdma_dl_ack_ch_index = -1; +static int hf_dlmap_aas_sdma_dl_acid = -1; +static int hf_dlmap_aas_sdma_dl_ai_sn = -1; +static int hf_dlmap_aas_sdma_dl_nep = -1; +static int hf_dlmap_aas_sdma_dl_nsch = -1; +static int hf_dlmap_aas_sdma_dl_spid = -1; +static int hf_dlmap_aas_sdma_dl_allocation_index = -1; +static int hf_dlmap_aas_sdma_dl_period = -1; +static int hf_dlmap_aas_sdma_dl_frame_offset = -1; +static int hf_dlmap_aas_sdma_dl_duration = -1; +static int hf_dlmap_channel_measurement_channel_nr = -1; +static int hf_dlmap_channel_measurement_ofdma_symbol_offset = -1; +static int hf_dlmap_channel_measurement_cid = -1; +static int hf_dlmap_stc_zone_ofdma_symbol_offset = -1; +static int hf_dlmap_stc_zone_permutations = -1; +static int hf_dlmap_stc_zone_use_all_sc_indicator = -1; +static int hf_dlmap_stc_zone_stc = -1; +static int hf_dlmap_stc_zone_matrix_indicator = -1; +static int hf_dlmap_stc_zone_dl_permbase = -1; +static int hf_dlmap_stc_zone_prbs_id = -1; +static int hf_dlmap_stc_zone_amc_type = -1; +static int hf_dlmap_stc_zone_midamble_presence = -1; +static int hf_dlmap_stc_zone_midamble_boosting = -1; +static int hf_dlmap_stc_zone_2_3_antenna_select = -1; +static int hf_dlmap_stc_zone_dedicated_pilots = -1; +static int hf_dlmap_aas_dl_ofdma_symbol_offset = -1; +static int hf_dlmap_aas_dl_permutation = -1; +static int hf_dlmap_aas_dl_dl_permbase = -1; +static int hf_dlmap_aas_dl_downlink_preamble_config = -1; +static int hf_dlmap_aas_dl_preamble_type = -1; +static int hf_dlmap_aas_dl_prbs_id = -1; +static int hf_dlmap_aas_dl_diversity_map = -1; +static int hf_dlmap_data_location_another_bs_segment = -1; +static int hf_dlmap_data_location_another_bs_used_subchannels = -1; +static int hf_dlmap_data_location_another_bs_diuc = -1; +static int hf_dlmap_data_location_another_bs_frame_advance = -1; +static int hf_dlmap_data_location_another_bs_ofdma_symbol_offset = -1; +static int hf_dlmap_data_location_another_bs_subchannel_offset = -1; +static int hf_dlmap_data_location_another_bs_boosting = -1; +static int hf_dlmap_data_location_another_bs_preamble_index = -1; +static int hf_dlmap_data_location_another_bs_num_ofdma_symbols = -1; +static int hf_dlmap_data_location_another_bs_num_subchannels = -1; +static int hf_dlmap_data_location_another_bs_repetition_coding_indication = -1; +static int hf_dlmap_data_location_another_bs_cid = -1; +static int hf_dlmap_harq_map_pointer_diuc = -1; +static int hf_dlmap_harq_map_pointer_num_slots = -1; +static int hf_dlmap_harq_map_pointer_repetition_coding_indication = -1; +static int hf_dlmap_harq_map_pointer_map_version = -1; +static int hf_dlmap_harq_map_pointer_idle_users = -1; +static int hf_dlmap_harq_map_pointer_sleep_users = -1; +static int hf_dlmap_harq_map_pointer_cid_mask_length = -1; +static int hf_dlmap_phymod_dl_preamble_modifier_type = -1; +static int hf_dlmap_phymod_dl_preamble_frequency_shift_index = -1; +static int hf_dlmap_phymod_dl_preamble_time_shift_index = -1; +static int hf_dlmap_phymod_dl_pilot_pattern_modifier = -1; +static int hf_dlmap_phymod_dl_pilot_pattern_index = -1; +static int hf_dlmap_broadcast_ctrl_ptr_dcd_ucd_transmission_frame = -1; +static int hf_dlmap_broadcast_ctrl_ptr_skip_broadcast_system_update = -1; +static int hf_dlmap_broadcast_ctrl_ptr_broadcast_system_update_type = -1; +static int hf_dlmap_broadcast_ctrl_ptr_broadcast_system_update_transmission_frame = -1; +static int hf_dlmap_dl_pusc_burst_allocation_cid = -1; +static int hf_dlmap_dl_pusc_burst_allocation_diuc = -1; +static int hf_dlmap_dl_pusc_burst_allocation_segment = -1; +static int hf_dlmap_dl_pusc_burst_allocation_boosting = -1; +static int hf_dlmap_dl_pusc_burst_allocation_idcell = -1; +static int hf_dlmap_dl_pusc_burst_allocation_dl_permbase = -1; +static int hf_dlmap_dl_pusc_burst_allocation_prbs_id = -1; +static int hf_dlmap_dl_pusc_burst_allocation_repetition_coding_indication = -1; +static int hf_dlmap_dl_pusc_burst_allocation_used_subchannels = -1; +static int hf_dlmap_dl_pusc_burst_allocation_ofdma_symbol_offset = -1; +static int hf_dlmap_dl_pusc_burst_allocation_num_ofdma_symbols = -1; +static int hf_dlmap_dl_pusc_burst_allocation_subchannel_offset = -1; +static int hf_dlmap_dl_pusc_burst_allocation_num_subchannels = -1; +static int hf_dlmap_pusc_asca_alloc_diuc = -1; +static int hf_dlmap_pusc_asca_alloc_short_basic_cid = -1; +static int hf_dlmap_pusc_asca_alloc_ofdma_symbol_offset = -1; +static int hf_dlmap_pusc_asca_alloc_subchannel_offset = -1; +static int hf_dlmap_pusc_asca_alloc_num_ofdma_symbols = -1; +static int hf_dlmap_pusc_asca_alloc_num_symbols = -1; +static int hf_dlmap_pusc_asca_alloc_repetition_coding_information = -1; +static int hf_dlmap_pusc_asca_alloc_permutation_id = -1; +static int hf_dlmap_reduced_aas_num_ie = -1; +static int hf_dlmap_reduced_aas_periodicity = -1; +static int hf_dlmap_reduced_aas_cid_included = -1; +static int hf_dlmap_reduced_aas_dcd_count_included = -1; +static int hf_dlmap_reduced_aas_phy_modification_included = -1; +static int hf_dlmap_reduced_aas_cqich_control_indicator = -1; +static int hf_dlmap_reduced_aas_encoding_mode = -1; +static int hf_dlmap_reduced_aas_separate_mcs_enabled = -1; +static int hf_dlmap_reduced_aas_duration = -1; +static int hf_dlmap_reduced_aas_diuc = -1; +static int hf_dlmap_reduced_aas_repetition_coding_indication = -1; +static int hf_dlmap_reduced_aas_cid = -1; +static int hf_dlmap_reduced_aas_allocation_index = -1; +static int hf_dlmap_reduced_aas_report_period = -1; +static int hf_dlmap_reduced_aas_frame_offset = -1; +static int hf_dlmap_reduced_aas_report_duration = -1; +static int hf_dlmap_reduced_aas_cqi_measurement_type = -1; +static int hf_dlmap_reduced_aas_dcd_count = -1; +static int hf_dlmap_reduced_aas_preamble_select = -1; +static int hf_dlmap_reduced_aas_preamble_shift_index = -1; +static int hf_dlmap_reduced_aas_pilot_pattern_modifier = -1; +static int hf_dlmap_reduced_aas_pilot_pattern_index = -1; +static int hf_dlmap_reduced_aas_dl_frame_offset = -1; +static int hf_dlmap_reduced_aas_zone_symbol_offset = -1; +static int hf_dlmap_reduced_aas_ofdma_symbol_offset = -1; +static int hf_dlmap_reduced_aas_subchannel_offset = -1; +static int hf_dlmap_reduced_aas_num_ofdma_triple_symbol = -1; +static int hf_dlmap_reduced_aas_num_subchannels = -1; +static int hf_dlmap_reduced_aas_num_ofdma_symbols = -1; +static int hf_dlmap_reduced_aas_diuc_nep = -1; +static int hf_dlmap_reduced_aas_dl_harq_ack_bitmap = -1; +static int hf_dlmap_reduced_aas_ack_allocation_index = -1; +static int hf_dlmap_reduced_aas_acid = -1; +static int hf_dlmap_reduced_aas_ai_sn = -1; +static int hf_dlmap_reduced_aas_nsch = -1; +static int hf_dlmap_reduced_aas_spid = -1; + + + +static expert_field ei_dlmap_not_implemented = EI_INIT; +static expert_field ei_crc16 = EI_INIT; +static expert_field ei_mac_header_compress_dlmap_crc = EI_INIT; +static expert_field ei_mac_header_invalid_length = EI_INIT; + +/* Copied and renamed from proto.c because global value_strings don't work for plugins */ +static const value_string plugin_proto_checksum_vals[] = { + { PROTO_CHECKSUM_E_BAD, "Bad" }, + { PROTO_CHECKSUM_E_GOOD, "Good" }, + { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" }, + { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" }, + + { 0, NULL } +}; + +/******************************************************************** + * DL-MAP Miscellaneous IEs and TLVs + *******************************************************************/ + +gint RCID_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb, gint RCID_Type_lcl) +{ + /* RCID_IE 8.4.5.3 and 8.4.5.3.20.1 */ + /* offset of IE in bits, length is variable */ + gint bit = offset; + proto_item *ti = NULL; + proto_tree *tree = NULL; + gint Prefix = 0; + gint cid = 0; + + if (RCID_Type_lcl == 0) + length = 16; + else { + Prefix = TVB_BIT_BIT(bit, tvb); + if (Prefix == 1) length = 12; + else if (RCID_Type_lcl == 1) length = 12; + else if (RCID_Type_lcl == 2) length = 8; + else if (RCID_Type_lcl == 3) length = 4; + } + + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, length), ett_286j, &ti, "RCID_IE"); + + if (RCID_Type_lcl == 0) { + XBIT_HF_VALUE(cid, 16, hf_dlmap_rcid_ie_cid); + } else { + XBIT_HF_VALUE(Prefix, 1, hf_dlmap_rcid_ie_prefix); + + if (Prefix == 1) { + /* RCID 11 */ + XBIT_HF_VALUE(cid, 11, hf_dlmap_rcid_ie_cid11); + } else { + if (RCID_Type_lcl == 1) { + /* RCID 11 */ + XBIT_HF_VALUE(cid, 11, hf_dlmap_rcid_ie_cid11); + } else if (RCID_Type_lcl == 2) { + /* RCID 7 */ + XBIT_HF_VALUE(cid, 7, hf_dlmap_rcid_ie_cid7); + } else if (RCID_Type_lcl == 3) { + /* RCID 3 */ + XBIT_HF_VALUE(cid, 3, hf_dlmap_rcid_ie_cid3); + } + } + } + + proto_item_append_text(ti, " (CID = %d)", cid); + + return length; /* return length in bits */ +} + +/******************************************************************** + * DL-MAP Extended-2 HARQ sub-burst IEs (8.4.5.3.21) + *******************************************************************/ + +static gint Dedicated_DL_Control_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.3.20 */ + /* offset of IE in nibbles, length is variable */ + gint nib; + gint nibble; + proto_tree *tree; + gint len; + + nib = offset; + + length = TVB_NIB_NIBBLE(nib, tvb); /* length in nibbles */ + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(nib, length+1), ett_286i, NULL, "Dedicated_DL_Control_IE"); + + VNIB(length, 1, hf_dlmap_dedicated_dl_control_length); + VNIB(nibble, 1, hf_dlmap_dedicated_dl_control_control_header); + + if ((nibble & 1) == 1) { + nibble = TVB_NIB_NIBBLE(nib, tvb); + proto_tree_add_uint(tree, hf_dlmap_dedicated_dl_control_num_sdma_layers, tvb, NIBHI(nib,1), (nibble >> 2) & 0x3); + /* Bit padding */ + if ((nib*4)+2 < (offset+length)*4) { + len = ((offset + length - nib) * 4) - 2; + proto_tree_add_bytes_format(tree, hf_reserved, tvb, BITHI(nib*4, len), NULL, "Reserved bits"); + } + } else { + /* Nibble padding */ + if (nib < offset+length) { + len = (offset + length) - nib; + proto_tree_add_bytes_format(tree, hf_reserved, tvb, NIBHI(nib,len), NULL, "Reserved bits"); + } + } + return (length + 1); +} + +static gint Dedicated_MIMO_DL_Control_IE(proto_tree *diuc_tree, gint offset, gint length _U_, tvbuff_t *tvb) +{ + /* offset of IE in bits, length is variable */ + gint bit; + proto_tree *tree; + gint mci, cqi, cmi, matrix = 0, pad, CQICH_num, mimo_mode; + gint j; + + bit = offset; + + /* 8.4.5.3.21 table 286t */ + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, 1), ett_286t, NULL, "Dedicated MIMO DL Control IE"); + + XBIT_HF_VALUE(length, 5, hf_dlmap_dedicated_mimo_dl_control_length); + XBIT_HF_VALUE(mci, 1, hf_dlmap_dedicated_mimo_dl_control_control_header_mimo_control_info); + XBIT_HF_VALUE(cqi, 1, hf_dlmap_dedicated_mimo_dl_control_control_header_cqi_control_info); + XBIT_HF_VALUE(cmi, 1, hf_dlmap_dedicated_mimo_dl_control_control_header_closed_mimo_control_info); + XBIT_HF_VALUE(N_layer, 2, hf_dlmap_dedicated_mimo_dl_control_n_layer); + + /* MIMO Control Info */ + if (mci == 1) { + XBIT_HF_VALUE(matrix, 2, hf_dlmap_dedicated_mimo_dl_control_matrix); + if (STC_Zone_Dedicated_Pilots == 1) { + XBIT_HF(2, hf_dlmap_dedicated_mimo_dl_control_num_beamformed_streams); + } + } + + /* CQICH Control Info */ + if (cqi == 1) { + XBIT_HF(3, hf_dlmap_dedicated_mimo_dl_control_period); + XBIT_HF(3, hf_dlmap_dedicated_mimo_dl_control_frame_offset); + XBIT_HF(4, hf_dlmap_dedicated_mimo_dl_control_duration); + for (j = 0; j < N_layer; j++) { + XBIT_HF(6, hf_dlmap_dedicated_mimo_dl_control_allocation_index); + } + XBIT_HF_VALUE(CQICH_num, 2, hf_dlmap_dedicated_mimo_dl_control_cqich_num); + for (j = 0; j < CQICH_num; j++) { + XBIT_HF(3, hf_dlmap_dedicated_mimo_dl_control_feedback_type); + XBIT_HF(6, hf_dlmap_dedicated_mimo_dl_control_allocation_index); + } + } + + /* Closed MIMO Control Info */ + if (cmi == 1) { + if (mci == 1) { + mimo_mode = matrix; + } else { + mimo_mode = STC_Zone_Matrix; + } + if (mimo_mode == 0 || mimo_mode == 1) { + XBIT_HF(3, hf_dlmap_dedicated_mimo_dl_control_antenna_grouping_index); + } else if (mimo_mode == 2) { + XBIT_HF(2, hf_dlmap_dedicated_mimo_dl_control_num_stream); + XBIT_HF(3, hf_dlmap_dedicated_mimo_dl_control_antenna_selection_index); + } else if (mimo_mode == 3) { + XBIT_HF(2, hf_dlmap_dedicated_mimo_dl_control_num_stream); + XBIT_HF(6, hf_dlmap_dedicated_mimo_dl_control_codebook_precoding_index); + } + } + + /* padding to nibble */ + pad = BIT_PADDING(bit,4); + if(pad){ + proto_tree_add_bytes_format_value(tree, hf_padding, tvb, BITHI(bit,pad), NULL, "%d bits", pad); + bit += pad; + } + + return (bit - offset); +} + +static gint DL_HARQ_Chase_sub_burst_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.3.21 DL_HARQ_Chase_sub_burst_IE */ + /* offset of IE in nibbles, length is variable */ + gint bit; + proto_tree *tree; + gint nsub, ddci, dur, sbi; + gint j; + + bit = NIB_TO_BIT(offset); + + /* 8.4.5.3.21 table 286m */ + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, length), ett_286m, NULL, "DL_HARQ_Chase_sub_burst_IE"); + + XBIT_HF_VALUE(nsub, 4, hf_dlmap_n_sub_burst_isi); + XBIT_HF(4, hf_dlmap_harq_chase_n_ack_channel); + + nsub += 1; + for (j = 0; j < nsub; j++) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + XBIT_HF_VALUE(dur, 10, hf_dlmap_harq_chase_duration); + XBIT_HF_VALUE(sbi, 1, hf_dlmap_harq_chase_sub_burst_diuc_indicator); + XBIT_HF(1, hf_dlmap_reserved_uint); + + if (sbi == 1) { + XBIT_HF(4, hf_dlmap_harq_chase_diuc); + XBIT_HF(2, hf_dlmap_harq_chase_repetition_coding_indication); + XBIT_HF(2, hf_dlmap_reserved_uint); + } + + XBIT_HF(4, hf_dlmap_harq_chase_acid); + XBIT_HF(1, hf_dlmap_harq_chase_ai_sn); + XBIT_HF(1, hf_dlmap_harq_chase_ack_disable); + XBIT_HF_VALUE(ddci, 2, hf_dlmap_harq_chase_dedicated_dl_control_indicator); + + if ((ddci & 1) == 1) { + XBIT_HF_VALUE(dur, 4, hf_dlmap_harq_chase_duration); + if (dur != 0) { + XBIT_HF(6, hf_dlmap_harq_chase_allocation_index); + XBIT_HF(3, hf_dlmap_harq_chase_period); + XBIT_HF(3, hf_dlmap_harq_chase_frame_offset); + } + } + + if ((ddci & 2) == 2) { + bit += Dedicated_DL_Control_IE(tree, BIT_TO_NIB(bit), length, tvb) * 4; + } + } + + /* XBIT_HF(data, 4, "(DL HARQ Chase sub-burst IE)"); */ + return (BIT_TO_NIB(bit) - offset); +} + +static gint DL_HARQ_IR_CTC_sub_burst_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* offset of IE in nibbles, length is variable */ + gint bit; + proto_tree *tree; + gint nsub, ddci, dur; + gint j; + guint32 calculated_crc; + + bit = NIB_TO_BIT(offset); + + /* 8.4.5.3.21 table 286n */ + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, 4), ett_286n, NULL, "DL HARQ IR CTC sub-burst IE"); + + XBIT_HF_VALUE(nsub, 4, hf_dlmap_n_sub_burst_isi); + XBIT_HF(4, hf_dlmap_harq_ir_ctc_n_ack_channel); + + nsub += 1; + for (j = 0; j < nsub; j++) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + + XBIT_HF(4, hf_dlmap_harq_ir_ctc_nep); + XBIT_HF(4, hf_dlmap_harq_ir_ctc_nsch); + XBIT_HF(2, hf_dlmap_harq_ir_ctc_spid); + XBIT_HF(4, hf_dlmap_harq_ir_ctc_acid); + XBIT_HF(1, hf_dlmap_harq_ir_ctc_ai_sn); + XBIT_HF(1, hf_dlmap_harq_ir_ctc_ack_disable); + XBIT_HF(2, hf_dlmap_reserved_uint); + XBIT_HF_VALUE(ddci, 2, hf_dlmap_harq_ir_ctc_dedicated_dl_control_indicator); + + if ((ddci & 1) == 1) { + XBIT_HF_VALUE(dur, 4, hf_dlmap_harq_ir_ctc_duration); + + if (dur != 0) { + XBIT_HF(6, hf_dlmap_harq_ir_ctc_allocation_index); + XBIT_HF(3, hf_dlmap_harq_ir_ctc_period); + XBIT_HF(3, hf_dlmap_harq_ir_ctc_frame_offset); + } + } + if ((ddci & 2) == 2) { + bit += Dedicated_DL_Control_IE(tree, BIT_TO_NIB(bit), length, tvb); + } + } + + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16(tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BIT_ADDR(bit), hf_crc16, hf_crc16_status, &ei_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + } + + return (BIT_TO_NIB(bit) - offset); +} + +static gint DL_HARQ_IR_CC_sub_burst_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* offset of IE in nibbles, length is variable */ + gint bit; + proto_tree *tree; + gint nsub, sbdi, ddci, dur; + gint j; + guint16 calculated_crc; + + bit = NIB_TO_BIT(offset); + + /* 8.4.5.3.21 table 286o */ + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, 4), ett_286o, NULL, "DL HARQ IR CC sub-burst IE"); + + XBIT_HF_VALUE(nsub, 4, hf_dlmap_n_sub_burst_isi); + XBIT_HF(4, hf_dlmap_harq_ir_cc_n_ack_channel); + + nsub += 1; + for (j = 0; j < nsub; j++) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type) / 4; + + XBIT_HF(10, hf_dlmap_harq_ir_cc_duration); + XBIT_HF_VALUE(sbdi, 1, hf_dlmap_harq_ir_cc_sub_burst_diuc_indicator); + XBIT_HF(1, hf_dlmap_reserved_uint); + + if (sbdi) { + XBIT_HF(4, hf_dlmap_harq_ir_cc_diuc); + XBIT_HF(2, hf_dlmap_harq_ir_cc_repetition_coding_indication); + XBIT_HF(2, hf_dlmap_reserved_uint); + } + + XBIT_HF(4, hf_dlmap_harq_ir_cc_acid); + XBIT_HF(1, hf_dlmap_harq_ir_cc_ai_sn); + XBIT_HF(2, hf_dlmap_harq_ir_cc_spid); + XBIT_HF(1, hf_dlmap_harq_ir_cc_ack_disable); + XBIT_HF_VALUE(ddci, 2, hf_dlmap_harq_ir_cc_dedicated_dl_control_indicator); + XBIT_HF(2, hf_dlmap_reserved_uint); + + if (ddci & 1) { + XBIT_HF_VALUE(dur, 4, hf_dlmap_harq_ir_cc_duration); + + if (dur != 0) { + XBIT_HF(6, hf_dlmap_harq_ir_cc_allocation_index); + XBIT_HF(3, hf_dlmap_harq_ir_cc_period); + XBIT_HF(3, hf_dlmap_harq_ir_cc_frame_offset); + } + } + if ((ddci & 2) == 2) { + bit += Dedicated_DL_Control_IE(tree, BIT_TO_NIB(bit), length, tvb); + } + } + + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16(tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BIT_ADDR(bit), hf_crc16, hf_crc16_status, &ei_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + } + + return (BIT_TO_NIB(bit) - offset); +} + +static gint MIMO_DL_Chase_HARQ_sub_burst_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* offset of IE in nibbles, length is variable */ + gint bit; + gint data; + proto_tree *tree; + gint nsub, mui, dci, akd; + gint i, j; + guint16 calculated_crc; + + bit = NIB_TO_BIT(offset); + + /* 8.4.5.3.21 table 286p */ + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, 1), ett_286p, NULL, "MIMO DL Chase HARQ sub-burst IE"); + + XBIT_HF_VALUE(nsub, 4, hf_dlmap_n_sub_burst_isi); + XBIT_HF(6, hf_dlmap_mimo_dl_chase_harq_n_ack_channel); + + nsub += 1; + for (j = 0; j < nsub; j++) { + XBIT_HF_VALUE(mui, 1, hf_dlmap_mimo_dl_chase_harq_mu_indicator); + XBIT_HF_VALUE(dci, 1, hf_dlmap_mimo_dl_chase_harq_dedicated_mimo_dl_control_indicator); + XBIT_HF_VALUE(akd, 1, hf_dlmap_mimo_dl_chase_harq_ack_disable); + if (mui == 0) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + if (dci == 1) { + bit += Dedicated_MIMO_DL_Control_IE(tree, bit, length, tvb); + } + XBIT_HF(10, hf_dlmap_mimo_dl_chase_harq_duration); + for (i = 0; i < N_layer; i++) { + if (mui == 1) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + XBIT_HF(4, hf_dlmap_mimo_dl_chase_harq_diuc); + XBIT_HF(2, hf_dlmap_mimo_dl_chase_harq_repetition_coding_indication); + if (akd == 0) { + XBIT_HF(4, hf_dlmap_mimo_dl_chase_harq_acid); + XBIT_HF(1, hf_dlmap_mimo_dl_chase_harq_ai_sn); + } + } + } + /* Padding to nibble */ + data = BIT_PADDING(bit, 4); + if (data) { + proto_tree_add_bytes_format_value(tree, hf_padding, tvb, BITHI(bit,data), NULL, "%d bits", data); + bit += data; + } + + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16(tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BIT_ADDR(bit), hf_crc16, hf_crc16_status, &ei_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + } + + return (BIT_TO_NIB(bit) - offset); +} + +static gint MIMO_DL_IR_HARQ_sub_burst_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* offset of IE in nibbles, length is variable */ + gint bit; + proto_tree *tree; + gint nsub, mui, dci, akd; + gint i, j; + guint16 calculated_crc; + + bit = NIB_TO_BIT(offset); + + /* 8.4.5.3.21 table 286q */ + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, 4), ett_286q, NULL, "MIMO DL IR HARQ sub-burst IE"); + + XBIT_HF_VALUE(nsub, 4, hf_dlmap_n_sub_burst_isi); + XBIT_HF(6, hf_dlmap_mimo_dl_ir_harq_n_ack_channel); + + nsub += 1; + for (j = 0; j < nsub; j++) { + XBIT_HF_VALUE(mui, 1, hf_dlmap_mimo_dl_ir_harq_mu_indicator); + XBIT_HF_VALUE(dci, 1, hf_dlmap_mimo_dl_ir_harq_dedicated_mimo_dl_control_indicator); + XBIT_HF_VALUE(akd, 1, hf_dlmap_mimo_dl_ir_harq_ack_disable); + if (mui == 0) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + if (dci == 1) { + bit += Dedicated_MIMO_DL_Control_IE(tree, bit, length, tvb); + } + XBIT_HF(4, hf_dlmap_mimo_dl_ir_harq_nsch); + for (i = 0; i < N_layer; i++) { + if (mui == 1) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + XBIT_HF(4, hf_dlmap_mimo_dl_ir_harq_nep); + if (akd) { + XBIT_HF(2, hf_dlmap_mimo_dl_ir_harq_spid); + XBIT_HF(4, hf_dlmap_mimo_dl_ir_harq_acid); + XBIT_HF(1, hf_dlmap_mimo_dl_ir_harq_ai_sn); + } + } + } + + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16(tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BIT_ADDR(bit), hf_crc16, hf_crc16_status, &ei_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + } + + return (BIT_TO_NIB(bit) - offset); +} + +static gint MIMO_DL_IR_HARQ_for_CC_sub_burst_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* offset of IE in nibbles, length is variable */ + gint bit; + proto_tree *tree; + gint nsub, mui, dci, akd; + gint i, j; + guint16 calculated_crc; + + bit = NIB_TO_BIT(offset); + + /* 8.4.5.3.21 table 286r */ + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, 1), ett_286r, NULL, "MIMO DL IR HARQ for CC sub-burst IE"); + + XBIT_HF_VALUE(nsub, 4, hf_dlmap_n_sub_burst_isi); + XBIT_HF(6, hf_dlmap_mimo_dl_ir_harq_cc_n_ack_channel); + + nsub += 1; + for (j = 0; j < nsub; j++) { + XBIT_HF_VALUE(mui, 1, hf_dlmap_mimo_dl_ir_harq_cc_mu_indicator); + XBIT_HF_VALUE(dci, 1, hf_dlmap_mimo_dl_ir_harq_cc_dedicated_mimo_dl_control_indicator); + XBIT_HF_VALUE(akd, 1, hf_dlmap_mimo_dl_ir_harq_cc_ack_disable); + if (mui == 0) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + if (dci == 1) { + bit += Dedicated_MIMO_DL_Control_IE(tree, bit, length, tvb); + } + XBIT_HF(10, hf_dlmap_mimo_dl_ir_harq_cc_duration); + for (i = 0; i < N_layer; i++) { + if (mui == 1) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + XBIT_HF(4, hf_dlmap_mimo_dl_ir_harq_cc_diuc); + XBIT_HF(2, hf_dlmap_mimo_dl_ir_harq_cc_repetition_coding_indication); + if (akd == 0) { + XBIT_HF(4, hf_dlmap_mimo_dl_ir_harq_cc_acid); + XBIT_HF(1, hf_dlmap_mimo_dl_ir_harq_cc_ai_sn); + XBIT_HF(2, hf_dlmap_mimo_dl_ir_harq_cc_spid); + } + } + } + + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16(tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BIT_ADDR(bit), hf_crc16, hf_crc16_status, &ei_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + } + + return (BIT_TO_NIB(bit) - offset); +} + +static gint MIMO_DL_STC_HARQ_sub_burst_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* offset of IE in nibbles, length is variable */ + gint bit; + proto_tree *tree; + gint nsub, sbi, txc, akd, dmci; + gint j; + guint16 calculated_crc; + + bit = NIB_TO_BIT(offset); + + /* 8.4.5.3.21 table 286s */ + tree = proto_tree_add_subtree(diuc_tree, tvb, BITHI(bit, 1), ett_286s, NULL, "MIMO DL STC HARQ sub-burst IE"); + + XBIT_HF_VALUE(nsub, 4, hf_dlmap_n_sub_burst_isi); + XBIT_HF(6, hf_dlmap_mimo_dl_stc_harq_n_ack_channel); + + nsub += 1; + for (j = 0; j < nsub; j++) { + XBIT_HF_VALUE(txc, 2, hf_dlmap_mimo_dl_stc_harq_tx_count); + XBIT_HF(10, hf_dlmap_mimo_dl_stc_harq_duration); + XBIT_HF_VALUE(sbi, 1, hf_dlmap_mimo_dl_stc_harq_sub_burst_offset_indication); + XBIT_HF(3, hf_dlmap_reserved_uint); + if (sbi == 1) { + XBIT_HF(8, hf_dlmap_mimo_dl_stc_harq_sub_burst_offset); + } + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + XBIT_HF_VALUE(akd, 1, hf_dlmap_mimo_dl_stc_harq_ack_disable); + if (txc == 0) { + XBIT_HF_VALUE(dmci, 1, hf_dlmap_mimo_dl_stc_harq_dedicated_mimo_dl_control_indicator); + if (dmci == 1) { + bit += Dedicated_MIMO_DL_Control_IE(tree, bit, length, tvb); + } + XBIT_HF(4, hf_dlmap_mimo_dl_stc_harq_diuc); + XBIT_HF(2, hf_dlmap_mimo_dl_stc_harq_repetition_coding_indication); + } + if (akd == 0) { + XBIT_HF(4, hf_dlmap_mimo_dl_stc_harq_acid); + } + } + + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16(tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BIT_ADDR(bit), hf_crc16, hf_crc16_status, &ei_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + } + + return (BIT_TO_NIB(bit) - offset); +} + +/******************************************************************** + * DL-MAP Extended-2 IEs + *******************************************************************/ + +static gint MBS_MAP_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 0 */ + /* 8.4.5.3.12 MBS_MAP_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + gint mde, dci, s3i; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286a, NULL, "MBS_MAP_IE"); + + XBIT_HF(4, hf_dlmap_mbs_map_extended_2_diuc); + VBIT(data, 8, hf_dlmap_ie_length); + + XBIT_HF(7, hf_dlmap_mbs_map_mbs_zone_identifier); + XBIT_HF_VALUE(mde, 1, hf_dlmap_mbs_map_macro_diversity_enhanced); + if (mde == 1) + { + XBIT_HF(2, hf_dlmap_mbs_map_permutation); + XBIT_HF(5, hf_dlmap_mbs_map_dl_permbase); + XBIT_HF(2, hf_dlmap_mbs_map_prbs_id); + XBIT_HF(7, hf_dlmap_mbs_map_ofdma_symbol_offset); + XBIT_HF_VALUE(dci, 1, hf_dlmap_mbs_map_diuc_change_indication); + XBIT_HF(3, hf_dlmap_reserved_uint); + if (dci == 1) { + XBIT_HF(3, hf_dlmap_reserved_uint); + XBIT_HF(3, hf_dlmap_mbs_map_boosting); + XBIT_HF(4, hf_dlmap_mbs_map_diuc); + XBIT_HF(6, hf_dlmap_mbs_map_num_subchannels); + XBIT_HF(6, hf_dlmap_mbs_map_num_ofdma_symbols); + XBIT_HF(2, hf_dlmap_mbs_map_repetition_coding_indication); + } + } else { + XBIT_HF(4, hf_dlmap_mbs_map_diuc); + XBIT_HF(16, hf_dlmap_mbs_map_cid); + XBIT_HF(8, hf_dlmap_mbs_map_ofdma_symbols_offset); + XBIT_HF(6, hf_dlmap_mbs_map_subchannel_offset); + XBIT_HF(3, hf_dlmap_mbs_map_boosting); + XBIT_HF_VALUE(s3i, 1, hf_dlmap_mbs_map_slc_3_indication); + XBIT_HF(6, hf_dlmap_mbs_map_num_ofdma_symbols); + XBIT_HF(6, hf_dlmap_mbs_map_num_subchannels); + XBIT_HF(2, hf_dlmap_mbs_map_repetition_coding_indication); + if (s3i == 1) { + XBIT_HF(8, hf_dlmap_mbs_map_next_mbs_map_ie_frame_offset); + } + } + data = BIT_PADDING(bit, 4); + if (data) { + proto_tree_add_bytes_format_value(tree, hf_padding, tvb, BITHI(bit,data), NULL, "%d bits", data); + bit += data; + } + return BIT_TO_NIB(bit); +} + +static gint HO_Anchor_Active_DL_MAP_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 1 */ + /* 8.4.5.3.14 [2] HO_Anchor_Active_DL-MAP_IE TODO 1.1 */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286c, NULL, "HO_Anchor_Active_DL_MAP_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + proto_tree_add_expert(diuc_tree, pinfo, &ei_dlmap_not_implemented, tvb, NIBHI(nib, length-3)); + return nib; +} + +static gint HO_Active_Anchor_DL_MAP_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 2 */ + /* 8.4.5.3.15 HO_Active_Anchor_DL_MAP_IE TODO 1.1 */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286d, NULL, "HO_Active_Anchor_DL_MAP_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + proto_tree_add_expert(diuc_tree, pinfo, &ei_dlmap_not_implemented, tvb, NIBHI(nib, length-3)); + return nib; +} + +static gint HO_CID_Translation_MAP_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 3 */ + /* 8.4.5.3.16 HO_CID_Translation_MAP_IE TODO 1.1 */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286e, NULL, "CID_Translation_MAP_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + proto_tree_add_expert(diuc_tree, pinfo, &ei_dlmap_not_implemented, tvb, NIBHI(nib, length-3)); + return nib; +} + +static gint MIMO_in_another_BS_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 4 */ + /* 8.4.5.3.17 [2] MIMO_in_another_BS_IE (not implemented)*/ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286f, NULL, "MIMO_in_another_BS_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + proto_tree_add_expert(diuc_tree, pinfo, &ei_dlmap_not_implemented, tvb, NIBHI(nib, length-3)); + return nib; +} + +static gint Macro_MIMO_DL_Basic_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* dl-map extended-2 ie = 5 */ + /* 8.4.5.3.18 [2] Macro-MIMO_DL_Basic_IE (not implemented) */ + /* offset of tlv in nibbles, length of tlv in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286g, NULL, "Macro_MIMO_DL_Basic_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + proto_tree_add_expert(diuc_tree, pinfo, &ei_dlmap_not_implemented, tvb, NIBHI(nib, length-3)); + return nib; +} + +static gint Skip_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 6 */ + /* 8.4.5.3.20.2 Skip_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286k, NULL, "Skip_IE"); + + XBIT_HF(4, hf_dlmap_skip_extended_2_diuc); + VBIT(data, 8, hf_dlmap_ie_length); + + XBIT_HF(1, hf_dlmap_skip_mode); + XBIT_HF(7, hf_dlmap_reserved_uint); + + return BIT_TO_NIB(bit); +} + +static gint HARQ_DL_MAP_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 7 */ + /* 8.4.5.3.21 [2] HARQ_DL_MAP_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_tree *tree; + gint len, lastbit, rui, mode, sub_len, pad; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286l, NULL, "HARQ_DL_MAP_IE"); + + XBIT_HF(4, hf_dlmap_harq_dl_map_extended_2_diuc); + VBIT(len, 2, hf_dlmap_ie_length); + + XBIT_HF_VALUE(RCID_Type, 2, hf_dlmap_harq_dl_map_rcid_type); + XBIT_HF(2, hf_dlmap_reserved_uint); + + /* while data remains */ + length = NIB_TO_BIT(length); + /* Subtract extra nibble to be sure to stop in time. */ + lastbit = bit + BYTE_TO_BIT(len) - 14 - 4; + while (bit < lastbit) { + XBIT_HF(3, hf_dlmap_harq_dl_map_boosting); + XBIT_HF_VALUE(rui, 1, hf_dlmap_harq_dl_map_region_id_use_indicator); + + if (rui == 0) { + XBIT_HF(8, hf_dlmap_harq_dl_map_ofdma_symbol_offset); + XBIT_HF(7, hf_dlmap_harq_dl_map_subchannel_offset); + XBIT_HF(7, hf_dlmap_harq_dl_map_number_of_ofdma_symbols); + XBIT_HF(7, hf_dlmap_harq_dl_map_number_of_subchannels); + if (include_cor2_changes) + { + XBIT_HF(1, hf_dlmap_harq_dl_map_rectangular_sub_burst_indicator); /* Implemented: "Rectangular Sub-Burst Indicator" field added */ + XBIT_HF(2, hf_dlmap_reserved_uint); /* and "Reserved" field resized from 3 bits to 2 bits */ + } + else + { + XBIT_HF(3, hf_dlmap_reserved_uint); + } + } else { + XBIT_HF(8, hf_dlmap_harq_dl_map_region_id); + } + XBIT_HF_VALUE(mode, 4, hf_dlmap_harq_dl_map_mode); + XBIT_HF_VALUE(sub_len, 8, hf_dlmap_harq_dl_map_sub_burst_ie_length); + + /* 8.4.5.3.21 */ + /* length of these are variable, each returns length in nibbles */ + if (mode == 0) { + DL_HARQ_Chase_sub_burst_IE(tree, BIT_TO_NIB(bit), length, tvb); + } else if (mode == 1) { + DL_HARQ_IR_CTC_sub_burst_IE(tree, pinfo, BIT_TO_NIB(bit), length, tvb); + } else if (mode == 2) { + DL_HARQ_IR_CC_sub_burst_IE(tree, pinfo, BIT_TO_NIB(bit), length, tvb); + } else if (mode == 3) { + MIMO_DL_Chase_HARQ_sub_burst_IE(tree, pinfo, BIT_TO_NIB(bit), length, tvb); + } else if (mode == 4) { + MIMO_DL_IR_HARQ_sub_burst_IE(tree, pinfo, BIT_TO_NIB(bit), length, tvb); + } else if (mode == 5) { + MIMO_DL_IR_HARQ_for_CC_sub_burst_IE(tree, pinfo, BIT_TO_NIB(bit), length, tvb); + } else if (mode == 6) { + MIMO_DL_STC_HARQ_sub_burst_IE(tree, pinfo, BIT_TO_NIB(bit), length, tvb); + } else { + proto_tree_add_bits_item(tree, hf_dlmap_harq_dl_map_reserved_mode, tvb, bit, 1, ENC_BIG_ENDIAN); + break; /* cannot continue */ + } + bit += NIB_TO_BIT(sub_len); + } + + pad = NIB_TO_BIT(offset) + length - bit; + if (pad) { + proto_tree_add_bytes_format_value(tree, hf_padding, tvb, BITHI(bit,pad), NULL, "%d bits",pad); + bit += pad; + } + + return BIT_TO_NIB(bit); +} + +static gint HARQ_ACK_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 8 */ + /* 8.4.5.3.22 HARQ_ACK IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint data; + gint nib; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286u, NULL, "HARQ_ACK_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + + proto_tree_add_item(diuc_tree, hf_dlmap_harq_ack_bitmap_data, tvb, NIBHI(nib,length-3), ENC_NA); + + return nib; +} + +static gint Enhanced_DL_MAP_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 9 */ + /* 8.4.5.3.23 Enhanced DL MAP IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + gint numass, n_cid; + gint i, n; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286v, NULL, "Enhanced_DL-MAP_IE"); + + XBIT_HF(4, hf_dlmap_enhanced_dl_map_extended_2_diuc); + VBIT(data, 8, hf_dlmap_ie_length); + + XBIT_HF_VALUE(numass, 4, hf_dlmap_enhanced_dl_map_num_assignment); + for (i = 0; i < numass; i++) { + if (INC_CID == 1) { + XBIT_HF_VALUE(n_cid, 8, hf_dlmap_enhanced_dl_map_n_cid); + for (n = 0; n < n_cid; n++) { + XBIT_HF(16, hf_dlmap_enhanced_dl_map_cid); + } + } + XBIT_HF(4, hf_dlmap_enhanced_dl_map_diuc); + XBIT_HF(3, hf_dlmap_enhanced_dl_map_boosting); + XBIT_HF(2, hf_dlmap_enhanced_dl_map_repetition_coding_indication); + XBIT_HF(8, hf_dlmap_enhanced_dl_map_region_id); + XBIT_HF(3, hf_dlmap_reserved_uint); + } + return BIT_TO_NIB(bit); +} + +static gint Closed_loop_MIMO_DL_Enhanced_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 0xA */ + /* 8.4.5.3.24 Closed-loop MIMO DL Enhanced IE (not implemented) */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286w, NULL, "CL_MIMO_DL_Enhanced_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + proto_tree_add_expert(diuc_tree, pinfo, &ei_dlmap_not_implemented, tvb, NIBHI(nib, length-3)); + return nib; +} + +static gint AAS_SDMA_DL_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended-2 IE = 0xE */ + /* 8.4.5.3.26 AAS_SDMA_DL_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + gint num_region, num_users, pilot_pattern, encoding_mode, ackch_alloc, cqich_alloc; + gint aas_preamble = 1; + gint zone_permut = 0; /* TODO */ + gint i, j; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286y, NULL, "AAS_SDMA_DL_IE"); + + XBIT_HF(4, hf_dlmap_aas_sdma_dl_extended_2_diuc); + VBIT(data, 8, hf_dlmap_ie_length); + + XBIT_HF_VALUE(RCID_Type, 2, hf_dlmap_aas_sdma_dl_rcid_type); + XBIT_HF_VALUE(num_region, 4, hf_dlmap_aas_sdma_dl_num_burst_region); + XBIT_HF(2, hf_dlmap_reserved_uint); + for (i = 0; i < num_region; i++) { + XBIT_HF(8, hf_dlmap_aas_sdma_dl_ofdma_symbol_offset); + if (zone_permut == 0) { + XBIT_HF(8, hf_dlmap_aas_sdma_dl_subchannel_offset); + XBIT_HF(5, hf_dlmap_aas_sdma_dl_num_ofdma_triple_symbols); + XBIT_HF(6, hf_dlmap_aas_sdma_dl_num_subchannels); + } else { + XBIT_HF(6, hf_dlmap_aas_sdma_dl_subchannel_offset); + XBIT_HF(7, hf_dlmap_aas_sdma_dl_num_ofdma_triple_symbols); + XBIT_HF(6, hf_dlmap_aas_sdma_dl_num_subchannels); + } + XBIT_HF_VALUE(num_users, 3, hf_dlmap_aas_sdma_dl_number_of_users); + XBIT_HF(2, hf_dlmap_reserved_uint); + for (j = 0; j < num_users; j++) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + XBIT_HF_VALUE(encoding_mode, 2, hf_dlmap_aas_sdma_dl_encoding_mode); + XBIT_HF_VALUE(cqich_alloc, 1, hf_dlmap_aas_sdma_dl_cqich_allocation); + XBIT_HF_VALUE(ackch_alloc, 1, hf_dlmap_aas_sdma_dl_ackch_allocation); + XBIT_HF_VALUE(pilot_pattern, 1, hf_dlmap_aas_sdma_dl_pilot_pattern_modifier); + if (aas_preamble) { + XBIT_HF(4, hf_dlmap_aas_sdma_dl_preamble_modifier_index); + } + if (pilot_pattern) { + XBIT_HF(2, hf_dlmap_aas_sdma_dl_pilot_pattern); + XBIT_HF(1, hf_dlmap_reserved_uint); + } else { + XBIT_HF(3, hf_dlmap_reserved_uint); + } + if (encoding_mode == 0x0) { + XBIT_HF(4, hf_dlmap_aas_sdma_dl_diuc); + XBIT_HF(2, hf_dlmap_aas_sdma_dl_repetition_coding_indication); + XBIT_HF(2, hf_dlmap_reserved_uint); + } + if (encoding_mode == 0x1) { + if (ackch_alloc) { + XBIT_HF(5, hf_dlmap_aas_sdma_dl_ack_ch_index); + } else { + XBIT_HF(1, hf_dlmap_reserved_uint); + } + XBIT_HF(4, hf_dlmap_aas_sdma_dl_diuc); + XBIT_HF(2, hf_dlmap_aas_sdma_dl_repetition_coding_indication); + XBIT_HF(4, hf_dlmap_aas_sdma_dl_acid); + XBIT_HF(1, hf_dlmap_aas_sdma_dl_ai_sn); + } + if (encoding_mode == 0x2) { + if (ackch_alloc) { + XBIT_HF(5, hf_dlmap_aas_sdma_dl_ack_ch_index); + } else { + XBIT_HF(1, hf_dlmap_reserved_uint); + } + XBIT_HF(4, hf_dlmap_aas_sdma_dl_nep); + XBIT_HF(4, hf_dlmap_aas_sdma_dl_nsch); + XBIT_HF(2, hf_dlmap_aas_sdma_dl_spid); + XBIT_HF(4, hf_dlmap_aas_sdma_dl_acid); + XBIT_HF(1, hf_dlmap_aas_sdma_dl_ai_sn); + } + if (encoding_mode == 0x3) { + if (ackch_alloc) { + XBIT_HF(5, hf_dlmap_aas_sdma_dl_ack_ch_index); + XBIT_HF(2, hf_dlmap_reserved_uint); + } else { + XBIT_HF(3, hf_dlmap_reserved_uint); + } + XBIT_HF(4, hf_dlmap_aas_sdma_dl_diuc); + XBIT_HF(2, hf_dlmap_aas_sdma_dl_repetition_coding_indication); + XBIT_HF(2, hf_dlmap_aas_sdma_dl_spid); + XBIT_HF(4, hf_dlmap_aas_sdma_dl_acid); + XBIT_HF(1, hf_dlmap_aas_sdma_dl_ai_sn); + } + if (cqich_alloc) { + XBIT_HF(6, hf_dlmap_aas_sdma_dl_allocation_index); + XBIT_HF(3, hf_dlmap_aas_sdma_dl_period); + XBIT_HF(3, hf_dlmap_aas_sdma_dl_frame_offset); + XBIT_HF(4, hf_dlmap_aas_sdma_dl_duration); + } + } + } + data = BIT_PADDING(bit,4); + /* Should this be an optional field? Or do we want it, even if it has a length of zero? */ + proto_tree_add_bytes_format_value(tree, hf_padding, tvb, BITHI(bit,data), NULL, "%d bits", data); + bit += data; + + return BIT_TO_NIB(bit); +} + + + +/******************************************************************** + * DL-MAP Extended IEs + *******************************************************************/ + +static gint Channel_Measurement_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 0 */ + /* 8.4.5.3.5 [1] Channel_Measurement_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_280, NULL, "Channel_Measurement_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext); + VNIB(data, 1, hf_dlmap_ie_length); + + VNIB(data, 2, hf_dlmap_channel_measurement_channel_nr); + VNIB(data, 2, hf_dlmap_channel_measurement_ofdma_symbol_offset); + VNIB(data, 4, hf_dlmap_channel_measurement_cid); + return nib; +} + +static gint STC_Zone_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 1 */ + /* 8.4.5.3.4 STC_Zone_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + /* set globals: STC_Zone_Dedicated_Pilots, STC_Zone_Matrix + * used in 8.4.5.3.21.1 Dedicated MIMO Control IE 286t */ + gint bit; + gint data; + proto_tree *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_279, NULL, "STC_Zone_IE"); + + VBIT(data, 4, hf_dlmap_ie_diuc_ext); + VBIT(data, 4, hf_dlmap_ie_length); + + XBIT_HF(8, hf_dlmap_stc_zone_ofdma_symbol_offset); + XBIT_HF(2, hf_dlmap_stc_zone_permutations); + XBIT_HF(1, hf_dlmap_stc_zone_use_all_sc_indicator); + XBIT_HF(2, hf_dlmap_stc_zone_stc); + XBIT_HF_VALUE(STC_Zone_Matrix, 2, hf_dlmap_stc_zone_matrix_indicator); + XBIT_HF(5, hf_dlmap_stc_zone_dl_permbase); + XBIT_HF(2, hf_dlmap_stc_zone_prbs_id); + XBIT_HF(2, hf_dlmap_stc_zone_amc_type); + XBIT_HF(1, hf_dlmap_stc_zone_midamble_presence); + XBIT_HF(1, hf_dlmap_stc_zone_midamble_boosting); + XBIT_HF(1, hf_dlmap_stc_zone_2_3_antenna_select); + XBIT_HF_VALUE(STC_Zone_Dedicated_Pilots, 1, hf_dlmap_stc_zone_dedicated_pilots); + XBIT_HF(4, hf_dlmap_reserved_uint); + + return BIT_TO_NIB(bit); +} + +static gint AAS_DL_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 2 */ + /* 8.4.5.3.3 AAS_DL_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_278, NULL, "AAS_DL_IE"); + + VBIT(data, 4, hf_dlmap_ie_diuc_ext); + VBIT(data, 4, hf_dlmap_ie_length); + + XBIT_HF(8, hf_dlmap_aas_dl_ofdma_symbol_offset); + XBIT_HF(3, hf_dlmap_aas_dl_permutation); + XBIT_HF(6, hf_dlmap_aas_dl_dl_permbase); + XBIT_HF(2, hf_dlmap_aas_dl_downlink_preamble_config); + XBIT_HF(1, hf_dlmap_aas_dl_preamble_type); + XBIT_HF(2, hf_dlmap_aas_dl_prbs_id); + XBIT_HF(1, hf_dlmap_aas_dl_diversity_map); + XBIT_HF(1, hf_dlmap_reserved_uint); + + return BIT_TO_NIB(bit); +} + +static gint Data_location_in_another_BS_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 3 */ + /* 8.4.5.3.6 Data_location_in_another_BS_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_281, NULL, "Data location in another BS IE"); + + VBIT(data, 4, hf_dlmap_ie_diuc_ext); + VBIT(data, 4, hf_dlmap_ie_length); + + XBIT_HF(2, hf_dlmap_data_location_another_bs_segment); + XBIT_HF(6, hf_dlmap_data_location_another_bs_used_subchannels); + XBIT_HF(4, hf_dlmap_data_location_another_bs_diuc); + XBIT_HF(3, hf_dlmap_data_location_another_bs_frame_advance); + XBIT_HF(1, hf_dlmap_reserved_uint); + XBIT_HF(8, hf_dlmap_data_location_another_bs_ofdma_symbol_offset); + XBIT_HF(6, hf_dlmap_data_location_another_bs_subchannel_offset); + XBIT_HF(3, hf_dlmap_data_location_another_bs_boosting); + XBIT_HF(7, hf_dlmap_data_location_another_bs_preamble_index); + XBIT_HF(8, hf_dlmap_data_location_another_bs_num_ofdma_symbols); + XBIT_HF(6, hf_dlmap_data_location_another_bs_num_subchannels); + XBIT_HF(2, hf_dlmap_data_location_another_bs_repetition_coding_indication); + XBIT_HF(16, hf_dlmap_data_location_another_bs_cid); + + return BIT_TO_NIB(bit); +} + +static gint CID_Switch_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 4 */ + /* 8.4.5.3.7 [1] CID_Switch_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + INC_CID = INC_CID ? 0 : 1; + + tree = proto_tree_add_subtree_format(diuc_tree, tvb, NIBHI(offset, length), ett_282, NULL, "CID_Switch_IE (INC_CID = %d)", INC_CID); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext); + VNIB(data, 1, hf_dlmap_ie_length); + + return nib; +} + +static gint MIMO_DL_Basic_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 5 */ + /* 8.4.5.3.8 MIMO_DL_Basic_IE (not implemented) */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_283, NULL, "MIMO_DL_Basic_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + proto_tree_add_expert(diuc_tree, pinfo, &ei_dlmap_not_implemented, tvb, NIBHI(nib, length-2)); + return nib; +} + +static gint MIMO_DL_Enhanced_IE(proto_tree *diuc_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 6 */ + /* 8.4.5.3.9 MIMO_DL_Enhanced_IE (not implemented) */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_tree *tree; + + nib = offset; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_284, NULL, "MIMO_DL_Enhanced_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext2); + VNIB(data, 2, hf_dlmap_ie_length); + proto_tree_add_expert(diuc_tree, pinfo, &ei_dlmap_not_implemented, tvb, NIBHI(nib, length-2)); + return nib; +} + +static gint HARQ_Map_Pointer_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 7 */ + /* 8.4.5.3.10 [2] HARQ_Map_Pointer_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + gint length_in_bits, map, mask_len; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_285, NULL, "HARQ_Map_Pointer_IE"); + + VBIT(data, 4, hf_dlmap_ie_diuc_ext); + VBIT(data, 4, hf_dlmap_ie_length); + + length_in_bits = NIB_TO_BIT(length-1); + while (bit < length_in_bits) { + XBIT_HF(4, hf_dlmap_harq_map_pointer_diuc); + XBIT_HF(8, hf_dlmap_harq_map_pointer_num_slots); + XBIT_HF(2, hf_dlmap_harq_map_pointer_repetition_coding_indication); + XBIT_HF_VALUE(map, 2, hf_dlmap_harq_map_pointer_map_version); + if (map == 2) { + XBIT_HF(1, hf_dlmap_harq_map_pointer_idle_users); + XBIT_HF(1, hf_dlmap_harq_map_pointer_sleep_users); + XBIT_HF_VALUE(mask_len, 2, hf_dlmap_harq_map_pointer_cid_mask_length); + if (mask_len == 0) { + /* 12 bits */ + proto_tree_add_bytes_format_value(diuc_tree, hf_cid_mask, tvb, BITHI(bit,12), NULL, "12 bits"); + bit += 12; + } else if (mask_len == 1) { + /* 20 bits */ + proto_tree_add_bytes_format_value(diuc_tree, hf_cid_mask, tvb, BITHI(bit,20), NULL, "20 bits"); + bit += 20; + } else if (mask_len == 2) { + /* 36 bits */ + proto_tree_add_bytes_format_value(diuc_tree, hf_cid_mask, tvb, BITHI(bit,36), NULL, "36 bits"); + bit += 36; + } else if (mask_len == 3) { + /* 52 bits */ + proto_tree_add_bytes_format_value(diuc_tree, hf_cid_mask, tvb, BITHI(bit,52), NULL, "52 bits"); + bit += 52; + } + } + } + return BIT_TO_NIB(bit); +} + +static gint PHYMOD_DL_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 8 */ + /* 8.4.5.3.11 PHYMOD_DL_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + gint pmt; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286, NULL, "PHYMOD_DL_IE"); + + VBIT(data, 4, hf_dlmap_ie_diuc_ext); + VBIT(data, 4, hf_dlmap_ie_length); + + XBIT_HF_VALUE(pmt, 1, hf_dlmap_phymod_dl_preamble_modifier_type); + if (pmt == 0) { + XBIT_HF(4, hf_dlmap_phymod_dl_preamble_frequency_shift_index); + } else { + XBIT_HF(4, hf_dlmap_phymod_dl_preamble_time_shift_index); + } + XBIT_HF(1, hf_dlmap_phymod_dl_pilot_pattern_modifier); + XBIT_HF(2, hf_dlmap_phymod_dl_pilot_pattern_index); + + return BIT_TO_NIB(bit); +} + +static gint Broadcast_Control_Pointer_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 0xA */ + /* 8.4.5.3.25 Broadcast Control Pointer IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + gint skip; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286x, NULL, "Broadcast Control Pointer IE"); + + VBIT(data, 4, hf_dlmap_ie_diuc_ext); + VBIT(data, 4, hf_dlmap_ie_length); + + XBIT_HF(7, hf_dlmap_broadcast_ctrl_ptr_dcd_ucd_transmission_frame); + XBIT_HF_VALUE(skip, 1, hf_dlmap_broadcast_ctrl_ptr_skip_broadcast_system_update); + if (skip == 0) { + XBIT_HF(1, hf_dlmap_broadcast_ctrl_ptr_broadcast_system_update_type); + XBIT_HF(7, hf_dlmap_broadcast_ctrl_ptr_broadcast_system_update_transmission_frame); + } + return BIT_TO_NIB(bit); +} + +static gint DL_PUSC_Burst_Allocation_in_Other_Segment_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 0xB */ + /* 8.4.5.3.13 DL PUSC Burst Allocation in Other Segment IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286b, NULL, "DL_PUSC_Burst_Allocation_in_Other_Segment_IE"); + + VBIT(data, 4, hf_dlmap_ie_diuc_ext); + VBIT(data, 4, hf_dlmap_ie_length); + + XBIT_HF(16, hf_dlmap_dl_pusc_burst_allocation_cid); + XBIT_HF(4, hf_dlmap_dl_pusc_burst_allocation_diuc); + XBIT_HF(2, hf_dlmap_dl_pusc_burst_allocation_segment); + XBIT_HF(3, hf_dlmap_dl_pusc_burst_allocation_boosting); + XBIT_HF(5, hf_dlmap_dl_pusc_burst_allocation_idcell); + XBIT_HF(5, hf_dlmap_dl_pusc_burst_allocation_dl_permbase); + XBIT_HF(2, hf_dlmap_dl_pusc_burst_allocation_prbs_id); + XBIT_HF(2, hf_dlmap_dl_pusc_burst_allocation_repetition_coding_indication); + XBIT_HF(6, hf_dlmap_dl_pusc_burst_allocation_used_subchannels); + XBIT_HF(8, hf_dlmap_dl_pusc_burst_allocation_ofdma_symbol_offset); + XBIT_HF(1, hf_dlmap_reserved_uint); + XBIT_HF(7, hf_dlmap_dl_pusc_burst_allocation_num_ofdma_symbols); + XBIT_HF(6, hf_dlmap_dl_pusc_burst_allocation_subchannel_offset); + XBIT_HF(6, hf_dlmap_dl_pusc_burst_allocation_num_subchannels); + XBIT_HF(7, hf_dlmap_reserved_uint); + return BIT_TO_NIB(bit); +} + +static gint PUSC_ASCA_Alloc_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 0xC */ + /* 8.4.5.3.27 PUSC_ASCA_Alloc_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_tree *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286z, NULL, "PUSC_ASCA_Alloc_IE"); + + VBIT(data, 4, hf_dlmap_ie_diuc_ext); + VBIT(data, 4, hf_dlmap_ie_length); + XBIT_HF(4, hf_dlmap_pusc_asca_alloc_diuc); + XBIT_HF(12, hf_dlmap_pusc_asca_alloc_short_basic_cid); + XBIT_HF(8, hf_dlmap_pusc_asca_alloc_ofdma_symbol_offset); + XBIT_HF(6, hf_dlmap_pusc_asca_alloc_subchannel_offset); + XBIT_HF(7, hf_dlmap_pusc_asca_alloc_num_ofdma_symbols); + XBIT_HF(6, hf_dlmap_pusc_asca_alloc_num_symbols); + XBIT_HF(2, hf_dlmap_pusc_asca_alloc_repetition_coding_information); + XBIT_HF(4, hf_dlmap_pusc_asca_alloc_permutation_id); + XBIT_HF(7, hf_dlmap_reserved_uint); + + return BIT_TO_NIB(bit); +} + +static gint UL_interference_and_noise_level_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* DL-MAP Extended IE = 0xF */ + /* 8.4.5.3.19 UL_interference_and_noise_level_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + proto_tree *tree; + gint nib = offset; + gint bitmap, data; + + tree = proto_tree_add_subtree(diuc_tree, tvb, NIBHI(offset, length), ett_286h, NULL, "UL_interference_and_noise_level_IE"); + + VNIB(data, 1, hf_dlmap_ie_diuc_ext); + VNIB(data, 1, hf_dlmap_ie_length); + VNIB(bitmap, 2, hf_dlmap_ie_bitmap); + + if (bitmap & 0x01) { + VNIB(data, 2, hf_dlmap_ie_bitmap_cqi); + } + if (bitmap & 0x02) { + VNIB(data, 2, hf_dlmap_ie_bitmap_pusc); + } + if (bitmap & 0x04) { + VNIB(data, 2, hf_dlmap_ie_bitmap_opt_pusc); + } + if (bitmap & 0x08) { + VNIB(data, 2, hf_dlmap_ie_bitmap_amc); + } + if (bitmap & 0x10) { + VNIB(data, 2, hf_dlmap_ie_bitmap_aas); + } + if (bitmap & 0x20) { + VNIB(data, 2, hf_dlmap_ie_bitmap_periodic_ranging); + } + if (bitmap & 0x40) { + VNIB(data, 2, hf_dlmap_ie_bitmap_sounding); + } + if (bitmap & 0x80) { + VNIB(data, 2, hf_dlmap_ie_bitmap_mimo); + } + + return nib; +} + +/******************************************************************** + * DL-MAP Plugin + *******************************************************************/ + +static gint dissect_dlmap_ie(proto_tree *ie_tree, packet_info *pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* decode a single DL-MAP IE and return the + * length of the IE in nibbles + * offset = start of IE (nibbles) + * length = total length of IE (nibbles) */ + proto_item *ti = NULL; + proto_tree *tree = NULL; + + gint nibble = offset; + gint diuc; + gint ext2_diuc; + gint len; + gint ext_diuc; + + gint alt_format = 0; + guint data = 0; + gint i; + /*gint papr = 0;*/ + gint ie_len = 9; + + gint n_cid; + + /* 8.4.5.3 DL-MAP IE format - table 275 */ + diuc = TVB_NIB_NIBBLE(nibble, tvb); + if (diuc == 14) + { + /* 8.4.5.3.2.2 [2] Extended-2 DIUC dependent IE table 277b */ + ext2_diuc = TVB_NIB_NIBBLE(1+nibble, tvb); + len = TVB_NIB_BYTE(1+nibble+1, tvb); + + ti = proto_tree_add_uint(ie_tree, hf_dlmap_ie_diuc, tvb, NIBHI(nibble, 1+3+len*2), diuc); + proto_item_append_text(ti, " (Extended-2)"); + tree = proto_item_add_subtree(ti, ett_277b); + nibble++; + + len = 3 + BYTE_TO_NIB(len); + + /* table 277c [2] */ + switch (ext2_diuc) + { + case 0x00: + /* 8.4.5.3.12 MBS_MAP_IE */ + nibble = MBS_MAP_IE(tree, nibble, len, tvb); + break; + case 0x01: + /* 8.4.5.3.14 HO_Anchor_Active_DL-MAP_IE */ + nibble = HO_Anchor_Active_DL_MAP_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x02: + /* 8.4.5.3.15 HO_Active_Anchor_DL_MAP_IE */ + nibble = HO_Active_Anchor_DL_MAP_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x03: + /* 8.4.5.3.16 HO_CID_Translation_MAP_IE */ + nibble = HO_CID_Translation_MAP_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x04: + /* 8.4.5.3.17 MIMO_in_another_BS_IE */ + nibble = MIMO_in_another_BS_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x05: + /* 8.4.5.3.18 Macro-MIMO_DL_Basic_IE */ + nibble = Macro_MIMO_DL_Basic_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x06: + /* 8.4.5.3.20.2 Skip_IE */ + nibble = Skip_IE(tree, nibble, len, tvb); + break; + case 0x07: + /* 8.4.5.3.21 HARQ_DL_MAP_IE */ + nibble = HARQ_DL_MAP_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x08: + /* 8.4.5.3.22 HARQ_ACK IE */ + nibble = HARQ_ACK_IE(tree, nibble, len, tvb); + break; + case 0x09: + /* 8.4.5.3.23 Enhanced DL MAP IE */ + nibble = Enhanced_DL_MAP_IE(tree, nibble, len, tvb); + break; + case 0x0a: + /* 8.4.5.3.24 Closed-loop MIMO DL Enhanced IE */ + nibble = Closed_loop_MIMO_DL_Enhanced_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x0b: + nibble = MIMO_DL_Basic_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x0c: + nibble = MIMO_DL_Enhanced_IE(tree, pinfo, nibble, len, tvb); + break; + + case 0x0e: + nibble = AAS_SDMA_DL_IE(tree, nibble, len, tvb); + break; + + default: + proto_tree_add_bytes_format(tree, hf_dlmap_ie_reserved_extended2_duic, tvb, NIBHI(nibble,len), NULL, "(reserved Extended-2 DIUC: %d)", ext2_diuc); + nibble += len; + break; + + } + } + else if (diuc == 15) + { + /* 8.4.5.3.2.1 [1] Extended DIUC dependent IE - table 277 */ + ext_diuc = TVB_NIB_NIBBLE(1+nibble, tvb); + len = TVB_NIB_NIBBLE(1+nibble+1, tvb); + + ti = proto_tree_add_uint(ie_tree, hf_dlmap_ie_diuc, tvb, NIBHI(nibble, 1+2+len*2), diuc); + proto_item_append_text(ti, " (Extended)"); + tree = proto_item_add_subtree(ti, ett_277); + nibble++; + + len = 2 + BYTE_TO_NIB(len); + + /* TODO 8.4.5.3.27 PUSC_ASCA_IE -- unspecified ExtDIUC? */ + + /* 8.4.5.3.2.1 table 277a */ + switch (ext_diuc) + { + case 0x00: + /* 8.4.5.3.? Channel_Measurement_IE */ + nibble = Channel_Measurement_IE(tree, nibble, len, tvb); + break; + case 0x01: + /* 8.4.5.3.4 STC_Zone_IE */ + nibble = STC_Zone_IE(tree, nibble, len, tvb); + break; + case 0x02: + /* 8.4.5.3.3 AAS_DL_IE */ + nibble = AAS_DL_IE(tree, nibble, len, tvb); + break; + case 0x03: + /* 8.4.5.3.6 Data_location_in_another_BS_IE */ + nibble = Data_location_in_another_BS_IE(tree, nibble, len, tvb); + break; + case 0x04: + /* 8.4.5.3.7 CID_Switch_IE */ + nibble = CID_Switch_IE(tree, nibble, len, tvb); + break; + case 0x07: + /* 8.4.5.3.10 HARQ_Map_Pointer_IE */ + nibble = HARQ_Map_Pointer_IE(tree, nibble, len, tvb); + break; + case 0x08: + /* 8.4.5.3.11 PHYMOD_DL_IE */ + nibble = PHYMOD_DL_IE(tree, nibble, len, tvb); + break; + case 0x0a: + /* 8.4.5.3.25 Broadcast Control Pointer IE */ + nibble = Broadcast_Control_Pointer_IE(tree, nibble, len, tvb); + break; + case 0x0b: + /* 8.4.5.3.13 DL PUSC Burst Allocation in Other Segment IE */ + nibble = DL_PUSC_Burst_Allocation_in_Other_Segment_IE(tree, nibble, len, tvb); + break; + case 0x0c: + nibble = PUSC_ASCA_Alloc_IE(tree, nibble, len, tvb); + break; + + case 0x0f: + /* 8.4.5.3.19 UL_interference_and_noise_level_IE */ + nibble = UL_interference_and_noise_level_IE(tree, nibble, len, tvb); + break; + + default: + proto_tree_add_bytes_format(tree, hf_dlmap_ie_reserved_extended_duic, tvb, NIBHI(nibble,len), NULL, "(reserved Extended DIUC: %d)", ext_diuc); + nibble += len; + break; + } + } + else + { + /* Downlink IE */ + alt_format = 0; + /*papr = 0; XX: not used ? */ + ie_len = 9; + + /* TODO: alt_format = 1 if (Permutation == 0x11) and (AMC type is 2x3 or 1x6) */ + + /* precalculate IE len for correct highlighting */ + if (INC_CID && !sub_dl_ul_map) { + ie_len += 2 + (TVB_NIB_BYTE(nibble+1, tvb) * 4); + } + + /* DL-MAP_IE */ + ti = proto_tree_add_uint(ie_tree, hf_dlmap_ie_diuc, tvb, NIBHI(nibble, ie_len), diuc); + tree = proto_item_add_subtree(ti, ett_275_1); + nibble += 1; + + if (diuc == 13) { + /* 8.4.5.3.1 [1] Gap/PAPR Reduction */ + /*papr = 1; XX: not used ? */ + proto_item_append_text(ti, " (Gap/PAPR Reduction)"); + } + + + if (INC_CID) + { + n_cid = TVB_NIB_BYTE(nibble, tvb); + proto_tree_add_uint(tree, hf_dlmap_ie_ncid, tvb, NIBHI(nibble, 2), n_cid); + nibble += 2; + + for (i = 0; i < n_cid; i++) + { + if (sub_dl_ul_map) { + /* RCID_IE 8.4.5.3 and 8.4.5.3.20.1, only part of SUB-DL-UL-MAP */ + /* RCID_Type comes from 6.3.2.3.43.2 [2] Format_configuration_IE in Compact_DL-MAP_IE */ + nibble += RCID_IE(tree, nibble*4, length, tvb, RCID_Type) / 4; + } else { + data = TVB_NIB_WORD(nibble, tvb); + proto_tree_add_uint(tree, hf_dlmap_ie_cid, tvb, NIBHI(nibble, 4), data); + nibble += 4; + } + } + } + + data = TVB_NIB_LONG(nibble, tvb); + if (alt_format) { + proto_tree_add_uint(tree, hf_dlmap_ie_offsym2, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_offsub2, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_boosting2, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_numsym2, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_numsub2, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_rep2, tvb, NIBHI(nibble, 8), data); + } else { + proto_tree_add_uint(tree, hf_dlmap_ie_offsym, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_offsub, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_boosting, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_numsym, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_numsub, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_dlmap_ie_rep, tvb, NIBHI(nibble, 8), data); + } + nibble += 8; + } + + /* length in nibbles */ + return (nibble - offset); +} + + +static int dissect_mac_mgmt_msg_dlmap_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *base_tree, void* data _U_) +{ + /* 6.3.2.3.2 [2] DL-MAP table 16 */ + guint offset = 0; + gint length, nib, pad; + proto_item *ti = NULL; + proto_tree *dlmap_tree = NULL; + proto_tree *ie_tree = NULL; + proto_tree *phy_tree = NULL; + gint tvb_len = tvb_reported_length(tvb); + + INC_CID = 0; + + /* add protocol */ + ti = proto_tree_add_protocol_format(base_tree, proto_mac_mgmt_msg_dlmap_decoder, tvb, offset, -1, "DL-MAP"); + dlmap_tree = proto_item_add_subtree(ti, ett_dlmap); + + /* PHY Synchronization Field 8.4.5.1 */ + { + phy_tree = proto_tree_add_subtree(dlmap_tree, tvb, offset, 4, ett_275_phy, NULL, "Phy Synchronization Field"); + proto_tree_add_item(phy_tree, hf_dlmap_phy_fdur_ms, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(phy_tree, hf_dlmap_phy_fdur_per_sec, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(phy_tree, hf_dlmap_phy_fdur, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + proto_tree_add_item(phy_tree, hf_dlmap_phy_fnum, tvb, offset, 3, ENC_BIG_ENDIAN); + offset += 3; + } + proto_tree_add_item(dlmap_tree, hf_dlmap_dcd, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + proto_tree_add_item(dlmap_tree, hf_dlmap_bsid, tvb, offset, 6, ENC_NA); + offset += 6; + proto_tree_add_item(dlmap_tree, hf_dlmap_ofdma_sym, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + /* DL-MAP IEs */ + length = tvb_len - offset; /* remaining length in bytes */ + ie_tree = proto_tree_add_subtree_format(dlmap_tree, tvb, offset, length, ett_dlmap_ie, NULL, "DL-MAP IEs (%d bytes)", length); + + /* length = BYTE_TO_NIB(length); */ /* convert length to nibbles */ + + nib = BYTE_TO_NIB(offset); + while (nib < ((tvb_len*2)-1)) { + nib += dissect_dlmap_ie(ie_tree, pinfo, nib, tvb_len * 2, tvb); + } + pad = NIB_PADDING(nib); + if (pad) { + proto_tree_add_bytes_format(dlmap_tree, hf_padding, tvb, NIBHI(nib,1), NULL, "Padding nibble"); + nib++; + } + return tvb_captured_length(tvb); +} + +gint wimax_decode_dlmapc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *base_tree) +{ + /* 8.4.5.6.1 [2] Compressed DL-MAP */ + /* decode a compressed dl-map and return the length in bytes; */ + /* if there is a compressed ul-map, also decode that and include in the length */ + guint offset = 0; + proto_item *ti = NULL; + proto_item *ti_phy = NULL; + proto_item *ti_dlmap_ies = NULL; + proto_tree *tree = NULL; + proto_tree *ie_tree = NULL; + proto_tree *phy_tree = NULL; + gint ulmap_appended; + guint length, lennib, pad; + guint mac_len, dl_ie_count; + guint tvb_len = tvb_reported_length(tvb); + guint nib = 0; + guint32 mac_crc, calculated_crc; + + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Compressed DL-MAP"); + + INC_CID = 0; + + length = tvb_get_ntohs(tvb, offset) & 0x07FF; /* compressed map length is 11 bits */ + mac_len = length; + lennib = BYTE_TO_NIB(length); + + ulmap_appended = (tvb_get_guint8(tvb, offset) >> 4) & 1; /* UL MAP appended? */ + + /* display MAC Compressed DL-MAP and create subtree */ + ti = proto_tree_add_protocol_format(base_tree, proto_mac_mgmt_msg_dlmap_decoder, tvb, offset, length, "Compressed DL-MAP (%u bytes)", length); + tree = proto_item_add_subtree(ti, ett_305); + + /* decode dlmap fields */ + proto_tree_add_item(tree, hf_dlmapc_compr, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_dlmapc_ulmap, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_dlmapc_rsv, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_dlmapc_len, tvb, offset, 2, ENC_BIG_ENDIAN); + /* PHY Synchronization Field 8.4.5.1 */ + { + phy_tree = proto_tree_add_subtree(tree, tvb, offset+2, 4, ett_275_phy, &ti_phy, "Phy Synchronization Field"); + proto_tree_add_item(phy_tree, hf_dlmap_phy_fdur_ms, tvb, offset+2, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(phy_tree, hf_dlmap_phy_fdur_per_sec, tvb, offset+2, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(phy_tree, hf_dlmap_phy_fnum, tvb, offset+3, 3, ENC_BIG_ENDIAN); + } + proto_tree_add_item(tree, hf_dlmap_dcd, tvb, offset+6, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_dlmapc_opid, tvb, offset+7, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_dlmapc_secid, tvb, offset+8, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_dlmap_ofdma_sym, tvb, offset+9, 1, ENC_BIG_ENDIAN); /* 2005 */ + proto_tree_add_item(tree, hf_dlmapc_count, tvb, offset+10,1, ENC_BIG_ENDIAN); + dl_ie_count = tvb_get_guint8(tvb, offset + 10); + offset += 11; + nib = BYTE_TO_NIB(offset); + + /* DL-MAP IEs */ + length -= 15; /* remaining length in bytes (11 bytes above + CRC at end) */ + if (dl_ie_count) { + ie_tree = proto_tree_add_subtree_format(tree, tvb, offset, length, ett_dlmap_ie, &ti_dlmap_ies, "DL-MAP IEs (%d bytes)", length); + + /* length = BYTE_TO_NIB(mac_len - (int)sizeof(mac_crc) - 1); */ /* convert length to nibbles */ + + while (dl_ie_count--) { + nib += dissect_dlmap_ie(ie_tree, pinfo, nib, tvb_len * 2, tvb); + } + pad = NIB_PADDING(nib); + if (pad) { + proto_tree_add_bytes_format(tree, hf_padding, tvb, NIBHI(nib,1), NULL, "Padding nibble"); + nib++; + } + } + + if (ulmap_appended) { + /* Replace the text of items to set the correct length in bytes.*/ + proto_item_set_text(ti, "Compressed DL-MAP (%u bytes)", NIB_ADDR(nib)); + proto_item_set_text(ti_dlmap_ies, "DL-MAP IEs (%u bytes)",NIB_ADDR(nib)- offset); + + /* set the length of items */ + proto_item_set_end(ti_dlmap_ies, tvb, NIB_ADDR(nib)); + proto_item_set_end(ti, tvb, NIB_ADDR(nib)); + + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Compressed UL-MAP"); + + /* subtract 8 from lennib (CRC) */ + wimax_decode_ulmapc(base_tree, pinfo, nib, lennib - 8, tvb); + } + + /* CRC is always appended */ + /* check the length */ + if (mac_len <= sizeof(mac_crc)) + { + expert_add_info_format(pinfo, ti, &ei_mac_header_invalid_length, + "Invalid length: %d.", mac_len); + return sizeof(mac_crc); + } + else if (MIN(tvb_len, tvb_reported_length(tvb)) >= mac_len) + { + /* calculate the CRC */ + calculated_crc = wimax_mac_calc_crc32(tvb_get_ptr(tvb, 0, mac_len - (int)sizeof(mac_crc)), mac_len - (int)sizeof(mac_crc)); + proto_tree_add_checksum(base_tree, tvb, mac_len - (int)sizeof(mac_crc), hf_mac_header_compress_dlmap_crc, hf_mac_header_compress_dlmap_crc_status, &ei_mac_header_compress_dlmap_crc, + pinfo, calculated_crc, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + } + else + { /* display error message */ + proto_tree_add_protocol_format(base_tree, proto_mac_mgmt_msg_dlmap_decoder, tvb, 0, tvb_len, "CRC missing - the frame is too short (%u bytes)", tvb_len); + } + + return mac_len; +} +#if 0 +static gint wimax_decode_sub_dl_ul_map(tvbuff_t *tvb, packet_info *pinfo, proto_tree *base_tree) +{ + /* decode a SUB-DL-UL-MAP message 6.3.2.3.60 and return the length in bytes */ + /* first three bits are 0x7, which following a compressed DL map indicates this message */ + proto_tree *tree = NULL; + proto_tree *ie_tree = NULL; + proto_item *generic_item = NULL; + gint data; + gint i, numie; + guint16 calculated_crc; + + gint length = tvb_reported_length(tvb); + gint nib = 0; + gint lennib = BYTE_TO_NIB(length); + + sub_dl_ul_map = 1; /* set flag */ + + tree = proto_tree_add_subtree(base_tree, tvb, NIBHI(nib,lennib-nib), ett_109x, NULL, "SUB-DL-UL-MAP"); + + data = TVB_NIB_WORD(nib,tvb); + proto_tree_add_uint(tree, hf_109x_cmi, tvb, NIBHI(nib,4), data); + proto_tree_add_uint(tree, hf_109x_len, tvb, NIBHI(nib,4), data); + proto_tree_add_uint(tree, hf_109x_rcid, tvb, NIBHI(nib,4), data); + proto_tree_add_uint(tree, hf_109x_haoi, tvb, NIBHI(nib,4), data); + nib += 4; + + /* HARQ ACK offset indicator */ + if (data & 1) { + data = TVB_NIB_BYTE(nib,tvb); + proto_tree_add_uint(tree, hf_109x_dl, tvb, NIBHI(nib,2), data); + nib += 2; + data = TVB_NIB_BYTE(nib,tvb); + proto_tree_add_uint(tree, hf_109x_ul, tvb, NIBHI(nib,2), data); + nib += 2; + } + + numie = TVB_NIB_BYTE(nib,tvb); + proto_tree_add_uint(tree, hf_109x_dlie, tvb, NIBHI(nib,2), numie); + nib += 2; + + /* DL-MAP IEs */ + ie_tree = proto_tree_add_subtree(tree, tvb, NIBHI(nib,1), ett_109x_dl, NULL, "DL-MAP IEs"); + for (i = 0; i < numie; i++) { + nib += dissect_dlmap_ie(ie_tree, pinfo, nib, lennib - nib, tvb); + } + + data = TVB_NIB_BYTE(nib,tvb); + proto_tree_add_uint(tree, hf_109x_symofs, tvb, NIBHI(nib,2), data); + nib += 2; + data = TVB_NIB_BYTE(nib,tvb); + proto_tree_add_uint(tree, hf_109x_subofs, tvb, NIBHI(nib,2), data); + proto_tree_add_uint(tree, hf_109x_rsv, tvb, NIBHI(nib,2), data); + nib += 2; + + /* UL-MAP IEs */ + ie_tree = proto_tree_add_subtree(tree, tvb, NIBHI(nib,lennib-nib), ett_109x_ul, NULL, "UL-MAP IEs"); + for ( ; nib < lennib - 1; ) { + nib += dissect_ulmap_ie(ie_tree, nib, lennib - nib, tvb); + } + + /* padding */ + if (nib & 1) { + proto_tree_add_bytes_format(tree, hf_padding, tvb, NIBHI(nib,1), NULL, "Padding Nibble"); + nib++; + } + + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16(tvb_get_ptr(tvb, 0, NIB_TO_BYTE(nib)), NIB_TO_BYTE(nib)); + proto_tree_add_checksum(tree, tvb, NIBHI(nib,4), hf_crc16, hf_crc16_status, &ei_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + /* nib += 4; */ + + sub_dl_ul_map = 0; /* clear flag */ + /* return length */ + return length; +} +#endif + +gint wimax_decode_dlmap_reduced_aas(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *base_tree) +{ + /* 8.4.5.8.1 [2] Reduced AAS private DL-MAP */ + /* if there is an appended UL-MAP, also decode that */ + guint offset = 0; + proto_item *ti = NULL; + proto_tree *tree = NULL; + gint ulmap_appended; + gint length; + gint tvb_len = tvb_reported_length(tvb); + gint bit = 0; + guint data, pad, mult; + gint numie = 1; + gint i; + guint16 calculated_crc; + gint smcs,cidi,dcdi,phyi,cqci; + + length = tvb_len; + + /* display MAC Reduced_AAS_Private_DL-MAP and create subtree */ + ti = proto_tree_add_protocol_format(base_tree, proto_mac_mgmt_msg_dlmap_decoder, tvb, offset, length, "Reduced_AAS_Private_DL-MAP"); + tree = proto_item_add_subtree(ti, ett_308a); + + VBIT(data, 3, hf_308a_cmi); + VBIT(ulmap_appended, 1, hf_308a_ulmap); + VBIT(data, 2, hf_308a_type); + VBIT(mult, 1, hf_308a_mult); + VBIT(data, 1, hf_308a_rsv); + + if (mult) { + XBIT_HF_VALUE(numie, 8, hf_dlmap_reduced_aas_num_ie); + } + + for (i = 0; i < numie; i++) { + XBIT_HF(2, hf_dlmap_reduced_aas_periodicity); + XBIT_HF_VALUE(cidi, 1, hf_dlmap_reduced_aas_cid_included); + XBIT_HF_VALUE(dcdi, 1, hf_dlmap_reduced_aas_dcd_count_included); + XBIT_HF_VALUE(phyi, 1, hf_dlmap_reduced_aas_phy_modification_included); + XBIT_HF_VALUE(cqci, 1, hf_dlmap_reduced_aas_cqich_control_indicator); + XBIT_HF(2, hf_dlmap_reduced_aas_encoding_mode); + XBIT_HF_VALUE(smcs, 1, hf_dlmap_reduced_aas_separate_mcs_enabled); + + if (smcs) { + XBIT_HF(10, hf_dlmap_reduced_aas_duration); + XBIT_HF(4, hf_dlmap_reduced_aas_diuc); + XBIT_HF(2, hf_dlmap_reduced_aas_repetition_coding_indication); + } + if (cidi) { + XBIT_HF(16, hf_dlmap_reduced_aas_cid); + } + if (cqci) { + XBIT_HF(6, hf_dlmap_reduced_aas_allocation_index); + XBIT_HF(3, hf_dlmap_reduced_aas_report_period); + XBIT_HF(3, hf_dlmap_reduced_aas_frame_offset); + XBIT_HF(4, hf_dlmap_reduced_aas_report_duration); + XBIT_HF(2, hf_dlmap_reduced_aas_cqi_measurement_type); + XBIT_HF(2, hf_dlmap_reserved_uint); + } + if (dcdi) { + XBIT_HF(8, hf_dlmap_reduced_aas_dcd_count); + } + if (phyi) { + XBIT_HF(1, hf_dlmap_reduced_aas_preamble_select); + XBIT_HF(4, hf_dlmap_reduced_aas_preamble_shift_index); + XBIT_HF(1, hf_dlmap_reduced_aas_pilot_pattern_modifier); + XBIT_HF(2, hf_dlmap_reduced_aas_pilot_pattern_index); + } + XBIT_HF(3, hf_dlmap_reduced_aas_dl_frame_offset); + if (fusc) { + XBIT_HF(8, hf_dlmap_reduced_aas_zone_symbol_offset); + } + XBIT_HF(8, hf_dlmap_reduced_aas_ofdma_symbol_offset); + if (tusc) { + XBIT_HF(8, hf_dlmap_reduced_aas_subchannel_offset); + XBIT_HF(5, hf_dlmap_reduced_aas_num_ofdma_triple_symbol); + XBIT_HF(6, hf_dlmap_reduced_aas_num_subchannels); + } else { + XBIT_HF(6, hf_dlmap_reduced_aas_subchannel_offset); + XBIT_HF(7, hf_dlmap_reduced_aas_num_ofdma_symbols); + XBIT_HF(6, hf_dlmap_reduced_aas_num_subchannels); + } + XBIT_HF(4, hf_dlmap_reduced_aas_diuc_nep); + if (harq) { + XBIT_HF(1, hf_dlmap_reduced_aas_dl_harq_ack_bitmap); + XBIT_HF(6, hf_dlmap_reduced_aas_ack_allocation_index); + XBIT_HF(4, hf_dlmap_reduced_aas_acid); + XBIT_HF(1, hf_dlmap_reduced_aas_ai_sn); + if (ir_type) { + XBIT_HF(4, hf_dlmap_reduced_aas_nsch); + XBIT_HF(2, hf_dlmap_reduced_aas_spid); + XBIT_HF(2, hf_dlmap_reserved_uint); + } + } + XBIT_HF(2, hf_dlmap_reduced_aas_repetition_coding_indication); + if (ulmap_appended) { + /* offset and length are in bits */ + bit += wimax_decode_ulmap_reduced_aas(tree, offset, length*8, tvb); + } + XBIT_HF(3, hf_dlmap_reserved_uint); + } + + /* padding */ + pad = BIT_PADDING(bit,8); + if (pad) { + proto_tree_add_bytes_format_value(tree, hf_padding, tvb, BITHI(bit,pad), NULL, "%d bits",pad); + bit += pad; + } + + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16(tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BIT_ADDR(bit), hf_crc16, hf_crc16_status, &ei_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + + return BIT_TO_BYTE(bit) - offset; +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_dlmap(void) +{ + /* DL-MAP fields display */ + static hf_register_info hf[] = + { + { + &hf_dlmap_bsid, + { + "Base Station ID", "wmx.dlmap.bsid", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_dcd, + { + "DCD Count", "wmx.dlmap.dcd", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#if 0 + { + &hf_dlmap_fch_expected, + { + "FCH Expected", "wmx.dlmap.fch_expected", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie, + { + "DL-MAP IE", "wmx.dlmap.ie", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#endif + { + &hf_dlmap_ie_boosting, + { + "Boosting", "wmx.dlmap.ie.boosting", + FT_UINT32, BASE_DEC, VALS(boost_msgs), 0x00038000, NULL, HFILL + } + }, + { + &hf_dlmap_ie_boosting2, + { + "Boosting", "wmx.dlmap.ie.boosting", + FT_UINT32, BASE_DEC, VALS(boost_msgs), 0x0000E000, NULL, HFILL + } + }, + { + &hf_dlmap_ie_cid, + { + "CID", "wmx.dlmap.ie.cid", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_diuc, + { + "DIUC", "wmx.dlmap.ie.diuc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_diuc_ext, + { + "Extended DIUC", "wmx.dlmap.ie.ext_diuc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_diuc_ext2, + { + "Extended-2 DIUC", "wmx.dlmap.ie.ext2_diuc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_reserved_extended2_duic, + { + "Reserved Extended-2 DIUC", "wmx.dlmap.ie.ext2_diuc_reserved", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_reserved_extended_duic, + { + "Reserved Extended DIUC", "wmx.dlmap.ie.ext_diuc_reserved", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_length, + { + "Length", "wmx.dlmap.ie.length", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap, + { + "Bitmap", "wmx.dlmap.ie.bitmap", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap_cqi, + { + "CQI/ACK/Periodic Ranging region NI", "wmx.dlmap.ie.bitmap.cqi", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap_pusc, + { + "PUSC region NI", "wmx.dlmap.ie.bitmap.pusc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap_opt_pusc, + { + "Optional PUSC region NI", "wmx.dlmap.ie.bitmap.opt_pusc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap_amc, + { + "AMC region NI", "wmx.dlmap.ie.bitmap.amc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap_aas, + { + "AAS region NI", "wmx.dlmap.ie.bitmap.aas", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap_periodic_ranging, + { + "Periodic Ranging region NI", "wmx.dlmap.ie.bitmap.periodic_ranging", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap_sounding, + { + "Sounding region NI", "wmx.dlmap.ie.bitmap.sounding", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_bitmap_mimo, + { + "MIMO region NI", "wmx.dlmap.ie.bitmap.mimo", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_ncid, + { + "N_CID", "wmx.dlmap.ie.ncid", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_ie_numsub, + { + "Number of Subchannels", "wmx.dlmap.ie.numsub", + FT_UINT32, BASE_DEC, NULL, 0x000000FC, NULL, HFILL + } + }, + { + &hf_dlmap_ie_numsym, + { + "Number of OFDMA Symbols", "wmx.dlmap.ie.numsym", + FT_UINT32, BASE_DEC, NULL, 0x00007F00, NULL, HFILL + } + }, + { + &hf_dlmap_ie_numsub2, + { + "Number of Subchannels", "wmx.dlmap.ie.numsub", + FT_UINT32, BASE_DEC, NULL, 0x000000FC, NULL, HFILL + } + }, + { + &hf_dlmap_ie_numsym2, + { + "Number of OFDMA Symbols", "wmx.dlmap.ie.numsym", + FT_UINT32, BASE_DEC, NULL, 0x00001F00, NULL, HFILL + } + }, + { + &hf_dlmap_ie_offsub, + { + "Subchannel Offset", "wmx.dlmap.ie.offsub", + FT_UINT32, BASE_DEC, NULL, 0x00FC0000, NULL, HFILL + } + }, + { + &hf_dlmap_ie_offsym, + { + "OFDMA Symbol Offset", "wmx.dlmap.ie.offsym", + FT_UINT32, BASE_DEC, NULL, 0xFF000000, NULL, HFILL + } + }, + /* alt ie format */ + { + &hf_dlmap_ie_offsub2, + { + "Subchannel Offset", "wmx.dlmap.ie.offsub", + FT_UINT32, BASE_DEC, NULL, 0x00FF0000, NULL, HFILL + } + }, + { + &hf_dlmap_ie_offsym2, + { + "OFDMA Symbol Offset", "wmx.dlmap.ie.offsym", + FT_UINT32, BASE_DEC, NULL, 0xFF000000, NULL, HFILL + } + }, + { + &hf_dlmap_ie_rep, + { + "Repetition Coding Indication", "wmx.dlmap.ie.rep", + FT_UINT32, BASE_DEC, VALS(rep_msgs), 0x00000003, NULL, HFILL + } + }, + { + &hf_dlmap_ie_rep2, + { + "Repetition Coding Indication", "wmx.dlmap.ie.rep", + FT_UINT32, BASE_DEC, VALS(rep_msgs), 0x00000003, NULL, HFILL + } + }, + { + &hf_dlmap_ofdma_sym, + { + "Num OFDMA Symbols", "wmx.dlmap.ofdma_sym", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_phy_fdur, + { + "Frame Duration Code", "wmx.dlmap.phy_fdur", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_dlmap_phy_fdur_ms, + { + "Frame Duration", "wmx.dlmap.phy_fdur", + FT_UINT8, BASE_HEX, VALS(frame_duration), 0x00, NULL, HFILL + } + }, + { + &hf_dlmap_phy_fdur_per_sec, + { + "Frames per second", "wmx.dlmap.phy_fdur", + FT_UINT8, BASE_HEX, VALS(frames_per_second), 0x00, NULL, HFILL + } + }, + { + &hf_dlmap_phy_fnum, + { + "Frame Number", "wmx.dlmap.phy_fnum", + FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmapc_compr, + { + "Compressed map indicator", "wmx.dlmapc.compr", + FT_UINT16, BASE_DEC, NULL, 0xe000, NULL, HFILL + } + }, + { + &hf_dlmapc_count, + { + "DL IE Count", "wmx.dlmapc.count", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmapc_len, + { + "Map message length", "wmx.dlmapc.len", + FT_UINT16, BASE_DEC, NULL, 0x07FF, NULL, HFILL + } + }, + { + &hf_dlmapc_opid, + { + "Operator ID", "wmx.dlmapc.opid", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmapc_rsv, + { + "Reserved", "wmx.dlmapc.rsv", + FT_UINT16, BASE_DEC, NULL, 0x0800, NULL, HFILL + } + }, + { + &hf_dlmapc_secid, + { + "Sector ID", "wmx.dlmapc.secid", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#if 0 + { + &hf_dlmapc_sync, + { + "PHY Synchronization Field", "wmx.dlmapc.sync", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#endif + { + &hf_dlmapc_ulmap, + { + "UL-MAP appended", "wmx.dlmapc.ulmap", + FT_UINT16, BASE_DEC, NULL, 0x1000, NULL, HFILL + } + }, +#if 0 + { + &hf_dlmap_xie_diuc, + { + "Extended DIUC", "wmx.dlmapc.xie_diuc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dlmap_xie_len, + { + "Length", "wmx.dlmapc.xie_len", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + + { + &hf_109x_cmi, + { + "SUB-DL-UL-MAP map indicator", "wmx.dlul.cmi", + FT_UINT16, BASE_DEC, NULL, 0xE000, NULL, HFILL + } + }, + { + &hf_109x_dl, + { + "DL HARQ ACK offset", "wmx.dlul.dl", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_109x_dlie, + { + "DL IE Count", "wmx.dlul.dlie", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_109x_haoi, + { + "HARQ ACK offset indicator", "wmx.dlul.haoi", + FT_UINT16, BASE_DEC, NULL, 0x0001, NULL, HFILL + } + }, + { + &hf_109x_len, + { + "Map message length - The length is limited to 735 bytes at most", "wmx.dlul.len", + FT_UINT16, BASE_DEC, NULL, 0x1FF8, NULL, HFILL + } + }, + { + &hf_109x_rcid, + { + "RCID_Type", "wmx.dlul.rcid", + FT_UINT16, BASE_DEC, NULL, 0x0006, NULL, HFILL + } + }, + { + &hf_109x_subofs, + { + "Subchannel offset", "wmx.dlul.subofs", + FT_UINT8, BASE_DEC, NULL, 0xFE, NULL, HFILL + } + }, + { + &hf_109x_symofs, + { + "OFDMA Symbol offset of subsequent sub-bursts " + "in this Sub-DL-UL-MAP message with reference to " + "the start of UL sub-frame.", "wmx.dlul.symofs", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_109x_rsv, + { + "Reserved", "wmx.dlul.rsv", + FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_109x_ul, + { + "UL HARQ ACK offset", "wmx.dlul.ul", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#endif + { + &hf_308a_cmi, + { + "Compressed map indicator", "wmx.dlmap.reduced_aas_private.cmi", + FT_UINT8, BASE_DEC, NULL, 0xe0, NULL, HFILL + } + }, + { + &hf_308a_mult, + { + "Multiple IE", "wmx.dlmap.reduced_aas_private.mult", + FT_UINT8, BASE_DEC, NULL, 0x02, NULL, HFILL + } + }, + { + &hf_308a_rsv, + { + "Reserved", "wmx.dlmap.reduced_aas_private.rsv", + FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_308a_type, + { + "Compressed Map Type", "wmx.dlmap.reduced_aas_private.type", + FT_UINT8, BASE_DEC, NULL, 0x0d, NULL, HFILL + } + }, + { + &hf_308a_ulmap, + { + "UL-MAP appended", "wmx.dlmap.reduced_aas_private.ulmap", + FT_UINT8, BASE_DEC, NULL, 0x10, NULL, HFILL + } + }, + { + &hf_mac_header_compress_dlmap_crc, + { + "CRC", "wmx.compress_dlmap_crc", + FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_mac_header_compress_dlmap_crc_status, + { + "CRC Status", "wmx.compress_dlmap_crc.status", + FT_UINT8, BASE_NONE, VALS(plugin_proto_checksum_vals), 0x0, NULL, HFILL + } + }, + { + &hf_crc16, + { + "CRC-16", "wmx.dlmap.crc16", + FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_crc16_status, + { + "CRC-16 Status", "wmx.dlmap.crc16.status", + FT_UINT8, BASE_NONE, VALS(plugin_proto_checksum_vals), 0x0, NULL, HFILL + } + }, + { + &hf_padding, + { + "Padding", "wmx.dlmap.padding", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_cid_mask, + { + "CID Mask", "wmx.dlmap.cid_mask", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reserved, + { + "Reserved", "wmx.dlmap.reserved", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + /* Generated via "one time" script to help create filterable fields */ + { &hf_dlmap_rcid_ie_cid, { "CID", "wmx.dlmap.rcid_ie.cid", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_rcid_ie_prefix, { "Prefix", "wmx.dlmap.rcid_ie.prefix", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_rcid_ie_cid11, { "CID11", "wmx.dlmap.rcid_ie.cid11", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_rcid_ie_cid7, { "CID7", "wmx.dlmap.rcid_ie.cid7", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_rcid_ie_cid3, { "CID3", "wmx.dlmap.rcid_ie.cid3", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_dl_control_length, { "Length", "wmx.dlmap.dedicated_dl_control.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_dl_control_control_header, { "Control Header", "wmx.dlmap.dedicated_dl_control.control_header", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_dl_control_num_sdma_layers, { "Num SDMA Layers", "wmx.dlmap.dedicated_dl_control.num_sdma_layers", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_length, { "Length (nibbles)", "wmx.dlmap.dedicated_mimo_dl_control.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_control_header_mimo_control_info, { "Control Header (MIMO Control Info)", "wmx.dlmap.dedicated_mimo_dl_control.control_header_mimo_control_info", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_control_header_cqi_control_info, { "Control Header (CQI Control Info)", "wmx.dlmap.dedicated_mimo_dl_control.control_header_cqi_control_info", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_control_header_closed_mimo_control_info, { "Control Header (Closed MIMO Control Info)", "wmx.dlmap.dedicated_mimo_dl_control.control_header_closed_mimo_control_info", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_n_layer, { "N_layer", "wmx.dlmap.dedicated_mimo_dl_control.n_layer", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_matrix, { "Matrix", "wmx.dlmap.dedicated_mimo_dl_control.matrix", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_num_beamformed_streams, { "Num_Beamformed_Streams", "wmx.dlmap.dedicated_mimo_dl_control.num_beamformed_streams", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_period, { "Period", "wmx.dlmap.dedicated_mimo_dl_control.period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_frame_offset, { "Frame Offset", "wmx.dlmap.dedicated_mimo_dl_control.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_duration, { "Duration", "wmx.dlmap.dedicated_mimo_dl_control.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_allocation_index, { "Allocation Index", "wmx.dlmap.dedicated_mimo_dl_control.allocation_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_cqich_num, { "CQICH_Num", "wmx.dlmap.dedicated_mimo_dl_control.cqich_num", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_feedback_type, { "Feedback type", "wmx.dlmap.dedicated_mimo_dl_control.feedback_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_antenna_grouping_index, { "Antenna Grouping Index", "wmx.dlmap.dedicated_mimo_dl_control.antenna_grouping_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_num_stream, { "Num_stream", "wmx.dlmap.dedicated_mimo_dl_control.num_stream", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_antenna_selection_index, { "Antenna Selection Index", "wmx.dlmap.dedicated_mimo_dl_control.antenna_selection_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dedicated_mimo_dl_control_codebook_precoding_index, { "Codebook Precoding Index", "wmx.dlmap.dedicated_mimo_dl_control.codebook_precoding_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_n_sub_burst_isi, { "N sub burst[ISI]", "wmx.dlmap.n_sub_burst_isi", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_n_ack_channel, { "N ACK channel", "wmx.dlmap.harq_chase.n_ack_channel", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_duration, { "Duration", "wmx.dlmap.harq_chase.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_sub_burst_diuc_indicator, { "Sub-Burst DIUC Indicator", "wmx.dlmap.harq_chase.sub_burst_diuc_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reserved_uint, { "Reserved", "wmx.dlmap.reserved.uint", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_diuc, { "DIUC", "wmx.dlmap.harq_chase.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.harq_chase.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_acid, { "ACID", "wmx.dlmap.harq_chase.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_ai_sn, { "AI_SN", "wmx.dlmap.harq_chase.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_ack_disable, { "ACK disable", "wmx.dlmap.harq_chase.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_dedicated_dl_control_indicator, { "Dedicated DL Control Indicator", "wmx.dlmap.harq_chase.dedicated_dl_control_indicator", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_allocation_index, { "Allocation Index", "wmx.dlmap.harq_chase.allocation_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_period, { "Period (p)", "wmx.dlmap.harq_chase.period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_chase_frame_offset, { "Frame offset", "wmx.dlmap.harq_chase.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_n_ack_channel, { "N ACK channel", "wmx.dlmap.harq_ir_ctc.n_ack_channel", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_nep, { "N(EP)", "wmx.dlmap.harq_ir_ctc.n_ep", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_nsch, { "N(SCH)", "wmx.dlmap.harq_ir_ctc.n_sch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_spid, { "SPID", "wmx.dlmap.harq_ir_ctc.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_acid, { "ACID", "wmx.dlmap.harq_ir_ctc.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_ai_sn, { "AI_SN", "wmx.dlmap.harq_ir_ctc.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_ack_disable, { "ACK disable", "wmx.dlmap.harq_ir_ctc.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_dedicated_dl_control_indicator, { "Dedicated DL Control Indicator", "wmx.dlmap.harq_ir_ctc.dedicated_dl_control_indicator", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_duration, { "Duration (d)", "wmx.dlmap.harq_ir_ctc.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_allocation_index, { "Allocation Index", "wmx.dlmap.harq_ir_ctc.allocation_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_period, { "Period (p)", "wmx.dlmap.harq_ir_ctc.period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_ctc_frame_offset, { "Frame offset", "wmx.dlmap.harq_ir_ctc.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_n_ack_channel, { "N ACK channel", "wmx.dlmap.harq_ir_cc.n_ack_channel", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_duration, { "Duration", "wmx.dlmap.harq_ir_cc.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_sub_burst_diuc_indicator, { "Sub-Burst DIUC Indicator", "wmx.dlmap.harq_ir_cc.sub_burst_diuc_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_diuc, { "DIUC", "wmx.dlmap.harq_ir_cc.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.harq_ir_cc.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_acid, { "ACID", "wmx.dlmap.harq_ir_cc.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_ai_sn, { "AI_SN", "wmx.dlmap.harq_ir_cc.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_spid, { "SPID", "wmx.dlmap.harq_ir_cc.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_ack_disable, { "ACK disable", "wmx.dlmap.harq_ir_cc.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_dedicated_dl_control_indicator, { "Dedicated DL Control Indicator", "wmx.dlmap.harq_ir_cc.dedicated_dl_control_indicator", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_allocation_index, { "Allocation Index", "wmx.dlmap.harq_ir_cc.allocation_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_period, { "Period (p)", "wmx.dlmap.harq_ir_cc.period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ir_cc_frame_offset, { "Frame offset", "wmx.dlmap.harq_ir_cc.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_n_ack_channel, { "N ACK channel", "wmx.dlmap.mimo_dl_chase_harq.n_ack_channel", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_mu_indicator, { "MU Indicator", "wmx.dlmap.mimo_dl_chase_harq.mu_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_dedicated_mimo_dl_control_indicator, { "Dedicated MIMO DL Control Indicator", "wmx.dlmap.mimo_dl_chase_harq.dedicated_mimo_dl_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_ack_disable, { "ACK Disable", "wmx.dlmap.mimo_dl_chase_harq.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_duration, { "Duration", "wmx.dlmap.mimo_dl_chase_harq.duration", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_diuc, { "DIUC", "wmx.dlmap.mimo_dl_chase_harq.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.mimo_dl_chase_harq.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_acid, { "ACID", "wmx.dlmap.mimo_dl_chase_harq.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_chase_harq_ai_sn, { "AI_SN", "wmx.dlmap.mimo_dl_chase_harq.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_n_ack_channel, { "N ACK channel", "wmx.dlmap.mimo_dl_ir_harq.n_ack_channel", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_mu_indicator, { "MU Indicator", "wmx.dlmap.mimo_dl_ir_harq.mu_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_dedicated_mimo_dl_control_indicator, { "Dedicated MIMO DL Control Indicator", "wmx.dlmap.mimo_dl_ir_harq.dedicated_mimo_dl_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_ack_disable, { "ACK Disable", "wmx.dlmap.mimo_dl_ir_harq.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_nsch, { "N(SCH)", "wmx.dlmap.mimo_dl_ir_harq.n_sch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_nep, { "N(EP)", "wmx.dlmap.mimo_dl_ir_harq.n_ep", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_spid, { "SPID", "wmx.dlmap.mimo_dl_ir_harq.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_acid, { "ACID", "wmx.dlmap.mimo_dl_ir_harq.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_ai_sn, { "AI_SN", "wmx.dlmap.mimo_dl_ir_harq.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_n_ack_channel, { "N ACK channel", "wmx.dlmap.mimo_dl_ir_harq_cc.n_ack_channel", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_mu_indicator, { "MU Indicator", "wmx.dlmap.mimo_dl_ir_harq_cc.mu_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_dedicated_mimo_dl_control_indicator, { "Dedicated MIMO DL Control Indicator", "wmx.dlmap.mimo_dl_ir_harq_cc.dedicated_mimo_dl_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_ack_disable, { "ACK Disable", "wmx.dlmap.mimo_dl_ir_harq_cc.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_duration, { "Duration", "wmx.dlmap.mimo_dl_ir_harq_cc.duration", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_diuc, { "DIUC", "wmx.dlmap.mimo_dl_ir_harq_cc.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.mimo_dl_ir_harq_cc.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_acid, { "ACID", "wmx.dlmap.mimo_dl_ir_harq_cc.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_ai_sn, { "AI_SN", "wmx.dlmap.mimo_dl_ir_harq_cc.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_ir_harq_cc_spid, { "SPID", "wmx.dlmap.mimo_dl_ir_harq_cc.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_n_ack_channel, { "N ACK channel", "wmx.dlmap.mimo_dl_stc_harq.n_ack_channel", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_tx_count, { "TX Count", "wmx.dlmap.mimo_dl_stc_harq.tx_count", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_duration, { "Duration", "wmx.dlmap.mimo_dl_stc_harq.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_sub_burst_offset_indication, { "Sub-burst offset indication", "wmx.dlmap.mimo_dl_stc_harq.sub_burst_offset_indication", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_sub_burst_offset, { "Sub-burst offset", "wmx.dlmap.mimo_dl_stc_harq.sub_burst_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_ack_disable, { "ACK Disable", "wmx.dlmap.mimo_dl_stc_harq.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_dedicated_mimo_dl_control_indicator, { "Dedicated MIMO DL Control Indicator", "wmx.dlmap.mimo_dl_stc_harq.dedicated_mimo_dl_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_diuc, { "DIUC", "wmx.dlmap.mimo_dl_stc_harq.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_repetition_coding_indication, { "Repetition coding Indication", "wmx.dlmap.mimo_dl_stc_harq.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mimo_dl_stc_harq_acid, { "ACID", "wmx.dlmap.mimo_dl_stc_harq.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_extended_2_diuc, { "Extended-2 DIUC", "wmx.dlmap.mbs_map.extended_2_diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_mbs_zone_identifier, { "MBS Zone identifier", "wmx.dlmap.mbs_map.mbs_zone_identifier", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_macro_diversity_enhanced, { "Macro diversity enhanced", "wmx.dlmap.mbs_map.macro_diversity_enhanced", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_permutation, { "Permutation", "wmx.dlmap.mbs_map.permutation", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_dl_permbase, { "DL_PermBase", "wmx.dlmap.mbs_map.dl_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_prbs_id, { "PRBS_ID", "wmx.dlmap.mbs_map.prbs_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_ofdma_symbol_offset, { "OFDMA_Symbol_Offset", "wmx.dlmap.mbs_map.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_diuc_change_indication, { "DIUC_change_indication", "wmx.dlmap.mbs_map.diuc_change_indication", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_boosting, { "Boosting", "wmx.dlmap.mbs_map.boosting", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_diuc, { "DIUC", "wmx.dlmap.mbs_map.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_num_subchannels, { "No. Subchannels", "wmx.dlmap.mbs_map.num_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_num_ofdma_symbols, { "No. OFDMA Symbols", "wmx.dlmap.mbs_map.num_ofdma_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.mbs_map.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_cid, { "CID", "wmx.dlmap.mbs_map.cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_ofdma_symbols_offset, { "OFDMA Symbols Offset", "wmx.dlmap.mbs_map.ofdma_symbols_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_subchannel_offset, { "Subchannel offset", "wmx.dlmap.mbs_map.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_slc_3_indication, { "SLC_3_indication", "wmx.dlmap.mbs_map.slc_3_indication", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_mbs_map_next_mbs_map_ie_frame_offset, { "Next MBS_MAP_IE frame offset", "wmx.dlmap.mbs_map.next_mbs_map_ie_frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_skip_extended_2_diuc, { "Extended-2 DIUC", "wmx.dlmap.skip.extended_2_diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_skip_mode, { "Mode", "wmx.dlmap.skip.mode", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_extended_2_diuc, { "Extended-2 DIUC", "wmx.dlmap.harq_dl_map.extended_2_diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_rcid_type, { "RCID_Type", "wmx.dlmap.harq_dl_map.rcid_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_boosting, { "Boosting", "wmx.dlmap.harq_dl_map.boosting", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_region_id_use_indicator, { "Region_ID use indicator", "wmx.dlmap.harq_dl_map.region_id_use_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_ofdma_symbol_offset, { "OFDMA symbol offset", "wmx.dlmap.harq_dl_map.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_subchannel_offset, { "Subchannel offset", "wmx.dlmap.harq_dl_map.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_number_of_ofdma_symbols, { "Number of OFDMA symbols", "wmx.dlmap.harq_dl_map.number_of_ofdma_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_number_of_subchannels, { "Number of subchannels", "wmx.dlmap.harq_dl_map.number_of_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_rectangular_sub_burst_indicator, { "Rectangular Sub-Burst Indicator", "wmx.dlmap.harq_dl_map.rectangular_sub_burst_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_region_id, { "Region_ID", "wmx.dlmap.harq_dl_map.region_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_mode, { "Mode", "wmx.dlmap.harq_dl_map.mode", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_sub_burst_ie_length, { "Sub-burst IE Length", "wmx.dlmap.harq_dl_map.sub_burst_ie_length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_dl_map_reserved_mode, { "Reserved Mode", "wmx.dlmap.harq_dl_map.reserved_mode", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_ack_bitmap_data, { "Bitmap data", "wmx.dlmap.harq_ack.bitmap_data", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_enhanced_dl_map_extended_2_diuc, { "Extended-2 DIUC", "wmx.dlmap.enhanced_dl_map.extended_2_diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_enhanced_dl_map_num_assignment, { "Num_Assignment", "wmx.dlmap.enhanced_dl_map.num_assignment", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_enhanced_dl_map_n_cid, { "N_CID", "wmx.dlmap.enhanced_dl_map.n_cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_enhanced_dl_map_cid, { "CID", "wmx.dlmap.enhanced_dl_map.cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_enhanced_dl_map_diuc, { "DIUC", "wmx.dlmap.enhanced_dl_map.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_enhanced_dl_map_boosting, { "Boosting", "wmx.dlmap.enhanced_dl_map.boosting", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_enhanced_dl_map_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.enhanced_dl_map.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_enhanced_dl_map_region_id, { "Region_ID", "wmx.dlmap.enhanced_dl_map.region_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_extended_2_diuc, { "Extended-2 DIUC", "wmx.dlmap.aas_sdma_dl.extended_2_diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_rcid_type, { "RCID_Type", "wmx.dlmap.aas_sdma_dl.rcid_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_num_burst_region, { "Num_Burst_Region", "wmx.dlmap.aas_sdma_dl.num_burst_region", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_ofdma_symbol_offset, { "OFDMA Symbol Offset", "wmx.dlmap.aas_sdma_dl.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_subchannel_offset, { "Subchannel offset", "wmx.dlmap.aas_sdma_dl.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_num_ofdma_triple_symbols, { "No. OFDMA triple symbols", "wmx.dlmap.aas_sdma_dl.num_ofdma_triple_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_num_subchannels, { "No. subchannels", "wmx.dlmap.aas_sdma_dl.num_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_number_of_users, { "Number of Users", "wmx.dlmap.aas_sdma_dl.number_of_users", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_encoding_mode, { "Encoding Mode", "wmx.dlmap.aas_sdma_dl.encoding_mode", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_cqich_allocation, { "CQICH Allocation", "wmx.dlmap.aas_sdma_dl.cqich_allocation", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_ackch_allocation, { "ACKCH Allocation", "wmx.dlmap.aas_sdma_dl.ackch_allocation", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_pilot_pattern_modifier, { "Pilot Pattern Modifier", "wmx.dlmap.aas_sdma_dl.pilot_pattern_modifier", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_preamble_modifier_index, { "Preamble Modifier Index", "wmx.dlmap.aas_sdma_dl.preamble_modifier_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_pilot_pattern, { "Pilot Pattern", "wmx.dlmap.aas_sdma_dl.pilot_pattern", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_diuc, { "DIUC", "wmx.dlmap.aas_sdma_dl.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.aas_sdma_dl.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_ack_ch_index, { "ACK CH Index", "wmx.dlmap.aas_sdma_dl.ack_ch_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_acid, { "ACID", "wmx.dlmap.aas_sdma_dl.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_ai_sn, { "AI_SN", "wmx.dlmap.aas_sdma_dl.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_nep, { "N(EP)", "wmx.dlmap.aas_sdma_dl.n_ep", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_nsch, { "N(SCH)", "wmx.dlmap.aas_sdma_dl.n_sch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_spid, { "SPID", "wmx.dlmap.aas_sdma_dl.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_allocation_index, { "Allocation Index", "wmx.dlmap.aas_sdma_dl.allocation_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_period, { "Period (p)", "wmx.dlmap.aas_sdma_dl.period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_frame_offset, { "Frame offset", "wmx.dlmap.aas_sdma_dl.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_sdma_dl_duration, { "Duration (d)", "wmx.dlmap.aas_sdma_dl.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_channel_measurement_channel_nr, { "Channel Nr", "wmx.dlmap.channel_measurement.channel_nr", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_channel_measurement_ofdma_symbol_offset, { "OFDMA Symbol Offset", "wmx.dlmap.channel_measurement.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_channel_measurement_cid, { "CID", "wmx.dlmap.channel_measurement.cid", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_ofdma_symbol_offset, { "OFDMA Symbol Offset", "wmx.dlmap.stc_zone.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_permutations, { "Permutations", "wmx.dlmap.stc_zone.permutations", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_use_all_sc_indicator, { "Use All SC indicator", "wmx.dlmap.stc_zone.use_all_sc_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_stc, { "STC", "wmx.dlmap.stc_zone.stc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_matrix_indicator, { "Matrix indicator", "wmx.dlmap.stc_zone.matrix_indicator", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_dl_permbase, { "DL_PermBase", "wmx.dlmap.stc_zone.dl_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_prbs_id, { "PRBS_ID", "wmx.dlmap.stc_zone.prbs_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_amc_type, { "AMC type", "wmx.dlmap.stc_zone.amc_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_midamble_presence, { "Midamble Presence", "wmx.dlmap.stc_zone.midamble_presence", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_midamble_boosting, { "Midamble Boosting", "wmx.dlmap.stc_zone.midamble_boosting", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_2_3_antenna_select, { "2/3 antenna select", "wmx.dlmap.stc_zone.2_3_antenna_select", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_stc_zone_dedicated_pilots, { "Dedicated Pilots", "wmx.dlmap.stc_zone.dedicated_pilots", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_dl_ofdma_symbol_offset, { "OFDMA Symbol Offset", "wmx.dlmap.aas_dl.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_dl_permutation, { "Permutation", "wmx.dlmap.aas_dl.permutation", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_dl_dl_permbase, { "DL_PermBase", "wmx.dlmap.aas_dl.dl_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_dl_downlink_preamble_config, { "Downlink_preamble_config", "wmx.dlmap.aas_dl.downlink_preamble_config", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_dl_preamble_type, { "Preamble type", "wmx.dlmap.aas_dl.preamble_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_dl_prbs_id, { "PRBS_ID", "wmx.dlmap.aas_dl.prbs_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_aas_dl_diversity_map, { "Diversity Map", "wmx.dlmap.aas_dl.diversity_map", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_segment, { "Segment", "wmx.dlmap.data_location_another_bs.segment", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_used_subchannels, { "Used subchannels", "wmx.dlmap.data_location_another_bs.used_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_diuc, { "DIUC", "wmx.dlmap.data_location_another_bs.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_frame_advance, { "Frame Advance", "wmx.dlmap.data_location_another_bs.frame_advance", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_ofdma_symbol_offset, { "OFDMA Symbol Offset", "wmx.dlmap.data_location_another_bs.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_subchannel_offset, { "Subchannel Offset", "wmx.dlmap.data_location_another_bs.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_boosting, { "Boosting", "wmx.dlmap.data_location_another_bs.boosting", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_preamble_index, { "Preamble Index", "wmx.dlmap.data_location_another_bs.preamble_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_num_ofdma_symbols, { "No. OFDMA Symbols", "wmx.dlmap.data_location_another_bs.num_ofdma_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_num_subchannels, { "No. Subchannels", "wmx.dlmap.data_location_another_bs.num_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.data_location_another_bs.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_data_location_another_bs_cid, { "CID", "wmx.dlmap.data_location_another_bs.cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_map_pointer_diuc, { "DIUC", "wmx.dlmap.harq_map_pointer.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_map_pointer_num_slots, { "No. Slots", "wmx.dlmap.harq_map_pointer.num_slots", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_map_pointer_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.harq_map_pointer.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_map_pointer_map_version, { "Map Version", "wmx.dlmap.harq_map_pointer.map_version", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_map_pointer_idle_users, { "Idle users", "wmx.dlmap.harq_map_pointer.idle_users", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_map_pointer_sleep_users, { "Sleep users", "wmx.dlmap.harq_map_pointer.sleep_users", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_harq_map_pointer_cid_mask_length, { "CID Mask Length", "wmx.dlmap.harq_map_pointer.cid_mask_length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_phymod_dl_preamble_modifier_type, { "Preamble Modifier Type", "wmx.dlmap.phymod_dl.preamble_modifier_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_phymod_dl_preamble_frequency_shift_index, { "Preamble frequency shift index", "wmx.dlmap.phymod_dl.preamble_frequency_shift_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_phymod_dl_preamble_time_shift_index, { "Preamble Time Shift Index", "wmx.dlmap.phymod_dl.preamble_time_shift_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_phymod_dl_pilot_pattern_modifier, { "Pilot Pattern Modifier", "wmx.dlmap.phymod_dl.pilot_pattern_modifier", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_phymod_dl_pilot_pattern_index, { "Pilot Pattern Index", "wmx.dlmap.phymod_dl.pilot_pattern_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_broadcast_ctrl_ptr_dcd_ucd_transmission_frame, { "DCD_UCD Transmission Frame", "wmx.dlmap.broadcast_ctrl_ptr.dcd_ucd_transmission_frame", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_broadcast_ctrl_ptr_skip_broadcast_system_update, { "Skip Broadcast_System_Update", "wmx.dlmap.broadcast_ctrl_ptr.skip_broadcast_system_update", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_broadcast_ctrl_ptr_broadcast_system_update_type, { "Broadcast_System_Update_Type", "wmx.dlmap.broadcast_ctrl_ptr.broadcast_system_update_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_broadcast_ctrl_ptr_broadcast_system_update_transmission_frame, { "Broadcast_System_Update_Transmission_Frame", "wmx.dlmap.broadcast_ctrl_ptr.broadcast_system_update_transmission_frame", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_cid, { "CID", "wmx.dlmap.dl_pusc_burst_allocation.cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_diuc, { "DIUC", "wmx.dlmap.dl_pusc_burst_allocation.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_segment, { "Segment", "wmx.dlmap.dl_pusc_burst_allocation.segment", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_boosting, { "Boosting", "wmx.dlmap.dl_pusc_burst_allocation.boosting", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_idcell, { "IDcell", "wmx.dlmap.dl_pusc_burst_allocation.idcell", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_dl_permbase, { "DL_PermBase", "wmx.dlmap.dl_pusc_burst_allocation.dl_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_prbs_id, { "PRBS_ID", "wmx.dlmap.dl_pusc_burst_allocation.prbs_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_repetition_coding_indication, { "Repetition coding indication", "wmx.dlmap.dl_pusc_burst_allocation.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_used_subchannels, { "Used Subchannels", "wmx.dlmap.dl_pusc_burst_allocation.used_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_ofdma_symbol_offset, { "OFDMA symbol offset", "wmx.dlmap.dl_pusc_burst_allocation.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_num_ofdma_symbols, { "# OFDMA symbols", "wmx.dlmap.dl_pusc_burst_allocation.num_ofdma_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_subchannel_offset, { "Subchannel offset", "wmx.dlmap.dl_pusc_burst_allocation.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_dl_pusc_burst_allocation_num_subchannels, { "# subchannels", "wmx.dlmap.dl_pusc_burst_allocation.num_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_pusc_asca_alloc_diuc, { "DIUC", "wmx.dlmap.pusc_asca_alloc.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_pusc_asca_alloc_short_basic_cid, { "Short Basic CID", "wmx.dlmap.pusc_asca_alloc.short_basic_cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_pusc_asca_alloc_ofdma_symbol_offset, { "OFDMA Symbol offset", "wmx.dlmap.pusc_asca_alloc.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_pusc_asca_alloc_subchannel_offset, { "Subchannel offset", "wmx.dlmap.pusc_asca_alloc.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_pusc_asca_alloc_num_ofdma_symbols, { "# OFDMA Symbols", "wmx.dlmap.pusc_asca_alloc.num_ofdma_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_pusc_asca_alloc_num_symbols, { "# Symbols", "wmx.dlmap.pusc_asca_alloc.num_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_pusc_asca_alloc_repetition_coding_information, { "Repetition Coding Information", "wmx.dlmap.pusc_asca_alloc.repetition_coding_information", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_pusc_asca_alloc_permutation_id, { "Permutation ID", "wmx.dlmap.pusc_asca_alloc.permutation_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_num_ie, { "NUM IE", "wmx.dlmap.reduced_aas.num_ie", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_periodicity, { "Periodicity", "wmx.dlmap.reduced_aas.periodicity", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_cid_included, { "CID Included", "wmx.dlmap.reduced_aas.cid_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_dcd_count_included, { "DCD Count Included", "wmx.dlmap.reduced_aas.dcd_count_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_phy_modification_included, { "PHY modification included", "wmx.dlmap.reduced_aas.phy_modification_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_cqich_control_indicator, { "CQICH control indicator", "wmx.dlmap.reduced_aas.cqich_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_encoding_mode, { "Encoding Mode", "wmx.dlmap.reduced_aas.encoding_mode", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_separate_mcs_enabled, { "Separate MCS Enabled", "wmx.dlmap.reduced_aas.separate_mcs_enabled", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_duration, { "Duration", "wmx.dlmap.reduced_aas.duration", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_diuc, { "DIUC", "wmx.dlmap.reduced_aas.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_repetition_coding_indication, { "Repetition Coding Indication", "wmx.dlmap.reduced_aas.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_cid, { "CID", "wmx.dlmap.reduced_aas.cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_allocation_index, { "Allocation Index", "wmx.dlmap.reduced_aas.allocation_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_report_period, { "Report Period", "wmx.dlmap.reduced_aas.report_period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_frame_offset, { "Frame Offset", "wmx.dlmap.reduced_aas.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_report_duration, { "Report Duration", "wmx.dlmap.reduced_aas.report_duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_cqi_measurement_type, { "CQI Measurement Type", "wmx.dlmap.reduced_aas.cqi_measurement_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_dcd_count, { "DCD Count", "wmx.dlmap.reduced_aas.dcd_count", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_preamble_select, { "Preamble Select", "wmx.dlmap.reduced_aas.preamble_select", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_preamble_shift_index, { "Preamble Shift Index", "wmx.dlmap.reduced_aas.preamble_shift_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_pilot_pattern_modifier, { "Pilot Pattern Modifier", "wmx.dlmap.reduced_aas.pilot_pattern_modifier", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_pilot_pattern_index, { "Pilot Pattern Index", "wmx.dlmap.reduced_aas.pilot_pattern_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_dl_frame_offset, { "DL Frame Offset", "wmx.dlmap.reduced_aas.dl_frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_zone_symbol_offset, { "Zone Symbol Offset", "wmx.dlmap.reduced_aas.zone_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_ofdma_symbol_offset, { "OFDMA Symbol Offset", "wmx.dlmap.reduced_aas.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_subchannel_offset, { "Subchannel Offset", "wmx.dlmap.reduced_aas.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_num_ofdma_triple_symbol, { "No. OFDMA triple symbol", "wmx.dlmap.reduced_aas.num_ofdma_triple_symbol", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_num_subchannels, { "No. subchannels", "wmx.dlmap.reduced_aas.num_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_num_ofdma_symbols, { "No. OFDMA symbols", "wmx.dlmap.reduced_aas.num_ofdma_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_diuc_nep, { "DIUC/N(EP)", "wmx.dlmap.reduced_aas.diuc_nep", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_dl_harq_ack_bitmap, { "DL HARQ ACK bitmap", "wmx.dlmap.reduced_aas.dl_harq_ack_bitmap", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_ack_allocation_index, { "ACK Allocation Index", "wmx.dlmap.reduced_aas.ack_allocation_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_acid, { "ACID", "wmx.dlmap.reduced_aas.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_ai_sn, { "AI_SN", "wmx.dlmap.reduced_aas.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_nsch, { "N(SCH)", "wmx.dlmap.reduced_aas.nsch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_dlmap_reduced_aas_spid, { "SPID", "wmx.dlmap.reduced_aas.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_dlmap, + &ett_dlmap_ie, + /* &ett_dlmap_c_ie, */ + &ett_109x, + &ett_109x_dl, + &ett_109x_ul, + &ett_275_phy, + &ett_275_1, + &ett_277, + &ett_277b, + &ett_278, + &ett_279, + &ett_280, + &ett_281, + &ett_282, + &ett_283, + &ett_284, + &ett_285, + &ett_286, + &ett_286a, + &ett_286b, + &ett_286c, + &ett_286d, + &ett_286e, + &ett_286f, + &ett_286g, + &ett_286h, + &ett_286i, + &ett_286j, + &ett_286k, + &ett_286l, + &ett_286m, + &ett_286n, + &ett_286o, + &ett_286p, + &ett_286q, + &ett_286r, + &ett_286s, + &ett_286t, + &ett_286u, + &ett_286v, + &ett_286w, + &ett_286x, + &ett_286y, + &ett_286z, + &ett_305, + /* &ett_305_dl, */ + &ett_308a, + }; + + static ei_register_info ei[] = { + { &ei_dlmap_not_implemented, { "wmx.dlmap.not_implemented", PI_UNDECODED, PI_WARN, "Not implemented", EXPFILL }}, + { &ei_crc16, { "wmx.dlmap.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, + { &ei_mac_header_compress_dlmap_crc, { "wmx.compress_dlmap.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, + { &ei_mac_header_invalid_length, { "wmx.compress_dlmap.invalid_length", PI_MALFORMED, PI_ERROR, "Invalid length", EXPFILL }}, + }; + + expert_module_t* expert_mac_mgmt_msg_dlmap; + + proto_mac_mgmt_msg_dlmap_decoder = proto_register_protocol ( + "WiMax DLMAP Messages", /* name */ + "WiMax DLMAP", /* short name */ + "wmx.dlmap" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_dlmap_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_mac_mgmt_msg_dlmap = expert_register_protocol(proto_mac_mgmt_msg_dlmap_decoder); + expert_register_field_array(expert_mac_mgmt_msg_dlmap, ei, array_length(ei)); + dlmap_handle = register_dissector("mac_mgmt_msg_dlmap_handler", dissect_mac_mgmt_msg_dlmap_decoder, proto_mac_mgmt_msg_dlmap_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_dlmap(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DL_MAP, dlmap_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: + */ diff --git a/plugins/epan/wimax/msg_dreg.c b/plugins/epan/wimax/msg_dreg.c new file mode 100644 index 00000000..8c0cd650 --- /dev/null +++ b/plugins/epan/wimax/msg_dreg.c @@ -0,0 +1,529 @@ +/* msg_dreg.c + * WiMax MAC Management DREG-REQ, DREG-CMD Message decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +extern gboolean include_cor2_changes; + +void proto_register_mac_mgmt_msg_dreg_req(void); +void proto_register_mac_mgmt_msg_dreg_cmd(void); +void proto_reg_handoff_mac_mgmt_msg_dreg(void); + +static dissector_handle_t dreg_req_handle; +static dissector_handle_t dreg_cmd_handle; + +/* Forward reference */ +static void dissect_dreg_tlv(proto_tree *dreg_tree, gint tlv_type, tvbuff_t *tvb, guint tlv_offset, guint tlv_len); +static int dissect_mac_mgmt_msg_dreg_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); +static int dissect_mac_mgmt_msg_dreg_cmd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); + +static gint proto_mac_mgmt_msg_dreg_req_decoder = -1; +static gint proto_mac_mgmt_msg_dreg_cmd_decoder = -1; + +static gint ett_mac_mgmt_msg_dreg_decoder = -1; + +/* Setup protocol subtree array */ +static gint *ett[] = +{ + &ett_mac_mgmt_msg_dreg_decoder, +}; + +/* DREG fields */ +/* static gint hf_ack_type_reserved = -1; */ +static gint hf_dreg_cmd_action = -1; +static gint hf_dreg_cmd_action_cor2 = -1; +static gint hf_dreg_cmd_reserved = -1; +static gint hf_dreg_paging_cycle = -1; +static gint hf_dreg_paging_offset = -1; +static gint hf_dreg_paging_group_id = -1; +static gint hf_dreg_req_duration = -1; +static gint hf_paging_controller_id = -1; +static gint hf_mac_hash_skip_threshold = -1; +static gint hf_dreg_paging_cycle_request = -1; +static gint hf_dreg_retain_ms_service_sbc = -1; +static gint hf_dreg_retain_ms_service_pkm = -1; +static gint hf_dreg_retain_ms_service_reg = -1; +static gint hf_dreg_retain_ms_service_network_address = -1; +static gint hf_dreg_retain_ms_service_tod = -1; +static gint hf_dreg_retain_ms_service_tftp = -1; +static gint hf_dreg_retain_ms_service_full_service = -1; +static gint hf_dreg_consider_paging_pref = -1; +static gint hf_tlv_value = -1; +static gint hf_dreg_req_action = -1; +static gint hf_dreg_req_reserved = -1; +static gint hf_dreg_invalid_tlv = -1; + +/* STRING RESOURCES */ +static const value_string vals_dreg_req_code[] = { + {0, "SS De-Registration request from BS and network"}, + {1, "MS request for De-Registration from serving BS and initiation of Idle Mode"}, + {2, "MS response for the Unsolicited De-Registration initiated by BS"}, + {3, "Reject for the unsolicited DREG-CMD with action \ +code 05 (idle mode request) by the BS. \ +Applicable only when MS has pending UL data to transmit"}, + {4, "Reserved"}, + {0, NULL} +}; + +static const value_string vals_dreg_cmd_action[] = { + {0, "SS shall immediately terminate service with the BS and \ +should attempt network entry at another BS"}, + {1, "SS shall listen to the current channel BS but shall not \ +transmit until an RES-CMD message or DREG-CMD with \ +Action Code 02 or 03 is received"}, + {2, "SS shall listen to the BS but only transmit \ +on the Basic, and Primary Management Connections"}, + {3, "SS shall return to normal operation and may transmit on \ +any of its active connections"}, + {4, "SS shall terminate current Normal Operations with the BS; \ +the BS shall transmit this action code only in response \ +to any SS DREG-REQ message"}, + {5, "MS shall immediately begin de-registration from serving \ +BS and request initiation of MS Idle Mode"}, + {6, "The MS may retransmit the DREG-REQ message after the \ +time duration (REQ-duration) provided in the message"}, + {7, "The MS shall not retransmit the DREG-REQ message and shall \ +wait for the DREG-CMD message. BS transmittal of a \ +subsequent DREG-CMD with Action Code 03 shall cancel \ +this restriction"}, + {0, NULL} +}; + +static const value_string vals_dreg_cmd_action_cor2[] = { + {0, "SS shall immediately terminate service with the BS and \ +should attempt network entry at another BS"}, + {1, "SS shall listen to the current channel BS but shall not \ +transmit until an RES-CMD message or DREG-CMD with \ +Action Code 02 or 03 is received"}, + {2, "SS shall listen to the BS but only transmit \ +on the Basic, and Primary Management Connections"}, + {3, "SS shall return to normal operation and may transmit on \ +any of its active connections"}, + {4, "Only valid in response to a DREG-REQ message with DREG \ +Code = 00. SS shall terminate current Normal Operations with the BS"}, + {5, "MS shall immediately begin de-registration from serving \ +BS and request initiation of MS Idle Mode"}, + {6, "Only valid in response to a DREG-REQ message with DREG \ +Code = 01. The MS may retransmit the DREG-REQ message after the \ +REQ-duration provided in the message; \ +BS sending a subsequent DREG-CMD message with \ +Action Code 03 cancels this restriction"}, + {0, NULL} +}; + +/* Decode sub-TLV's of either DREG-REQ or DREG-CMD. */ +static void dissect_dreg_tlv(proto_tree *dreg_tree, gint tlv_type, tvbuff_t *tvb, guint tlv_offset, guint tlv_len) +{ + switch (tlv_type) { + case DREG_PAGING_INFO: + proto_tree_add_item(dreg_tree, hf_dreg_paging_cycle, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_paging_offset, tvb, tlv_offset + 2, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_paging_group_id, tvb, tlv_offset + 3, 2, ENC_BIG_ENDIAN); + break; + case DREG_REQ_DURATION: + proto_tree_add_item(dreg_tree, hf_dreg_req_duration, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case DREG_PAGING_CONTROLLER_ID: + proto_tree_add_item(dreg_tree, hf_paging_controller_id, tvb, tlv_offset, 6, ENC_NA); + break; + case DREG_IDLE_MODE_RETAIN_INFO: + proto_tree_add_item(dreg_tree, hf_dreg_retain_ms_service_sbc, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_retain_ms_service_pkm, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_retain_ms_service_reg, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_retain_ms_service_network_address, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_retain_ms_service_tod, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_retain_ms_service_tftp, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_retain_ms_service_full_service, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(dreg_tree, hf_dreg_consider_paging_pref, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case DREG_MAC_HASH_SKIP_THRESHOLD: + proto_tree_add_item(dreg_tree, hf_mac_hash_skip_threshold, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + break; + case DREG_PAGING_CYCLE_REQUEST: + proto_tree_add_item(dreg_tree, hf_dreg_paging_cycle_request, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + break; + default: + proto_tree_add_item(dreg_tree, hf_tlv_value, tvb, tlv_offset, tlv_len, ENC_NA); + break; + } +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_dreg_req(void) +{ + /* DREG fields display */ + static hf_register_info hf[] = + { + { + &hf_dreg_consider_paging_pref, + { + "Consider Paging Preference of each Service Flow in resource retention", "wmx.dreg.consider_paging_preference", + FT_UINT8, BASE_DEC, NULL, 0x80, NULL, HFILL + } + }, + { + &hf_dreg_invalid_tlv, + { + "Invalid TLV", "wmx.dreg.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_mac_hash_skip_threshold, + { + "MAC Hash Skip Threshold", "wmx.dreg.mac_hash_skip_threshold", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_paging_controller_id, + { + "Paging Controller ID", "wmx.dreg.paging_controller_id", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dreg_paging_cycle, + { + "PAGING CYCLE", "wmx.dreg.paging_cycle", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dreg_paging_cycle_request, + { + "Paging Cycle Request", "wmx.dreg.paging_cycle_request", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dreg_paging_group_id, + { + "Paging-group-ID", "wmx.dreg.paging_group_id", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dreg_paging_offset, + { + "PAGING OFFSET", "wmx.dreg.paging_offset", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dreg_req_duration, + { + "REQ-duration (Waiting value for the DREG-REQ message re-transmission in frames)", "wmx.dreg.req_duration", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dreg_retain_ms_service_full_service, + { + "Retain MS service and operation information associated with Full service", "wmx.dreg.retain_ms_full_service", + FT_UINT8, BASE_DEC, NULL, 0x40, NULL, HFILL + } + }, + { + &hf_dreg_retain_ms_service_network_address, + { + "Retain MS service and operational information associated with Network Address", "wmx.dreg.retain_ms_service_network_address", + FT_UINT8, BASE_DEC, NULL, 0x08, NULL, HFILL + } + }, + { + &hf_dreg_retain_ms_service_pkm, + { + "Retain MS service and operational information associated with PKM-REQ/RSP", "wmx.dreg.retain_ms_service_pkm", + FT_UINT8, BASE_DEC, NULL, 0x02, NULL, HFILL + } + }, + { + &hf_dreg_retain_ms_service_reg, + { + "Retain MS service and operational information associated with REG-REQ/RSP", "wmx.dreg.retain_ms_service_reg", + FT_UINT8, BASE_DEC, NULL, 0x04, NULL, HFILL + } + }, + { + &hf_dreg_retain_ms_service_sbc, + { + "Retain MS service and operational information associated with SBC-REQ/RSP", "wmx.dreg.retain_ms_service_sbc", + FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_dreg_retain_ms_service_tftp, + { + "Retain MS service and operational information associated with TFTP messages", "wmx.dreg.retain_ms_service_tftp", + FT_UINT8, BASE_DEC, NULL, 0x20, NULL, HFILL + } + }, + { + &hf_dreg_retain_ms_service_tod, + { + "Retain MS service and operational information associated with Time of Day", "wmx.dreg.retain_ms_service_tod", + FT_UINT8, BASE_DEC, NULL, 0x10, NULL, HFILL + } + }, + { + &hf_dreg_cmd_action, + { + "DREG-CMD Action code", "wmx.dreg_cmd.action", + FT_UINT8, BASE_DEC, VALS(vals_dreg_cmd_action), 0x07, NULL, HFILL + } + }, + { + &hf_dreg_cmd_action_cor2, + { + "DREG-CMD Action code", "wmx.dreg_cmd.action", + FT_UINT8, BASE_DEC, VALS(vals_dreg_cmd_action_cor2), 0x07, NULL, HFILL + } + }, + { + &hf_dreg_cmd_reserved, + { + "Reserved", "wmx.dreg_cmd.action_reserved", + FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL + } + }, + { + &hf_dreg_req_action, + { + "DREG-REQ Action code", "wmx.dreg_req.action", + FT_UINT8, BASE_DEC, VALS(vals_dreg_req_code), 0x03, NULL, HFILL + } + }, + { + &hf_dreg_req_reserved, + { + "Reserved", "wmx.dreg_req.action_reserved", + FT_UINT8, BASE_DEC, NULL, 0xFC, NULL, HFILL + } + }, + { + &hf_tlv_value, + { + "Value", "wmx.dreg.unknown_tlv_value", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, +#if 0 + { + &hf_ack_type_reserved, + { + "Reserved", "wmx.ack_type_reserved", + FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL + } + } +#endif + }; + + proto_mac_mgmt_msg_dreg_req_decoder = proto_register_protocol ( + "WiMax DREG-REQ Messages", /* name */ + "WiMax DREG-REQ", /* short name */ + "wmx.dreg_req" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_dreg_req_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + dreg_req_handle = register_dissector("mac_mgmt_msg_dreg_req_handler", dissect_mac_mgmt_msg_dreg_req_decoder, proto_mac_mgmt_msg_dreg_req_decoder); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_dreg_cmd(void) +{ + proto_mac_mgmt_msg_dreg_cmd_decoder = proto_register_protocol ( + "WiMax DREG-CMD Messages", /* name */ + "WiMax DREG-CMD", /* short name */ + "wmx.dreg_cmd" /* abbrev */ + ); + dreg_cmd_handle = register_dissector("mac_mgmt_msg_dreg_cmd_handler", dissect_mac_mgmt_msg_dreg_cmd_decoder, proto_mac_mgmt_msg_dreg_cmd_decoder); +} + +/* Decode DREG-REQ messages. */ +static int dissect_mac_mgmt_msg_dreg_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tlv_offset; + guint tvb_len; + proto_item *dreg_req_item; + proto_tree *dreg_req_tree; + proto_tree *tlv_tree = NULL; + tlv_info_t tlv_info; + gint tlv_type; + gint tlv_len; + gboolean hmac_found = FALSE; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type DREG-REQ */ + dreg_req_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dreg_req_decoder, tvb, 0, -1, "MAC Management Message, DREG-REQ"); + /* add MAC DREG REQ subtree */ + dreg_req_tree = proto_item_add_subtree(dreg_req_item, ett_mac_mgmt_msg_dreg_decoder); + /* display the Action Code */ + proto_tree_add_item(dreg_req_tree, hf_dreg_req_action, tvb, offset, 1, ENC_BIG_ENDIAN); + /* show the Reserved bits */ + proto_tree_add_item(dreg_req_tree, hf_dreg_req_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + while(offset < tvb_len) + { + /* Get the TLV data. */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DREG-REQ TLV error"); + proto_tree_add_item(dreg_req_tree, hf_dreg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the offset to the TLV data */ + tlv_offset = offset + get_tlv_value_offset(&tlv_info); + + switch (tlv_type) { + case HMAC_TUPLE: /* Table 348d */ + /* decode and display the HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dreg_decoder, dreg_req_tree, proto_mac_mgmt_msg_dreg_req_decoder, tvb, offset, tlv_len, "HMAC Tuple"); + wimax_hmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len); + hmac_found = TRUE; + break; + case CMAC_TUPLE: /* Table 348b */ + /* decode and display the CMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dreg_decoder, dreg_req_tree, proto_mac_mgmt_msg_dreg_req_decoder, tvb, offset, tlv_len, "CMAC Tuple"); + wimax_cmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len); + break; + default: + /* Decode DREG-REQ sub-TLV's */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dreg_decoder, dreg_req_tree, proto_mac_mgmt_msg_dreg_req_decoder, tvb, offset, tlv_len, "DREG-REQ sub-TLV's"); + dissect_dreg_tlv(tlv_tree, tlv_type, tvb, tlv_offset, tlv_len); + break; + } + + + offset = tlv_len + tlv_offset; + } /* end of TLV process while loop */ + if (!hmac_found) + proto_item_append_text(dreg_req_tree, " (HMAC Tuple is missing !)"); + } + return tvb_captured_length(tvb); +} + +/* Decode DREG-CMD messages. */ +static int dissect_mac_mgmt_msg_dreg_cmd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tlv_offset; + guint tvb_len; + proto_item *dreg_cmd_item; + proto_tree *dreg_cmd_tree; + proto_tree *tlv_tree = NULL; + tlv_info_t tlv_info; + gint tlv_type; + gint tlv_len; + gboolean hmac_found = FALSE; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type DREG-CMD */ + dreg_cmd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dreg_cmd_decoder, tvb, 0, -1, "MAC Management Message, DREG-CMD"); + /* add MAC DREG CMD subtree */ + dreg_cmd_tree = proto_item_add_subtree(dreg_cmd_item, ett_mac_mgmt_msg_dreg_decoder); + /* display the Action Code */ + if (include_cor2_changes) + proto_tree_add_item(dreg_cmd_tree, hf_dreg_cmd_action_cor2, tvb, offset, 1, ENC_BIG_ENDIAN); + else + proto_tree_add_item(dreg_cmd_tree, hf_dreg_cmd_action, tvb, offset, 1, ENC_BIG_ENDIAN); + /* show the Reserved bits */ + proto_tree_add_item(dreg_cmd_tree, hf_dreg_cmd_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + offset ++; + + while(offset < tvb_len) + { + /* Get the TLV data. */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DREG-CMD TLV error"); + proto_tree_add_item(dreg_cmd_tree, hf_dreg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the offset to the TLV data */ + tlv_offset = offset + get_tlv_value_offset(&tlv_info); + + switch (tlv_type) { + case HMAC_TUPLE: /* Table 348d */ + /* decode and display the HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dreg_decoder, dreg_cmd_tree, proto_mac_mgmt_msg_dreg_cmd_decoder, tvb, offset, tlv_len, "HMAC Tuple"); + wimax_hmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len); + hmac_found = TRUE; + break; + case CMAC_TUPLE: /* Table 348b */ + /* decode and display the CMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dreg_decoder, dreg_cmd_tree, proto_mac_mgmt_msg_dreg_cmd_decoder, tvb, offset, tlv_len, "CMAC Tuple"); + wimax_cmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len); + break; + default: + /* Decode DREG-CMD sub-TLV's */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dreg_decoder, dreg_cmd_tree, proto_mac_mgmt_msg_dreg_cmd_decoder, tvb, offset, tlv_len, "DREG-CMD sub-TLV's"); + dissect_dreg_tlv(tlv_tree, tlv_type, tvb, tlv_offset, tlv_len); + break; + } + + offset = tlv_len + tlv_offset; + } /* end of TLV process while loop */ + if (!hmac_found) + proto_item_append_text(dreg_cmd_tree, " (HMAC Tuple is missing !)"); + } + return tvb_captured_length(tvb); +} + +void +proto_reg_handoff_mac_mgmt_msg_dreg(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DREG_REQ, dreg_req_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DREG_CMD, dreg_cmd_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: + */ diff --git a/plugins/epan/wimax/msg_dsa.c b/plugins/epan/wimax/msg_dsa.c new file mode 100644 index 00000000..72280baa --- /dev/null +++ b/plugins/epan/wimax/msg_dsa.c @@ -0,0 +1,184 @@ +/* msg_dsa.c + * WiMax MAC Management DSA-REQ/RSP/ACK Messages decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +/* +#define DEBUG +*/ + +#include +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_dsa(void); +void proto_reg_handoff_mac_mgmt_msg_dsa(void); + +static dissector_handle_t dsa_req_handle; +static dissector_handle_t dsa_rsp_handle; +static dissector_handle_t dsa_ack_handle; + +static gint proto_mac_mgmt_msg_dsa_decoder = -1; +static gint ett_mac_mgmt_msg_dsa_req_decoder = -1; +static gint ett_mac_mgmt_msg_dsa_rsp_decoder = -1; +static gint ett_mac_mgmt_msg_dsa_ack_decoder = -1; + +/* fix fields */ +static gint hf_dsa_transaction_id = -1; +static gint hf_dsa_confirmation_code = -1; + +static int dissect_mac_mgmt_msg_dsa_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *dsa_item; + proto_tree *dsa_tree; + + { /* we are being asked for details */ + + /* display MAC message type */ + dsa_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsa_decoder, tvb, offset, -1, + "Dynamic Service Addition Request (DSA-REQ)"); + /* add MAC DSx subtree */ + dsa_tree = proto_item_add_subtree(dsa_item, ett_mac_mgmt_msg_dsa_req_decoder); + /* Decode and display the Uplink Channel Descriptor (UCD) */ + /* display the Transaction ID */ + proto_tree_add_item(dsa_tree, hf_dsa_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* process DSA-REQ message TLV Encode Information */ + wimax_common_tlv_encoding_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, dsa_tree); + } + return tvb_captured_length(tvb); +} + +static int dissect_mac_mgmt_msg_dsa_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *dsa_item; + proto_tree *dsa_tree; + + { /* we are being asked for details */ + /* display MAC message type */ + dsa_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsa_decoder, tvb, offset, -1, + "Dynamic Service Addition Response (DSA-RSP)"); + /* add MAC DSx subtree */ + dsa_tree = proto_item_add_subtree(dsa_item, ett_mac_mgmt_msg_dsa_rsp_decoder); + /* Decode and display the Uplink Channel Descriptor (UCD) */ + /* display the Transaction ID */ + proto_tree_add_item(dsa_tree, hf_dsa_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* display the Confirmation Code */ + proto_tree_add_item(dsa_tree, hf_dsa_confirmation_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* process DSA RSP message TLV Encode Information */ + wimax_common_tlv_encoding_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, dsa_tree); + } + return tvb_captured_length(tvb); +} + +static int dissect_mac_mgmt_msg_dsa_ack_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *dsa_item; + proto_tree *dsa_tree; + + { /* we are being asked for details */ + /* display MAC message type */ + dsa_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsa_decoder, tvb, offset, -1, + "Dynamic Service Addition Acknowledge (DSA-ACK)"); + /* add MAC DSx subtree */ + dsa_tree = proto_item_add_subtree(dsa_item, ett_mac_mgmt_msg_dsa_ack_decoder); + /* Decode and display the Uplink Channel Descriptor (UCD) */ + /* display the Transaction ID */ + proto_tree_add_item(dsa_tree, hf_dsa_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* display the Confirmation Code */ + proto_tree_add_item(dsa_tree, hf_dsa_confirmation_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* process DSA-REQ message TLV Encode Information */ + wimax_common_tlv_encoding_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, dsa_tree); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_dsa(void) +{ + /* DSx display */ + static hf_register_info hf[] = + { + { + &hf_dsa_confirmation_code, + { + "Confirmation code", "wmx.dsa.confirmation_code", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dsa_transaction_id, + { + "Transaction ID", "wmx.dsa.transaction_id", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_dsa_req_decoder, + &ett_mac_mgmt_msg_dsa_rsp_decoder, + &ett_mac_mgmt_msg_dsa_ack_decoder, + }; + + proto_mac_mgmt_msg_dsa_decoder = proto_register_protocol ( + "WiMax DSA Messages", /* name */ + "WiMax DSA", /* short name */ + "wmx.dsa" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_dsa_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + dsa_req_handle = register_dissector("mac_mgmt_msg_dsa_req_handler", dissect_mac_mgmt_msg_dsa_req_decoder, proto_mac_mgmt_msg_dsa_decoder); + dsa_rsp_handle = register_dissector("mac_mgmt_msg_dsa_rsp_handler", dissect_mac_mgmt_msg_dsa_rsp_decoder, proto_mac_mgmt_msg_dsa_decoder); + dsa_ack_handle = register_dissector("mac_mgmt_msg_dsa_ack_handler", dissect_mac_mgmt_msg_dsa_ack_decoder, proto_mac_mgmt_msg_dsa_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_dsa (void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSA_REQ, dsa_req_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSA_RSP, dsa_rsp_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSA_ACK, dsa_ack_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: + */ diff --git a/plugins/epan/wimax/msg_dsc.c b/plugins/epan/wimax/msg_dsc.c new file mode 100644 index 00000000..8f681965 --- /dev/null +++ b/plugins/epan/wimax/msg_dsc.c @@ -0,0 +1,185 @@ +/* msg_dsc.c + * WiMax MAC Management DSC-REQ/RSP/ACK Messages decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +/* +#define DEBUG +*/ + +#include +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_dsc(void); +void proto_reg_handoff_mac_mgmt_msg_dsc(void); + +static dissector_handle_t dsc_req_handle; +static dissector_handle_t dsc_rsp_handle; +static dissector_handle_t dsc_ack_handle; + +static gint proto_mac_mgmt_msg_dsc_decoder = -1; +static gint ett_mac_mgmt_msg_dsc_req_decoder = -1; +static gint ett_mac_mgmt_msg_dsc_rsp_decoder = -1; +static gint ett_mac_mgmt_msg_dsc_ack_decoder = -1; + +/* fix fields */ +static gint hf_dsc_transaction_id = -1; +static gint hf_dsc_confirmation_code = -1; + + +static int dissect_mac_mgmt_msg_dsc_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *dsc_item; + proto_tree *dsc_tree; + + { /* we are being asked for details */ + + /* display MAC message type */ + dsc_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsc_decoder, tvb, offset, -1, + "Dynamic Service Change Request (DSC-REQ)"); + /* add MAC DSx subtree */ + dsc_tree = proto_item_add_subtree(dsc_item, ett_mac_mgmt_msg_dsc_req_decoder); + /* Decode and display the Uplink Channel Descriptor (UCD) */ + /* display the Transaction ID */ + proto_tree_add_item(dsc_tree, hf_dsc_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* process DSC REQ message TLV Encode Information */ + wimax_common_tlv_encoding_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, dsc_tree); + } + return tvb_captured_length(tvb); +} + +static int dissect_mac_mgmt_msg_dsc_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *dsc_item; + proto_tree *dsc_tree; + + { /* we are being asked for details */ + /* display MAC message type */ + dsc_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsc_decoder, tvb, offset, -1, + "Dynamic Service Change Response (DSC-RSP)"); + /* add MAC DSx subtree */ + dsc_tree = proto_item_add_subtree(dsc_item, ett_mac_mgmt_msg_dsc_rsp_decoder); + /* Decode and display the Uplink Channel Descriptor (UCD) */ + /* display the Transaction ID */ + proto_tree_add_item(dsc_tree, hf_dsc_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* display the Confirmation Code */ + proto_tree_add_item(dsc_tree, hf_dsc_confirmation_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* process DSC RSP message TLV Encode Information */ + wimax_common_tlv_encoding_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, dsc_tree); + } + return tvb_captured_length(tvb); +} + +static int dissect_mac_mgmt_msg_dsc_ack_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *dsc_item; + proto_tree *dsc_tree; + + { /* we are being asked for details */ + /* display MAC message type */ + dsc_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsc_decoder, tvb, offset, -1, + "Dynamic Service Change Acknowledge (DSC-ACK)"); + /* add MAC DSx subtree */ + dsc_tree = proto_item_add_subtree(dsc_item, ett_mac_mgmt_msg_dsc_ack_decoder); + /* Decode and display the Uplink Channel Descriptor (UCD) */ + /* display the Transaction ID */ + proto_tree_add_item(dsc_tree, hf_dsc_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* display the Confirmation Code */ + proto_tree_add_item(dsc_tree, hf_dsc_confirmation_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* process DSC ACK message TLV Encode Information */ + wimax_common_tlv_encoding_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, dsc_tree); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_dsc(void) +{ + /* DSx display */ + static hf_register_info hf[] = + { + { + &hf_dsc_confirmation_code, + { + "Confirmation code", "wmx.dsc.confirmation_code", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dsc_transaction_id, + { + "Transaction ID", "wmx.dsc.transaction_id", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_dsc_req_decoder, + &ett_mac_mgmt_msg_dsc_rsp_decoder, + &ett_mac_mgmt_msg_dsc_ack_decoder + }; + + proto_mac_mgmt_msg_dsc_decoder = proto_register_protocol ( + "WiMax DSC Messages", /* name */ + "WiMax DSC", /* short name */ + "wmx.dsc" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_dsc_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + dsc_req_handle = register_dissector("mac_mgmt_msg_dsc_req_handler", dissect_mac_mgmt_msg_dsc_req_decoder, proto_mac_mgmt_msg_dsc_decoder); + dsc_rsp_handle = register_dissector("mac_mgmt_msg_dsc_rsp_handler", dissect_mac_mgmt_msg_dsc_rsp_decoder, proto_mac_mgmt_msg_dsc_decoder); + dsc_ack_handle = register_dissector("mac_mgmt_msg_dsc_ack_handler", dissect_mac_mgmt_msg_dsc_ack_decoder, proto_mac_mgmt_msg_dsc_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_dsc(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSC_REQ, dsc_req_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSC_RSP, dsc_rsp_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSC_ACK, dsc_ack_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: + */ diff --git a/plugins/epan/wimax/msg_dsd.c b/plugins/epan/wimax/msg_dsd.c new file mode 100644 index 00000000..6f7c4c07 --- /dev/null +++ b/plugins/epan/wimax/msg_dsd.c @@ -0,0 +1,279 @@ +/* msg_dsd.c + * WiMax MAC Management DSD-REQ/RSP Messages decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +/* +#define DEBUG +*/ + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_dsd(void); +void proto_reg_handoff_mac_mgmt_msg_dsd(void); + +static dissector_handle_t dsd_req_handle; +static dissector_handle_t dsd_rsp_handle; + +static gint proto_mac_mgmt_msg_dsd_decoder = -1; +static gint ett_mac_mgmt_msg_dsd_req_decoder = -1; +static gint ett_mac_mgmt_msg_dsd_rsp_decoder = -1; +/* static gint ett_dsd_ul_sfe_decoder = -1; */ +/* static gint ett_dsd_dl_sfe_decoder = -1; */ +/* static gint ett_dsd_hmac_tuple = -1; */ +/* static gint ett_dsd_cmac_tuple = -1; */ + +/* fix fields */ +static gint hf_dsd_transaction_id = -1; +static gint hf_dsd_service_flow_id = -1; +static gint hf_dsd_confirmation_code = -1; +static gint hf_dsd_invalid_tlv = -1; +static gint hf_dsd_unknown_type = -1; + + +static int dissect_mac_mgmt_msg_dsd_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + proto_item *dsd_item; + proto_tree *dsd_tree; + proto_tree *tlv_tree = NULL; + tlv_info_t tlv_info; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC message type */ + dsd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsd_decoder, tvb, offset, -1, + "Dynamic Service Deletion Request (DSD-REQ)"); + /* add MAC DSx subtree */ + dsd_tree = proto_item_add_subtree(dsd_item, ett_mac_mgmt_msg_dsd_req_decoder); + /* Decode and display the DSD message */ + /* display the Transaction ID */ + proto_tree_add_item(dsd_tree, hf_dsd_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* display the Service Flow ID */ + proto_tree_add_item(dsd_tree, hf_dsd_service_flow_id, tvb, offset, 4, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 4; + /* process DSD REQ message TLV Encode Information */ + while(offset < tvb_len) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DSD-REQ TLV error"); + proto_tree_add_item(dsd_tree, hf_dsd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(dsd_tree, proto_mac_mgmt_msg_dsd_decoder, tvb, offset, tlv_len + tlv_value_offset, "DSD-REQ TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len + tlv_value_offset, offset, tvb_len); +#endif + /* process TLV */ + switch (tlv_type) + { + case HMAC_TUPLE: /* Table 348d */ + /* decode and display the HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dsd_req_decoder, dsd_tree, proto_mac_mgmt_msg_dsd_decoder, tvb, offset, tlv_len, "HMAC Tuple"); + wimax_hmac_tuple_decoder(tlv_tree, tvb, offset+tlv_value_offset, tlv_len); + break; + case CMAC_TUPLE: /* Table 348b */ + /* decode and display the CMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dsd_req_decoder, dsd_tree, proto_mac_mgmt_msg_dsd_decoder, tvb, offset, tlv_len, "CMAC Tuple"); + wimax_cmac_tuple_decoder(tlv_tree, tvb, offset+tlv_value_offset, tlv_len); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, dsd_tree, hf_dsd_unknown_type, tvb, offset, ENC_NA); + break; + } + offset += (tlv_len+tlv_value_offset); + } /* end of while loop */ + } + return tvb_captured_length(tvb); +} + +static int dissect_mac_mgmt_msg_dsd_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + proto_item *dsd_item; + proto_tree *dsd_tree; + proto_tree *tlv_tree = NULL; + tlv_info_t tlv_info; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC message type */ + dsd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsd_decoder, tvb, offset, -1, + "Dynamic Service Deletion Response (DSD-RSP)"); + /* add MAC DSx subtree */ + dsd_tree = proto_item_add_subtree(dsd_item, ett_mac_mgmt_msg_dsd_rsp_decoder); + /* Decode and display the DSD message */ + /* display the Transaction ID */ + proto_tree_add_item(dsd_tree, hf_dsd_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* display the Confirmation Code */ + proto_tree_add_item(dsd_tree, hf_dsd_confirmation_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next field */ + offset++; + /* display the Service Flow ID */ + proto_tree_add_item(dsd_tree, hf_dsd_service_flow_id, tvb, offset, 4, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 4; + /* process DSD RSP message TLV Encode Information */ + while(offset < tvb_len) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DSD RSP TLV error"); + proto_tree_add_item(dsd_tree, hf_dsd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(dsd_tree, proto_mac_mgmt_msg_dsd_decoder, tvb, offset, tlv_len + tlv_value_offset, "DSD-RSP TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len + tlv_value_offset, offset, tvb_len); +#endif + /* process TLV */ + switch (tlv_type) + { + case HMAC_TUPLE: /* Table 348d */ + /* decode and display the HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dsd_req_decoder, dsd_tree, proto_mac_mgmt_msg_dsd_decoder, tvb, offset, tlv_len, "HMAC Tuple"); + wimax_hmac_tuple_decoder(tlv_tree, tvb, offset+tlv_value_offset, tlv_len); + break; + case CMAC_TUPLE: /* Table 348b */ + /* decode and display the CMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_dsd_req_decoder, dsd_tree, proto_mac_mgmt_msg_dsd_decoder, tvb, offset, tlv_len, "CMAC Tuple"); + wimax_cmac_tuple_decoder(tlv_tree, tvb, offset+tlv_value_offset, tlv_len); + break; + default: + add_tlv_subtree(&tlv_info, dsd_tree, hf_dsd_unknown_type, tvb, offset, ENC_NA); + break; + } + offset += (tlv_len+tlv_value_offset); + } /* end of while loop */ + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_dsd(void) +{ + /* DSx display */ + static hf_register_info hf[] = + { + { + &hf_dsd_confirmation_code, + { + "Confirmation code", "wmx.dsd.confirmation_code", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dsd_service_flow_id, + { + "Service Flow ID", "wmx.dsd.service_flow_id", + FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dsd_transaction_id, + { + "Transaction ID", "wmx.dsd.transaction_id", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dsd_invalid_tlv, + { + "Invalid TLV", "wmx.dsd.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_dsd_unknown_type, + { + "Unknown type", "wmx.dsd.unknown_type", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_dsd_req_decoder, + &ett_mac_mgmt_msg_dsd_rsp_decoder, + /* &ett_dsd_ul_sfe_decoder, */ + /* &ett_dsd_dl_sfe_decoder, */ + /* &ett_dsd_hmac_tuple, */ + /* &ett_dsd_cmac_tuple, */ + }; + + proto_mac_mgmt_msg_dsd_decoder = proto_register_protocol ( + "WiMax DSD Messages", /* name */ + "WiMax DSD", /* short name */ + "wmx.dsd" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_dsd_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + dsd_req_handle = register_dissector("mac_mgmt_msg_dsd_req_handler", dissect_mac_mgmt_msg_dsd_req_decoder, proto_mac_mgmt_msg_dsd_decoder); + dsd_rsp_handle = register_dissector("mac_mgmt_msg_dsd_rsp_handler", dissect_mac_mgmt_msg_dsd_rsp_decoder, proto_mac_mgmt_msg_dsd_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_dsd(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSD_REQ, dsd_req_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSD_RSP, dsd_rsp_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: + */ diff --git a/plugins/epan/wimax/msg_dsx_rvd.c b/plugins/epan/wimax/msg_dsx_rvd.c new file mode 100644 index 00000000..4362a9ef --- /dev/null +++ b/plugins/epan/wimax/msg_dsx_rvd.c @@ -0,0 +1,107 @@ +/* msg_dsx_rvd.c + * WiMax MAC Management DSX-RVD Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_mac.h" + +void proto_register_mac_mgmt_msg_dsx_rvd(void); +void proto_reg_handoff_mac_mgmt_msg_dsx_rvd(void); + +static dissector_handle_t dsx_rvd_handle; + +static gint proto_mac_mgmt_msg_dsx_rvd_decoder = -1; +static gint ett_mac_mgmt_msg_dsx_rvd_decoder = -1; + +/* fix fields */ +static gint hf_dsx_rvd_transaction_id = -1; +static gint hf_dsx_rvd_confirmation_code = -1; + + +/* Decode DSX-RVD messages. */ +static int dissect_mac_mgmt_msg_dsx_rvd_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *dsx_rvd_item; + proto_tree *dsx_rvd_tree; + + { /* we are being asked for details */ + /* display MAC message type */ + dsx_rvd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_dsx_rvd_decoder, tvb, offset, -1, "DSx Received (DSX-RVD)"); + /* add MAC DSx subtree */ + dsx_rvd_tree = proto_item_add_subtree(dsx_rvd_item, ett_mac_mgmt_msg_dsx_rvd_decoder); + /* display the Transaction ID */ + proto_tree_add_item(dsx_rvd_tree, hf_dsx_rvd_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* move to next field */ + offset += 2; + /* display the Confirmation Code */ + proto_tree_add_item(dsx_rvd_tree, hf_dsx_rvd_confirmation_code, tvb, offset, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_dsx_rvd(void) +{ + /* DSX_RVD display */ + static hf_register_info hf_dsx_rvd[] = + { + { + &hf_dsx_rvd_confirmation_code, + { "Confirmation code", "wmx.dsx_rvd.confirmation_code", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_dsx_rvd_transaction_id, + { "Transaction ID", "wmx.dsx_rvd.transaction_id", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL} + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_dsx_rvd_decoder, + }; + + proto_mac_mgmt_msg_dsx_rvd_decoder = proto_register_protocol ( + "WiMax DSX-RVD Message", /* name */ + "WiMax DSX-RVD (dsx_rvd)", /* short name */ + "wmx.dsx_rvd" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_dsx_rvd_decoder, hf_dsx_rvd, array_length(hf_dsx_rvd)); + proto_register_subtree_array(ett, array_length(ett)); + dsx_rvd_handle = register_dissector("mac_mgmt_msg_dsx_rvd_handler", dissect_mac_mgmt_msg_dsx_rvd_decoder, proto_mac_mgmt_msg_dsx_rvd_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_dsx_rvd(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_DSX_RVD, dsx_rvd_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: + */ diff --git a/plugins/epan/wimax/msg_fpc.c b/plugins/epan/wimax/msg_fpc.c new file mode 100644 index 00000000..42b50141 --- /dev/null +++ b/plugins/epan/wimax/msg_fpc.c @@ -0,0 +1,166 @@ +/* msg_fpc.c + * WiMax MAC Management FPC Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_mac.h" + + +void proto_register_mac_mgmt_msg_fpc(void); +void proto_reg_handoff_mac_mgmt_msg_fpc(void); + +static dissector_handle_t fpc_handle; + +static gint proto_mac_mgmt_msg_fpc_decoder = -1; + +static gint ett_mac_mgmt_msg_fpc_decoder = -1; + +/* FPC fields */ +static gint hf_fpc_number_of_stations = -1; +static gint hf_fpc_basic_cid = -1; +static gint hf_fpc_power_adjust = -1; +static gint hf_fpc_power_measurement_frame = -1; +/* static gint hf_fpc_invalid_tlv = -1; */ + + +/* Decode FPC messages. */ +static int dissect_mac_mgmt_msg_fpc_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint i; + guint number_stations; + guint tvb_len; + proto_item *fpc_item; + proto_tree *fpc_tree; + gint8 value; + gfloat power_change; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type FPC */ + fpc_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_fpc_decoder, tvb, 0, -1, "MAC Management Message, FPC"); + /* add MAC FPC subtree */ + fpc_tree = proto_item_add_subtree(fpc_item, ett_mac_mgmt_msg_fpc_decoder); + + /* display the Number of stations */ + proto_tree_add_item(fpc_tree, hf_fpc_number_of_stations, tvb, offset, 1, ENC_BIG_ENDIAN); + + number_stations = tvb_get_guint8(tvb, offset); + offset++; + for (i = 0; ((i < number_stations) && (offset >= tvb_len)); i++ ) { + /* display the Basic CID*/ + proto_tree_add_item(fpc_tree, hf_fpc_basic_cid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* display the Power adjust value */ + value = tvb_get_gint8(tvb, offset); + power_change = (float)0.25 * value; /* 0.25dB incr */ + + /* display the Power adjust value in dB */ + proto_tree_add_float_format_value(fpc_tree, hf_fpc_power_adjust, tvb, offset, 1, power_change, " %.2f dB", power_change); + offset++; + + /* display the Power measurement frame */ + proto_tree_add_item(fpc_tree, hf_fpc_power_measurement_frame, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + } + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_fpc(void) +{ + /* FPC fields display */ + static hf_register_info hf[] = + { + { + &hf_fpc_basic_cid, + { + "Basic CID", "wmx.fpc.basic_cid", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#if 0 + { + &hf_fpc_invalid_tlv, + { + "Invalid TLV", "wmx.fpc.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, +#endif + { + &hf_fpc_number_of_stations, + { + "Number of stations", "wmx.fpc.number_stations", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_fpc_power_adjust, + { + "Power Adjust", "wmx.fpc.power_adjust", + FT_FLOAT, BASE_NONE, NULL, 0x0, "Signed change in power level (incr of 0.25dB) that the SS shall apply to its current power setting", HFILL + } + }, + { + &hf_fpc_power_measurement_frame, + { + "Power measurement frame", "wmx.fpc.power_measurement_frame", + FT_INT8, BASE_DEC, NULL, 0x0, "The 8 LSB of the frame number in which the BS measured the power corrections referred to in the message", HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_fpc_decoder, + }; + + proto_mac_mgmt_msg_fpc_decoder = proto_register_protocol ( + "WiMax FPC Message", /* name */ + "WiMax FPC (fpc)", /* short name */ + "wmx.fpc" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_fpc_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + fpc_handle = register_dissector("mac_mgmt_msg_fpc_handler", dissect_mac_mgmt_msg_fpc_decoder, proto_mac_mgmt_msg_fpc_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_fpc(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_FPC, fpc_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: + */ diff --git a/plugins/epan/wimax/msg_pkm.c b/plugins/epan/wimax/msg_pkm.c new file mode 100644 index 00000000..b91f2601 --- /dev/null +++ b/plugins/epan/wimax/msg_pkm.c @@ -0,0 +1,178 @@ +/* msg_pkm.c + * WiMax MAC Management PKM-REQ/RSP Messages decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#if 0 +#define DEBUG /* for debug only */ +#endif + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_pkm(void); +void proto_reg_handoff_mac_mgmt_msg_pkm(void); + +static dissector_handle_t mac_mgmt_msg_pkm_req_handle; +static dissector_handle_t mac_mgmt_msg_pkm_rsp_handle; + + +static gint proto_mac_mgmt_msg_pkm_decoder = -1; +static gint ett_mac_mgmt_msg_pkm_req_decoder = -1; +static gint ett_mac_mgmt_msg_pkm_rsp_decoder = -1; + +static const value_string vals_pkm_msg_code[] = +{ + { 3, "SA ADD"}, + { 4, "Auth Request"}, + { 5, "Auth Reply"}, + { 6, "Auth Reject"}, + { 7, "Key Request"}, + { 8, "Key Reply"}, + { 9, "Key Reject"}, + {10, "Auth Invalid"}, + {11, "TEK Invalid"}, + {12, "Auth Info"}, + {13, "PKMv2 RSA-Request"}, + {14, "PKMv2 RSA-Reply"}, + {15, "PKMv2 RSA-Reject"}, + {16, "PKMv2 RSA-Acknowledgement"}, + {17, "PKMv2 EAP Start"}, + {18, "PKMv2 EAP-Transfer"}, + {19, "PKMv2 Authenticated EAP-Transfer"}, + {20, "PKMv2 SA TEK Challenge"}, + {21, "PKMv2 SA TEK Request"}, + {22, "PKMv2 SA TEK Response"}, + {23, "PKMv2 Key-Request"}, + {24, "PKMv2 Key-Reply"}, + {25, "PKMv2 Key-Reject"}, + {26, "PKMv2 SA-Addition"}, + {27, "PKMv2 TEK-Invalid"}, + {28, "PKMv2 Group-Key-Update-Command"}, + {29, "PKMv2 EAP Complete"}, + {30, "PKMv2 Authenticated EAP Start"}, + { 0, NULL} +}; + +/* fix fields */ +static gint hf_pkm_msg_code = -1; +static gint hf_pkm_msg_pkm_id = -1; + + +/* Wimax Mac PKM-REQ Message Dissector */ +static int dissect_mac_mgmt_msg_pkm_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *pkm_item; + proto_tree *pkm_tree; + + /* display MAC payload type PKM-REQ */ + pkm_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_pkm_decoder, tvb, offset, -1, "Privacy Key Management Request (PKM-REQ)"); + /* add MAC PKM subtree */ + pkm_tree = proto_item_add_subtree(pkm_item, ett_mac_mgmt_msg_pkm_req_decoder); + /* Decode and display the Privacy Key Management Request Message (PKM-REQ) (table 24) */ + /* display the PKM Code */ + proto_tree_add_item(pkm_tree, hf_pkm_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* set the offset for the PKM ID */ + offset++; + /* display the PKM ID */ + proto_tree_add_item(pkm_tree, hf_pkm_msg_pkm_id, tvb, offset, 1, ENC_BIG_ENDIAN); + /* set the offset for the TLV Encoded info */ + offset++; + wimax_pkm_tlv_encoded_attributes_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, pkm_tree); + return tvb_captured_length(tvb); +} + +/* Wimax Mac PKM-RSP Message Dissector */ +static int dissect_mac_mgmt_msg_pkm_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *pkm_item; + proto_tree *pkm_tree; + + /* display MAC payload type PKM-RSP */ + pkm_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_pkm_decoder, tvb, offset, -1, "Privacy Key Management Response (PKM-RSP)"); + /* add MAC PKM subtree */ + pkm_tree = proto_item_add_subtree(pkm_item, ett_mac_mgmt_msg_pkm_rsp_decoder); + /* Decode and display the Privacy Key Management Response (PKM-RSP) (table 25) */ + /* display the PKM Code */ + proto_tree_add_item(pkm_tree, hf_pkm_msg_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* set the offset for the PKM ID */ + offset++; + /* display the PKM ID */ + proto_tree_add_item(pkm_tree, hf_pkm_msg_pkm_id, tvb, offset, 1, ENC_BIG_ENDIAN); + /* set the offset for the TLV Encoded info */ + offset++; + /* process the PKM TLV Encoded Attributes */ + wimax_pkm_tlv_encoded_attributes_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, pkm_tree); + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac PKM-REQ/RSP Messages Dissectors */ +void proto_register_mac_mgmt_msg_pkm(void) +{ + /* PKM display */ + static hf_register_info hf_pkm[] = + { + { + &hf_pkm_msg_code, + {"Code", "wmx.pkm.msg_code",FT_UINT8, BASE_DEC, VALS(vals_pkm_msg_code),0x0, NULL, HFILL} + }, + { + &hf_pkm_msg_pkm_id, + {"PKM Identifier", "wmx.pkm.msg_pkm_identifier",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + }; + + /* Setup protocol subtree array */ + static gint *ett_pkm[] = + { + &ett_mac_mgmt_msg_pkm_req_decoder, + &ett_mac_mgmt_msg_pkm_rsp_decoder, + }; + + proto_mac_mgmt_msg_pkm_decoder = proto_register_protocol ( + "WiMax PKM-REQ/RSP Messages", /* name */ + "WiMax PKM-REQ/RSP (pkm)", /* short name */ + "wmx.pkm" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_pkm_decoder, hf_pkm, array_length(hf_pkm)); + proto_register_subtree_array(ett_pkm, array_length(ett_pkm)); + mac_mgmt_msg_pkm_req_handle = register_dissector("mac_mgmt_msg_pkm_req_handler", dissect_mac_mgmt_msg_pkm_req_decoder, proto_mac_mgmt_msg_pkm_decoder); + mac_mgmt_msg_pkm_rsp_handle = register_dissector("mac_mgmt_msg_pkm_rsp_handler", dissect_mac_mgmt_msg_pkm_rsp_decoder, proto_mac_mgmt_msg_pkm_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_pkm(void) +{ + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_PKM_REQ, mac_mgmt_msg_pkm_req_handle ); + dissector_add_uint( "wmx.mgmtmsg", MAC_MGMT_MSG_PKM_RSP, mac_mgmt_msg_pkm_rsp_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: + */ diff --git a/plugins/epan/wimax/msg_pmc.c b/plugins/epan/wimax/msg_pmc.c new file mode 100644 index 00000000..7fe16e04 --- /dev/null +++ b/plugins/epan/wimax/msg_pmc.c @@ -0,0 +1,248 @@ +/* msg_pmc.c + * WiMax MAC Management PMC-REQ, PMC-RSP Message decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + + +#include +#include "wimax_mac.h" + +extern gboolean include_cor2_changes; + +void proto_register_mac_mgmt_msg_pmc_req(void); +void proto_register_mac_mgmt_msg_pmc_rsp(void); +void proto_reg_handoff_mac_mgmt_msg_pmc(void); +static int dissect_mac_mgmt_msg_pmc_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); +static int dissect_mac_mgmt_msg_pmc_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); + +static dissector_handle_t pmc_req_handle; +static dissector_handle_t pmc_rsp_handle; + +static gint proto_mac_mgmt_msg_pmc_req_decoder = -1; +static gint proto_mac_mgmt_msg_pmc_rsp_decoder = -1; + +static gint ett_mac_mgmt_msg_pmc_decoder = -1; + +/* Setup protocol subtree array */ +static gint *ett[] = +{ + &ett_mac_mgmt_msg_pmc_decoder, +}; + +/* PMC fields */ +static gint hf_pmc_req_pwr_control_mode_change = -1; +static gint hf_pmc_req_pwr_control_mode_change_cor2 = -1; +static gint hf_pmc_req_tx_power_level = -1; +static gint hf_pmc_req_confirmation = -1; +static gint hf_pmc_req_reserved = -1; +static gint hf_pmc_rsp_start_frame = -1; +static gint hf_pmc_rsp_power_adjust = -1; +static gint hf_pmc_rsp_offset_BS_per_MS = -1; + +/* STRING RESOURCES */ +static const value_string vals_pmc_req_pwr[] = { + {0, "Closed loop power control mode"}, + {1, "Reserved"}, + {2, "Open loop power control passive mode"}, + {3, "Open loop power control active mode"}, + {0, NULL} +}; + +static const value_string vals_pmc_req_pwr_cor2[] = { + {0, "Closed loop power control mode"}, + {1, "Open loop power control passive mode with Offset_SSperSS retention"}, + {2, "Open loop power control passive mode with Offset_SSperSS reset"}, + {3, "Open loop power control active mode"}, + {0, NULL} +}; + +static const value_string vals_pmc_req_confirmation[] = { + {0, "MS requests to change the power control mode"}, + {1, "MS confirms the receipt of PMC_RSP from BS"}, + {0, NULL} +}; + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_pmc_req(void) +{ + /* PMC fields display */ + static hf_register_info hf[] = + { + { + &hf_pmc_req_confirmation, + { + "Confirmation", "wmx.pmc_req.confirmation", + FT_UINT16, BASE_DEC, VALS(vals_pmc_req_confirmation), 0x0020, NULL, HFILL + } + }, + { + &hf_pmc_req_pwr_control_mode_change, + { + "Power control mode change", "wmx.pmc_req.power_control_mode", + FT_UINT16, BASE_DEC, VALS(vals_pmc_req_pwr), 0xC000, NULL, HFILL + } + }, + { + &hf_pmc_req_pwr_control_mode_change_cor2, + { + "Power control mode change", "wmx.pmc_req.power_control_mode", + FT_UINT16, BASE_DEC, VALS(vals_pmc_req_pwr_cor2), 0xC000, NULL, HFILL + } + }, + { + &hf_pmc_req_reserved, + { + "Reserved", "wmx.pmc_req.reserved", + FT_UINT16, BASE_DEC, NULL, 0x001F, NULL, HFILL + } + }, + { + &hf_pmc_req_tx_power_level, + { + "UL Tx power level for the burst that carries this header", "wmx.pmc_req.ul_tx_power_level", + FT_UINT16, BASE_DEC, NULL, 0x3FC0, "When the Tx power is different from slot to slot, the maximum value is reported", HFILL + } + }, + { + &hf_pmc_rsp_offset_BS_per_MS, + { + "Offset_BS per MS", "wmx.pmc_rsp.offset_BS_per_MS", + FT_FLOAT, BASE_NONE, NULL, 0x0, "Signed change in power level (incr of 0.25 dB) that the MS shall apply to the open loop power control formula in 8.4.10.3.2", HFILL + } + }, + { + &hf_pmc_rsp_power_adjust, + { + "Power adjust", "wmx.pmc_rsp.power_adjust", + FT_FLOAT, BASE_NONE, NULL, 0x0, "Signed change in power level (incr of 0.25 dB) that the MS shall apply to its current transmission power. When subchannelization is employed, the SS shall interpret as a required change to the Tx power density", HFILL + } + }, + { + &hf_pmc_rsp_start_frame, + { + "Start frame", "wmx.pmc_rsp.start_frame", + FT_UINT16, BASE_HEX, NULL, 0x3F00, "Apply mode change from current frame when 6 LSBs of frame match this", HFILL + } + } + }; + + proto_mac_mgmt_msg_pmc_req_decoder = proto_register_protocol ( + "WiMax PMC-REQ Messages", /* name */ + "WiMax PMC-REQ", /* short name */ + "wmx.pmc_req" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_pmc_req_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + pmc_req_handle = register_dissector("mac_mgmt_msg_pmc_req_handler", dissect_mac_mgmt_msg_pmc_req_decoder, proto_mac_mgmt_msg_pmc_req_decoder); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_pmc_rsp(void) +{ + proto_mac_mgmt_msg_pmc_rsp_decoder = proto_register_protocol ( + "WiMax PMC-RSP Messages", /* name */ + "WiMax PMC-RSP", /* short name */ + "wmx.pmc_rsp" /* abbrev */ + ); + pmc_rsp_handle = register_dissector("mac_mgmt_msg_pmc_rsp_handler", dissect_mac_mgmt_msg_pmc_rsp_decoder, proto_mac_mgmt_msg_pmc_rsp_decoder); +} + +/* Decode PMC-REQ messages. */ +static int dissect_mac_mgmt_msg_pmc_req_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *pmc_req_item; + proto_tree *pmc_req_tree; + + { /* we are being asked for details */ + + /* display MAC payload type PMC-REQ */ + pmc_req_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_pmc_req_decoder, tvb, 0, -1, "MAC Management Message, PMC-REQ"); + /* add MAC PMC REQ subtree */ + pmc_req_tree = proto_item_add_subtree(pmc_req_item, ett_mac_mgmt_msg_pmc_decoder); + /* display the Power Control Mode Change */ + proto_tree_add_item(pmc_req_tree, hf_pmc_req_pwr_control_mode_change, tvb, offset, 2, ENC_BIG_ENDIAN); + /* show the Transmit Power Level */ + proto_tree_add_item(pmc_req_tree, hf_pmc_req_tx_power_level, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the Confirmation/request */ + proto_tree_add_item(pmc_req_tree, hf_pmc_req_confirmation, tvb, offset, 2, ENC_BIG_ENDIAN); + /* show the Reserved bits */ + proto_tree_add_item(pmc_req_tree, hf_pmc_req_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +/* Decode PMC-RSP messages. */ +static int dissect_mac_mgmt_msg_pmc_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *pmc_rsp_item; + proto_tree *pmc_rsp_tree; + guint8 pwr_control_mode; + gint8 value; + gfloat power_change; + + { /* we are being asked for details */ + + /* display MAC payload type PMC-RSP */ + pmc_rsp_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_pmc_rsp_decoder, tvb, 0, -1, "MAC Management Message, PMC-RSP"); + /* add MAC PMC RSP subtree */ + pmc_rsp_tree = proto_item_add_subtree(pmc_rsp_item, ett_mac_mgmt_msg_pmc_decoder); + + /* display the Power Control Mode Change */ + if (include_cor2_changes) + proto_tree_add_item(pmc_rsp_tree, hf_pmc_req_pwr_control_mode_change_cor2, tvb, offset, 2, ENC_BIG_ENDIAN); + else + proto_tree_add_item(pmc_rsp_tree, hf_pmc_req_pwr_control_mode_change, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the Power Adjust start frame */ + proto_tree_add_item(pmc_rsp_tree, hf_pmc_rsp_start_frame, tvb, offset, 2, ENC_BIG_ENDIAN); + pwr_control_mode = 0xC0 & tvb_get_guint8(tvb, offset); + offset++; + + value = tvb_get_gint8(tvb, offset); + power_change = (float)0.25 * value; /* 0.25dB incr */ + /* Check if Power Control Mode is 0 */ + if (pwr_control_mode == 0) { + /* display the amount of power change requested */ + proto_tree_add_float_format_value(pmc_rsp_tree, hf_pmc_rsp_power_adjust, tvb, offset, 1, power_change, " %.2f dB", power_change); + } else { + /* display the amount of MS power change requested */ + proto_tree_add_float_format_value(pmc_rsp_tree, hf_pmc_rsp_offset_BS_per_MS, tvb, offset, 1, power_change, " %.2f dB", power_change); + } + } + return tvb_captured_length(tvb); +} + +void +proto_reg_handoff_mac_mgmt_msg_pmc(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_PMC_REQ, pmc_req_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_PMC_RSP, pmc_rsp_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: + */ diff --git a/plugins/epan/wimax/msg_prc_lt_ctrl.c b/plugins/epan/wimax/msg_prc_lt_ctrl.c new file mode 100644 index 00000000..f8b5b97f --- /dev/null +++ b/plugins/epan/wimax/msg_prc_lt_ctrl.c @@ -0,0 +1,136 @@ +/* msg_prc_lt_ctrl.c + * WiMax MAC Management PRC-LT-CTRL Message decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_mac.h" + + +void proto_register_mac_mgmt_msg_prc_lt_ctrl(void); +void proto_reg_handoff_mac_mgmt_msg_prc_lt_ctrl(void); + +static dissector_handle_t prc_handle; + +static gint proto_mac_mgmt_msg_prc_lt_ctrl_decoder = -1; + +static gint ett_mac_mgmt_msg_prc_lt_ctrl_decoder = -1; + +/* PRC-LT-CTRL fields */ +static gint hf_prc_lt_ctrl_precoding = -1; +static gint hf_prc_lt_ctrl_precoding_delay = -1; +/* static gint hf_prc_lt_ctrl_invalid_tlv = -1; */ + +static const value_string vals_turn_on[] = { + {0, "Turn off"}, + {1, "Turn on"}, + {0, NULL} +}; + + +/* Decode PRC-LT-CTRL messages. */ +static int dissect_mac_mgmt_msg_prc_lt_ctrl_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + proto_item *prc_lt_ctrl_item; + proto_tree *prc_lt_ctrl_tree; + + { /* we are being asked for details */ + + /* display MAC payload type PRC-LT-CTRL */ + prc_lt_ctrl_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_prc_lt_ctrl_decoder, tvb, 0, -1, "MAC Management Message, PRC-LT-CTRL"); + + /* add MAC PRC-LT-CTRL subtree */ + prc_lt_ctrl_tree = proto_item_add_subtree(prc_lt_ctrl_item, ett_mac_mgmt_msg_prc_lt_ctrl_decoder); + + /* display whether to Setup or Tear-down the + * long-term MIMO precoding delay */ + proto_tree_add_item(prc_lt_ctrl_tree, hf_prc_lt_ctrl_precoding, tvb, offset, 1, ENC_BIG_ENDIAN); + + /* display the Precoding Delay */ + proto_tree_add_item(prc_lt_ctrl_tree, hf_prc_lt_ctrl_precoding_delay, tvb, offset, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_prc_lt_ctrl(void) +{ + /* PRC-LT-CTRL fields display */ + static hf_register_info hf[] = + { +#if 0 + { + &hf_prc_lt_ctrl_invalid_tlv, + { + "Invalid TLV", "wmx.prc_lt_ctrl.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, +#endif + { + &hf_prc_lt_ctrl_precoding, + { + "Setup/Tear-down long-term precoding with feedback", + "wmx.prc_lt_ctrl.precoding", + FT_UINT8, BASE_DEC, VALS(vals_turn_on), 0x80, NULL, HFILL + } + }, + { + &hf_prc_lt_ctrl_precoding_delay, + { + "BS precoding application delay", + "wmx.prc_lt_ctrl.precoding_delay", + FT_UINT8, BASE_DEC, NULL, 0x60, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_prc_lt_ctrl_decoder, + }; + + proto_mac_mgmt_msg_prc_lt_ctrl_decoder = proto_register_protocol ( + "WiMax PRC-LT-CTRL Message", /* name */ + "WiMax PRC-LT-CTRL (prc)", /* short name */ + "wmx.prc_lt_ctrl" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_prc_lt_ctrl_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + prc_handle = register_dissector("mac_mgmt_msg_prc_lt_ctrl_handler", dissect_mac_mgmt_msg_prc_lt_ctrl_decoder, proto_mac_mgmt_msg_prc_lt_ctrl_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_prc_lt_ctrl(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_PRC_LT_CTRL, prc_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: + */ diff --git a/plugins/epan/wimax/msg_reg_req.c b/plugins/epan/wimax/msg_reg_req.c new file mode 100644 index 00000000..f0ba1a5f --- /dev/null +++ b/plugins/epan/wimax/msg_reg_req.c @@ -0,0 +1,1440 @@ +/* msg_reg_req.c + * WiMax MAC Management REG-REQ Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#define WIMAX_16E_2005 + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +extern gboolean include_cor2_changes; + +void proto_register_mac_mgmt_msg_reg_req(void); +void proto_reg_handoff_mac_mgmt_msg_reg_req(void); + +static dissector_handle_t reg_req_handle; + +static gint proto_mac_mgmt_msg_reg_req_decoder = -1; +static gint ett_mac_mgmt_msg_reg_req_decoder = -1; + +/* REG-REQ fields */ +static gint hf_reg_ss_mgmt_support = -1; +static gint hf_reg_ip_mgmt_mode = -1; +static gint hf_reg_ip_version = -1; +static gint hf_reg_req_secondary_mgmt_cid = -1; +static gint hf_reg_ul_cids = -1; +static gint hf_reg_max_classifiers = -1; +static gint hf_reg_phs = -1; +static gint hf_reg_arq = -1; +static gint hf_reg_dsx_flow_control = -1; +static gint hf_reg_mac_crc_support = -1; +static gint hf_reg_mca_flow_control = -1; +static gint hf_reg_mcast_polling_cids = -1; +static gint hf_reg_num_dl_trans_cid = -1; +static gint hf_reg_mac_address = -1; +static gint hf_reg_tlv_t_20_1_max_mac_level_data_per_dl_frame = -1; +static gint hf_reg_tlv_t_20_2_max_mac_level_data_per_ul_frame = -1; +static gint hf_reg_tlv_t_21_packing_support = -1; +static gint hf_reg_tlv_t_22_mac_extended_rtps_support = -1; +static gint hf_reg_tlv_t_23_max_num_bursts_concurrently_to_the_ms = -1; +static gint hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_dhcp = -1; +static gint hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_mobile_ipv4 = -1; +static gint hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_dhcpv6 = -1; +static gint hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_ipv6 = -1; +static gint hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_rsvd = -1; +static gint hf_reg_tlv_t_27_handover_fbss_mdho_ho_disable = -1; +static gint hf_reg_tlv_t_27_handover_fbss_mdho_dl_rf_monitoring_maps = -1; +static gint hf_reg_tlv_t_27_handover_mdho_dl_monitoring_single_map = -1; +static gint hf_reg_tlv_t_27_handover_mdho_dl_monitoring_maps = -1; +static gint hf_reg_tlv_t_27_handover_mdho_ul_multiple = -1; +static gint hf_reg_tlv_t_27_handover_reserved = -1; +static gint hf_reg_tlv_t_29_ho_process_opt_ms_timer = -1; +static gint hf_reg_tlv_t_31_mobility_handover = -1; +static gint hf_reg_tlv_t_31_mobility_sleep_mode = -1; +static gint hf_reg_tlv_t_31_mobility_idle_mode = -1; +static gint hf_reg_req_tlv_t_32_sleep_mode_recovery_time = -1; +static gint hf_ms_previous_ip_address_v4 = -1; +static gint hf_ms_previous_ip_address_v6 = -1; +static gint hf_idle_mode_timeout = -1; +static gint hf_reg_req_tlv_t_45_ms_periodic_ranging_timer = -1; +static gint hf_reg_tlv_t_40_arq_ack_type_selective_ack_entry = -1; +static gint hf_reg_tlv_t_40_arq_ack_type_cumulative_ack_entry = -1; +static gint hf_reg_tlv_t_40_arq_ack_type_cumulative_with_selective_ack_entry = -1; +static gint hf_reg_tlv_t_40_arq_ack_type_cumulative_ack_with_block_sequence_ack = -1; +static gint hf_reg_tlv_t_40_arq_ack_type_reserved = -1; +static gint hf_reg_tlv_t_41_ho_connections_param_processing_time = -1; +static gint hf_reg_tlv_t_42_ho_tek_processing_time = -1; +static gint hf_reg_tlv_t_43_bandwidth_request_ul_tx_power_report_header_support = -1; +static gint hf_reg_tlv_t_43_bandwidth_request_cinr_report_header_support = -1; +static gint hf_reg_tlv_t_43_cqich_allocation_request_header_support = -1; +static gint hf_reg_tlv_t_43_phy_channel_report_header_support = -1; +static gint hf_reg_tlv_t_43_bandwidth_request_ul_sleep_control_header_support = -1; +static gint hf_reg_tlv_t_43_sn_report_header_support = -1; +static gint hf_reg_tlv_t_43_feedback_header_support = -1; +static gint hf_reg_tlv_t_43_sdu_sn_extended_subheader_support_and_parameter = -1; +static gint hf_reg_tlv_t_43_sdu_sn_parameter = -1; +static gint hf_reg_tlv_t_43_dl_sleep_control_extended_subheader = -1; +static gint hf_reg_tlv_t_43_feedback_request_extended_subheader = -1; +static gint hf_reg_tlv_t_43_mimo_mode_feedback_extended_subheader = -1; +static gint hf_reg_tlv_t_43_ul_tx_power_report_extended_subheader = -1; +static gint hf_reg_tlv_t_43_mini_feedback_extended_subheader = -1; +static gint hf_reg_tlv_t_43_sn_request_extended_subheader = -1; +static gint hf_reg_tlv_t_43_pdu_sn_short_extended_subheader = -1; +static gint hf_reg_tlv_t_43_pdu_sn_long_extended_subheader = -1; +static gint hf_reg_tlv_t_43_reserved = -1; +static gint hf_reg_tlv_t_46_handover_indication_readiness_timer = -1; +static gint hf_reg_req_min_time_for_intra_fa = -1; +static gint hf_reg_req_min_time_for_inter_fa = -1; +static gint hf_reg_encap_atm_4 = -1; +static gint hf_reg_encap_ipv4_4 = -1; +static gint hf_reg_encap_ipv6_4 = -1; +static gint hf_reg_encap_802_3_4 = -1; +static gint hf_reg_encap_802_1q_4 = -1; +static gint hf_reg_encap_ipv4_802_3_4 = -1; +static gint hf_reg_encap_ipv6_802_3_4 = -1; +static gint hf_reg_encap_ipv4_802_1q_4 = -1; +static gint hf_reg_encap_ipv6_802_1q_4 = -1; +static gint hf_reg_encap_packet_8023_ethernet_and_rohc_header_compression_4 = -1; +static gint hf_reg_encap_packet_8023_ethernet_and_ecrtp_header_compression_4 = -1; +static gint hf_reg_encap_packet_ip_rohc_header_compression_4 = -1; +static gint hf_reg_encap_packet_ip_ecrtp_header_compression_4 = -1; +static gint hf_reg_encap_rsvd_4 = -1; +static gint hf_reg_encap_atm_2 = -1; +static gint hf_reg_encap_ipv4_2 = -1; +static gint hf_reg_encap_ipv6_2 = -1; +static gint hf_reg_encap_802_3_2 = -1; +static gint hf_reg_encap_802_1q_2 = -1; +static gint hf_reg_encap_ipv4_802_3_2 = -1; +static gint hf_reg_encap_ipv6_802_3_2 = -1; +static gint hf_reg_encap_ipv4_802_1q_2 = -1; +static gint hf_reg_encap_ipv6_802_1q_2 = -1; +static gint hf_reg_encap_packet_8023_ethernet_and_rohc_header_compression_2 = -1; +static gint hf_reg_encap_packet_8023_ethernet_and_ecrtp_header_compression_2 = -1; +static gint hf_reg_encap_packet_ip_rohc_header_compression_2 = -1; +static gint hf_reg_encap_packet_ip_ecrtp_header_compression_2 = -1; +static gint hf_reg_encap_rsvd_2 = -1; +static gint hf_tlv_type = -1; +static gint hf_reg_invalid_tlv = -1; +static gint hf_reg_power_saving_class_type_i = -1; +static gint hf_reg_power_saving_class_type_ii = -1; +static gint hf_reg_power_saving_class_type_iii = -1; +static gint hf_reg_multi_active_power_saving_classes = -1; +static gint hf_reg_total_power_saving_class_instances = -1; +static gint hf_reg_power_saving_class_reserved = -1; +static gint hf_reg_power_saving_class_capability = -1; +static gint hf_reg_ip_phs_sdu_encap = -1; +static gint hf_reg_tlv_t_26_method_alloc_ip_addr_secondary_mgmnt_conn = -1; +static gint hf_reg_tlv_t_27_handover_supported = -1; +static gint hf_reg_tlv_t_31_mobility_features_supported = -1; +static gint hf_reg_tlv_t_40_arq_ack_type = -1; +static gint hf_reg_tlv_t_43_mac_header_ext_header_support = -1; +static gint hf_reg_req_bs_switching_timer = -1; + +/* STRING RESOURCES */ + +static const true_false_string tfs_reg_ip_mgmt_mode = { + "IP-managed mode", + "Unmanaged mode" +}; + +static const true_false_string tfs_reg_ss_mgmt_support = { + "secondary management connection", + "no secondary management connection" +}; + +#if 0 +static const true_false_string tfs_arq_enable = { + "ARQ Requested/Accepted", + "ARQ Not Requested/Accepted" +}; +#endif + +#if 0 +static const true_false_string tfs_arq_deliver_in_order = { + "Order of delivery is preserved", + "Order of delivery is not preserved" +}; +#endif + +static const true_false_string tfs_reg_fbss_mdho_ho_disable = { + "Disable", + "Enable" +}; + +static const value_string vals_reg_ip_version[] = { + {0x1, "IPv4"}, + {0x2, "IPV6"}, + {0, NULL} +}; + +static const value_string vals_reg_phs_support[] = { + {0, "no PHS support"}, + {1, "ATM PHS"}, + {2, "Packet PHS"}, + {3, "ATM and Packet PHS"}, + {0, NULL} +}; + +static const true_false_string tfs_supported = { + "supported", + "unsupported" +}; + +static const true_false_string tfs_mac_crc_support = { + "MAC CRC Support (Default)", + "No MAC CRC Support" +}; + +static const value_string tfs_support[] = { + {0, "not supported"}, + {1, "supported"}, + {0, NULL} +}; + +static const value_string unique_no_limit[] = { + {0, "no limit"}, + {0, NULL} +}; + +/* Decode REG-REQ sub-TLV's. */ +void dissect_extended_tlv(proto_tree *reg_req_tree, gint tlv_type, tvbuff_t *tvb, guint tlv_offset, guint tlv_len, packet_info *pinfo, guint offset, gint proto_registry) +{ + proto_item *tlv_item; + proto_tree *tlv_tree; + guint tvb_len; + tlv_info_t tlv_info; + guint tlv_end; + guint length; + guint nblocks; + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + +#ifdef WIMAX_16E_2005 + switch (tlv_type) { + case REG_ARQ_PARAMETERS: + /* display ARQ Service Flow Encodings info */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_req_decoder, reg_req_tree, proto_registry, tvb, offset, tlv_len, "ARQ Service Flow Encodings"); + /* decode and display the DL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree); + break; + case REG_SS_MGMT_SUPPORT: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_ss_mgmt_support, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_IP_MGMT_MODE: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_ip_mgmt_mode, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_IP_VERSION: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_ip_version, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_UL_TRANSPORT_CIDS_SUPPORTED: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_ul_cids, tvb, offset, ENC_BIG_ENDIAN); + break; + + case REG_POWER_SAVING_CLASS_CAPABILITY: + tlv_item = add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_power_saving_class_capability, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_reg_req_decoder); + proto_tree_add_item(tlv_tree, hf_reg_power_saving_class_type_i, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_power_saving_class_type_ii, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_power_saving_class_type_iii, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_multi_active_power_saving_classes, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_total_power_saving_class_instances, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_power_saving_class_reserved, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + break; + case REG_IP_PHS_SDU_ENCAP: + tlv_item = add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_ip_phs_sdu_encap, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_reg_req_decoder); + +#ifdef WIMAX_16E_2005 + if (tlv_len == 2){ + proto_tree_add_item(tlv_tree, hf_reg_encap_atm_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv4_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv6_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_802_3_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_802_1q_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv4_802_3_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv6_802_3_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv4_802_1q_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv6_802_1q_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_packet_8023_ethernet_and_rohc_header_compression_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_packet_8023_ethernet_and_ecrtp_header_compression_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_packet_ip_rohc_header_compression_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_packet_ip_ecrtp_header_compression_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_rsvd_2, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + } else if(tlv_len == 4){ + proto_tree_add_item(tlv_tree, hf_reg_encap_atm_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv4_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv6_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_802_3_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_802_1q_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv4_802_3_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv6_802_3_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv4_802_1q_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_ipv6_802_1q_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_packet_8023_ethernet_and_rohc_header_compression_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_packet_8023_ethernet_and_ecrtp_header_compression_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_packet_ip_rohc_header_compression_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_packet_ip_ecrtp_header_compression_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_encap_rsvd_4, tvb, tlv_offset, tlv_len, ENC_BIG_ENDIAN); + } +#endif + break; + case REG_MAX_CLASSIFIERS_SUPPORTED: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_max_classifiers, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_PHS_SUPPORT: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_phs, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_ARQ_SUPPORT: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_arq, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_DSX_FLOW_CONTROL: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_dsx_flow_control, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_MAC_CRC_SUPPORT: + if (!include_cor2_changes) { + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_mac_crc_support, tvb, offset, ENC_NA); + } else { + /* Unknown TLV Type */ + add_tlv_subtree(&tlv_info, reg_req_tree, hf_tlv_type, tvb, offset, ENC_NA); + } + break; + case REG_MCA_FLOW_CONTROL: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_mca_flow_control, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_MCAST_POLLING_CIDS: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_mcast_polling_cids, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_NUM_DL_TRANS_CID: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_num_dl_trans_cid, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_MAC_ADDRESS: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_mac_address, tvb, offset, ENC_NA); + break; + case REG_TLV_T_20_MAX_MAC_DATA_PER_FRAME_SUPPORT: + /* display Maximum MAC level data per frame info */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_req_decoder, reg_req_tree, proto_registry, tvb, offset, tlv_len, "Maximum MAC level data per frame"); + /* decode and display Maximum MAC level data per frame for UL & DL */ + /* Set endpoint of the subTLVs (tlv_offset + length) */ + tlv_end = tlv_offset + tlv_len; + /* process subTLVs */ + while ( tlv_offset < tlv_end ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, tlv_offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REG-REQ TLV error"); + proto_tree_add_item(reg_req_tree, hf_reg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* update the offset */ + tlv_offset += get_tlv_value_offset(&tlv_info); + nblocks = tvb_get_ntohs(tvb, tlv_offset); + switch (tlv_type) + { + case REG_TLV_T_20_1_MAX_MAC_LEVEL_DATA_PER_DL_FRAME: + tlv_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_reg_tlv_t_20_1_max_mac_level_data_per_dl_frame, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + if ( nblocks == 0 ) + { + proto_item_append_text(tlv_item, " (Unlimited bytes)"); + } else { + proto_item_append_text(tlv_item, " (%d bytes)", 256 * nblocks); + } + break; + case REG_TLV_T_20_2_MAX_MAC_LEVEL_DATA_PER_UL_FRAME: + tlv_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_reg_tlv_t_20_2_max_mac_level_data_per_ul_frame, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + if ( nblocks == 0 ) + { + proto_item_append_text(tlv_item, " (Unlimited bytes)"); + } else { + proto_item_append_text(tlv_item, " (%d bytes)", 256 * nblocks); + } + break; + default: + add_tlv_subtree(&tlv_info, tlv_tree, hf_reg_invalid_tlv, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + } + tlv_offset += length; + } + break; + + case REG_TLV_T_21_PACKING_SUPPORT: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_21_packing_support, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_22_MAC_EXTENDED_RTPS_SUPPORT: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_22_mac_extended_rtps_support, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_23_MAX_NUM_BURSTS_TRANSMITTED_CONCURRENTLY_TO_THE_MS: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_23_max_num_bursts_concurrently_to_the_ms, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_26_METHOD_FOR_ALLOCATING_IP_ADDR_SECONDARY_MGMNT_CONNECTION: + tlv_item = add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_26_method_alloc_ip_addr_secondary_mgmnt_conn, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_reg_req_decoder); + proto_tree_add_item(tlv_tree, hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_dhcp, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_mobile_ipv4, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_dhcpv6, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_ipv6, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_rsvd, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_27_HANDOVER_SUPPORTED: + tlv_item = add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_27_handover_supported, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_reg_req_decoder); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_27_handover_fbss_mdho_ho_disable, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_27_handover_fbss_mdho_dl_rf_monitoring_maps, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_27_handover_mdho_dl_monitoring_single_map, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_27_handover_mdho_dl_monitoring_maps, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_27_handover_mdho_ul_multiple, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_27_handover_reserved, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_29_HO_PROCESS_OPTIMIZATION_MS_TIMER: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_29_ho_process_opt_ms_timer, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_31_MOBILITY_FEATURES_SUPPORTED: + tlv_item = add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_31_mobility_features_supported, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_reg_req_decoder); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_31_mobility_handover, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_31_mobility_sleep_mode, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_31_mobility_idle_mode, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_40_ARQ_ACK_TYPE: + tlv_item = add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_40_arq_ack_type, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_reg_req_decoder); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_40_arq_ack_type_selective_ack_entry, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_40_arq_ack_type_cumulative_ack_entry, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_40_arq_ack_type_cumulative_with_selective_ack_entry, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_40_arq_ack_type_cumulative_ack_with_block_sequence_ack, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_40_arq_ack_type_reserved, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_41_MS_HO_CONNECTIONS_PARAM_PROCESSING_TIME: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_41_ho_connections_param_processing_time, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_42_MS_HO_TEK_PROCESSING_TIME: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_42_ho_tek_processing_time, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_TLV_T_43_MAC_HEADER_AND_EXTENDED_SUBHEADER_SUPPORT: + tlv_item = add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_43_mac_header_ext_header_support, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_reg_req_decoder); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_bandwidth_request_ul_tx_power_report_header_support, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_bandwidth_request_cinr_report_header_support, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_cqich_allocation_request_header_support, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_phy_channel_report_header_support, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_bandwidth_request_ul_sleep_control_header_support, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_sn_report_header_support, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_feedback_header_support, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_sdu_sn_extended_subheader_support_and_parameter, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_sdu_sn_parameter, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_dl_sleep_control_extended_subheader, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_feedback_request_extended_subheader, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_mimo_mode_feedback_extended_subheader, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_ul_tx_power_report_extended_subheader, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_mini_feedback_extended_subheader, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_sn_request_extended_subheader, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_pdu_sn_short_extended_subheader, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_pdu_sn_long_extended_subheader, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_tlv_t_43_reserved, tvb, tlv_offset, 3, ENC_BIG_ENDIAN); + break; + case REG_REQ_BS_SWITCHING_TIMER: + tlv_item = add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_req_bs_switching_timer, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_reg_req_decoder); + proto_tree_add_item(tlv_tree, hf_reg_req_min_time_for_intra_fa, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_reg_req_min_time_for_inter_fa, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case VENDOR_SPECIFIC_INFO: + case VENDOR_ID_ENCODING: + case CURRENT_TX_POWER: + case MAC_VERSION_ENCODING: + case CMAC_TUPLE: /* Table 348b */ + wimax_common_tlv_encoding_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, reg_req_tree); + break; + default: + add_tlv_subtree(&tlv_info, reg_req_tree, proto_registry, tvb, offset, ENC_NA); + break; + } +#endif +} + + +/* Decode REG-REQ messages. */ +static int dissect_mac_mgmt_msg_reg_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tlv_offset; + guint tvb_len; + proto_item *reg_req_item = NULL; + proto_tree *reg_req_tree = NULL; + proto_tree *tlv_tree = NULL; + gboolean hmac_found = FALSE; + tlv_info_t tlv_info; + gint tlv_type; + gint tlv_len; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type REG-REQ */ + reg_req_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_reg_req_decoder, tvb, offset, tvb_len, "MAC Management Message, REG-REQ"); + /* add MAC REG-REQ subtree */ + reg_req_tree = proto_item_add_subtree(reg_req_item, ett_mac_mgmt_msg_reg_req_decoder); + + while(offset < tvb_len) + { + /* Get the TLV data. */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REG-REQ TLV error"); + proto_tree_add_item(reg_req_tree, hf_reg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the offset to the TLV data */ + tlv_offset = offset + get_tlv_value_offset(&tlv_info); + + switch (tlv_type) { + case REG_ARQ_PARAMETERS: + case REG_SS_MGMT_SUPPORT: + case REG_IP_MGMT_MODE: + case REG_IP_VERSION: + case REG_UL_TRANSPORT_CIDS_SUPPORTED: + case REG_IP_PHS_SDU_ENCAP: + case REG_MAX_CLASSIFIERS_SUPPORTED: + case REG_PHS_SUPPORT: + case REG_ARQ_SUPPORT: + case REG_DSX_FLOW_CONTROL: + case REG_MAC_CRC_SUPPORT: + case REG_MCA_FLOW_CONTROL: + case REG_MCAST_POLLING_CIDS: + case REG_NUM_DL_TRANS_CID: + case REG_MAC_ADDRESS: +#ifdef WIMAX_16E_2005 + case REG_TLV_T_20_MAX_MAC_DATA_PER_FRAME_SUPPORT: + case REG_TLV_T_21_PACKING_SUPPORT: + case REG_TLV_T_22_MAC_EXTENDED_RTPS_SUPPORT: + case REG_TLV_T_23_MAX_NUM_BURSTS_TRANSMITTED_CONCURRENTLY_TO_THE_MS: + case REG_TLV_T_26_METHOD_FOR_ALLOCATING_IP_ADDR_SECONDARY_MGMNT_CONNECTION: + case REG_TLV_T_27_HANDOVER_SUPPORTED: + case REG_TLV_T_29_HO_PROCESS_OPTIMIZATION_MS_TIMER: + case REG_TLV_T_31_MOBILITY_FEATURES_SUPPORTED: + case REG_TLV_T_40_ARQ_ACK_TYPE: + case REG_TLV_T_41_MS_HO_CONNECTIONS_PARAM_PROCESSING_TIME: + case REG_TLV_T_42_MS_HO_TEK_PROCESSING_TIME: + case REG_TLV_T_43_MAC_HEADER_AND_EXTENDED_SUBHEADER_SUPPORT: + case REG_REQ_BS_SWITCHING_TIMER: + case REG_POWER_SAVING_CLASS_CAPABILITY: +#endif + /* Decode REG-REQ sub-TLV's. */ + dissect_extended_tlv(reg_req_tree, tlv_type, tvb, tlv_offset, tlv_len, pinfo, offset, proto_mac_mgmt_msg_reg_req_decoder); + break; + case REG_REQ_SECONDARY_MGMT_CID: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_req_secondary_mgmt_cid, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_REQ_TLV_T_32_SLEEP_MODE_RECOVERY_TIME: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_req_tlv_t_32_sleep_mode_recovery_time, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_REQ_TLV_T_33_MS_PREV_IP_ADDR: + if ( tlv_len == 4 ) { + add_tlv_subtree(&tlv_info, reg_req_tree, hf_ms_previous_ip_address_v4, tvb, offset, ENC_BIG_ENDIAN); + } else if ( tlv_len == 16 ) { + add_tlv_subtree(&tlv_info, reg_req_tree, hf_ms_previous_ip_address_v6, tvb, offset, ENC_NA); + } + break; + case REG_TLV_T_37_IDLE_MODE_TIMEOUT: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_idle_mode_timeout, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_REQ_TLV_T_45_MS_PERIODIC_RANGING_TIMER_INFO: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_req_tlv_t_45_ms_periodic_ranging_timer, tvb, offset, ENC_BIG_ENDIAN); + break; + case REG_HANDOVER_INDICATION_READINESS_TIMER: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_reg_tlv_t_46_handover_indication_readiness_timer, tvb, offset, ENC_BIG_ENDIAN); + break; + + case DSx_UPLINK_FLOW: + /* display Uplink Service Flow Encodings info */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_req_decoder, reg_req_tree, proto_mac_mgmt_msg_reg_req_decoder, tvb, offset, tlv_len, "Uplink Service Flow Encodings"); + /* decode and display the DL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree); + break; + case DSx_DOWNLINK_FLOW: + /* display Downlink Service Flow Encodings info */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_req_decoder, reg_req_tree, proto_mac_mgmt_msg_reg_req_decoder, tvb, offset, tlv_len, "Downlink Service Flow Encodings"); + /* decode and display the DL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree); + break; + case HMAC_TUPLE: /* Table 348d */ + /* decode and display the HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_req_decoder, reg_req_tree, proto_mac_mgmt_msg_reg_req_decoder, tvb, offset, tlv_len, "HMAC Tuple"); + wimax_hmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len); + hmac_found = TRUE; + break; + case CMAC_TUPLE: /* Table 348b */ + /* decode and display the CMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_req_decoder, reg_req_tree, proto_mac_mgmt_msg_reg_req_decoder, tvb, offset, tlv_len, "CMAC Tuple"); + wimax_cmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len); + break; + default: + add_tlv_subtree(&tlv_info, reg_req_tree, hf_tlv_type, tvb, offset, ENC_NA); + break; + } + /* update the offset */ + offset = tlv_len + tlv_offset; + } /* End while() looping through the tvb. */ + if (!hmac_found) + proto_item_append_text(reg_req_tree, " (HMAC Tuple is missing !)"); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_reg_req(void) +{ + /* REG-REQ fields display */ + static hf_register_info hf[] = + { + { + &hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_dhcp, + { + "DHCP", "wmx.reg.alloc_sec_mgmt_dhcp", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x01, NULL, HFILL + } + }, + { + &hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_dhcpv6, + { + "DHCPv6", "wmx.reg.alloc_sec_mgmt_dhcpv6", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x04, NULL, HFILL + } + }, + { + &hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_ipv6, + { + "IPv6 Stateless Address Autoconfiguration", "wmx.reg.alloc_sec_mgmt_ipv6", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x08, NULL, HFILL + } + }, + { + &hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_mobile_ipv4, + { + "Mobile IPv4", "wmx.reg.alloc_sec_mgmt_mobile_ipv4", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x02, NULL, HFILL + } + }, + { + &hf_reg_method_for_allocating_ip_addr_sec_mgmt_conn_rsvd, + { + "Reserved", "wmx.reg.alloc_sec_mgmt_rsvd", + FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_reg_arq, + { + "ARQ support", "wmx.reg.arq", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_supported), 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_40_arq_ack_type_cumulative_ack_entry, + { + "Cumulative ACK entry", "wmx.reg.arq_ack_type_cumulative_ack_entry", + FT_UINT8, BASE_DEC, NULL, 0x2, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_40_arq_ack_type_cumulative_ack_with_block_sequence_ack, + { + "Cumulative ACK with Block Sequence ACK", "wmx.reg.arq_ack_type_cumulative_ack_with_block_sequence_ack", + FT_UINT8, BASE_DEC, NULL, 0x8, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_40_arq_ack_type_cumulative_with_selective_ack_entry, + { + "Cumulative with Selective ACK entry", "wmx.reg.arq_ack_type_cumulative_with_selective_ack_entry", + FT_UINT8, BASE_DEC, NULL, 0x4, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_40_arq_ack_type_reserved, + { + "Reserved", "wmx.reg.arq_ack_type_reserved", + FT_UINT8, BASE_DEC, NULL, 0xf0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_40_arq_ack_type_selective_ack_entry, + { + "Selective ACK entry", "wmx.reg.arq_ack_type_selective_ack_entry", + FT_UINT8, BASE_DEC, NULL, 0x1, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_bandwidth_request_cinr_report_header_support, + { + "Bandwidth request and CINR report header support", "wmx.reg.bandwidth_request_cinr_report_header_support", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x2, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_bandwidth_request_ul_sleep_control_header_support, + { + "Bandwidth request and uplink sleep control header support", "wmx.reg.bandwidth_request_ul_sleep_control_header_support", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x10, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_cqich_allocation_request_header_support, + { + "CQICH Allocation Request header support", "wmx.reg.cqich_allocation_request_header_support", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x4, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_dl_sleep_control_extended_subheader, + { + "Downlink sleep control extended subheader", "wmx.reg.dl_sleep_control_extended_subheader", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x800, NULL, HFILL + } + }, + { + &hf_reg_dsx_flow_control, + { + "DSx flow control", "wmx.reg.dsx_flow_control", + FT_UINT8, BASE_DEC|BASE_SPECIAL_VALS, VALS(unique_no_limit), 0x0, NULL, HFILL + } + }, + /* When REG-REQ TLV 7 is length 2 */ + { + &hf_reg_encap_802_1q_2, + { + "Packet, 802.1Q VLAN", "wmx.reg.encap_802_1q", + FT_UINT16, BASE_HEX, NULL, 0x0010, NULL, HFILL + } + }, + { + &hf_reg_encap_802_3_2, + { + "Packet, 802.3/Ethernet", "wmx.reg.encap_802_3", + FT_UINT16, BASE_HEX, NULL, 0x00000008, NULL, HFILL + } + }, + { + &hf_reg_encap_atm_2, + { + "ATM", "wmx.reg.encap_atm", + FT_UINT16, BASE_HEX, NULL, 0x00000001, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv4_2, + { + "Packet, IPv4", "wmx.reg.encap_ipv4", + FT_UINT16, BASE_HEX, NULL, 0x00000002, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv6_2, + { + "Packet, IPv6", "wmx.reg.encap_ipv6", + FT_UINT16, BASE_HEX, NULL, 0x00000004, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv4_802_1q_2, + { + "Packet, IPv4 over 802.1Q VLAN", "wmx.reg.encap_ipv4_802_1q", + FT_UINT16, BASE_HEX, NULL, 0x00000080, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv4_802_3_2, + { + "Packet, IPv4 over 802.3/Ethernet", "wmx.reg.encap_ipv4_802_3", + FT_UINT16, BASE_HEX, NULL, 0x00000020, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv6_802_1q_2, + { + "Packet, IPv6 over 802.1Q VLAN", "wmx.reg.encap_ipv6_802_1q", + FT_UINT16, BASE_HEX, NULL, 0x00000100, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv6_802_3_2, + { + "Packet, IPv6 over 802.3/Ethernet", "wmx.reg.encap_ipv6_802_3", + FT_UINT16, BASE_HEX, NULL, 0x00000040, NULL, HFILL + } + }, + { + &hf_reg_encap_packet_8023_ethernet_and_ecrtp_header_compression_2, + { + "Packet, 802.3/Ethernet (with optional 802.1Q VLAN tags) and ECRTP header compression", "wmx.reg.encap_packet_802_3_ethernet_and_ecrtp_header_compression", + FT_UINT16, BASE_HEX, NULL, 0x00000400, NULL, HFILL + } + }, + { + &hf_reg_encap_packet_8023_ethernet_and_rohc_header_compression_2, + { + "Packet, 802.3/Ethernet (with optional 802.1Q VLAN tags) and ROHC header compression", "wmx.reg.encap_packet_802_3_ethernet_and_rohc_header_compression", + FT_UINT16, BASE_HEX, NULL, 0x00000200, NULL, HFILL + } + }, + { + &hf_reg_encap_packet_ip_ecrtp_header_compression_2, + { + "Packet, IP (v4 or v6) with ECRTP header compression", "wmx.reg.encap_packet_ip_ecrtp_header_compression", + FT_UINT16, BASE_HEX, NULL, 0x00001000, NULL, HFILL + } + }, + { + &hf_reg_encap_packet_ip_rohc_header_compression_2, + { + "Packet, IP (v4 or v6) with ROHC header compression", "wmx.reg.encap_packet_ip_rohc_header_compression", + FT_UINT16, BASE_HEX, NULL, 0x00000800, NULL, HFILL + } + }, + { + &hf_reg_encap_rsvd_2, + { + "Reserved", "wmx.reg.encap_rsvd", + FT_UINT16, BASE_HEX, NULL, 0x0000E000, NULL, HFILL + } + }, + /* When REG-REQ TLV 7 is length 4 */ + { + &hf_reg_encap_802_1q_4, + { + "Packet, 802.1Q VLAN", "wmx.reg.encap_802_1q", + FT_UINT32, BASE_HEX, NULL, 0x0010, NULL, HFILL + } + }, + { + &hf_reg_encap_802_3_4, + { + "Packet, 802.3/Ethernet", "wmx.reg.encap_802_3", + FT_UINT32, BASE_HEX, NULL, 0x00000008, NULL, HFILL + } + }, + { + &hf_reg_encap_atm_4, + { + "ATM", "wmx.reg.encap_atm", + FT_UINT32, BASE_HEX, NULL, 0x00000001, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv4_4, + { + "Packet, IPv4", "wmx.reg.encap_ipv4", + FT_UINT32, BASE_HEX, NULL, 0x00000002, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv4_802_1q_4, + { + "Packet, IPv4 over 802.1Q VLAN", "wmx.reg.encap_ipv4_802_1q", + FT_UINT32, BASE_HEX, NULL, 0x00000080, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv4_802_3_4, + { + "Packet, IPv4 over 802.3/Ethernet", "wmx.reg.encap_ipv4_802_3", + FT_UINT32, BASE_HEX, NULL, 0x00000020, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv6_4, + { + "Packet, IPv6", "wmx.reg.encap_ipv6", + FT_UINT32, BASE_HEX, NULL, 0x00000004, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv6_802_1q_4, + { + "Packet, IPv6 over 802.1Q VLAN", "wmx.reg.encap_ipv6_802_1q", + FT_UINT32, BASE_HEX, NULL, 0x00000100, NULL, HFILL + } + }, + { + &hf_reg_encap_ipv6_802_3_4, + { + "Packet, IPv6 over 802.3/Ethernet", "wmx.reg.encap_ipv6_802_3", + FT_UINT32, BASE_HEX, NULL, 0x00000040, NULL, HFILL + } + }, + { + &hf_reg_encap_packet_8023_ethernet_and_ecrtp_header_compression_4, + { + "Packet, 802.3/Ethernet (with optional 802.1Q VLAN tags) and ECRTP header compression", "wmx.reg.encap_packet_802_3_ethernet_and_ecrtp_header_compression", + FT_UINT32, BASE_HEX, NULL, 0x00000400, NULL, HFILL + } + }, + { + &hf_reg_encap_packet_8023_ethernet_and_rohc_header_compression_4, + { + "Packet, 802.3/Ethernet (with optional 802.1Q VLAN tags) and ROHC header compression", "wmx.reg.encap_packet_802_3_ethernet_and_rohc_header_compression", + FT_UINT32, BASE_HEX, NULL, 0x00000200, NULL, HFILL + } + }, + { + &hf_reg_encap_packet_ip_ecrtp_header_compression_4, + { + "Packet, IP (v4 or v6) with ECRTP header compression", "wmx.reg.encap_packet_ip_ecrtp_header_compression", + FT_UINT32, BASE_HEX, NULL, 0x00001000, NULL, HFILL + } + }, + { + &hf_reg_encap_packet_ip_rohc_header_compression_4, + { + "Packet, IP (v4 or v6) with ROHC header compression", "wmx.reg.encap_packet_ip_rohc_header_compression", + FT_UINT32, BASE_HEX, NULL, 0x00000800, NULL, HFILL + } + }, + { + &hf_reg_encap_rsvd_4, + { + "Reserved", "wmx.reg.encap_rsvd", + FT_UINT32, BASE_HEX, NULL, 0xFFFFE000, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_22_mac_extended_rtps_support, + { + "MAC extended rtPS support", "wmx.reg.ext_rtps_support", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x01, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_27_handover_fbss_mdho_dl_rf_monitoring_maps, + { + "FBSS/MDHO DL RF Combining with monitoring MAPs from active BSs", "wmx.reg.fbss_mdho_dl_rf_combining", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x02, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_bandwidth_request_ul_tx_power_report_header_support, + { + "Bandwidth request and UL Tx Power Report header support", + "wmx.reg.bandwidth_request_ul_tx_pwr_report_header_support", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x1, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_27_handover_fbss_mdho_ho_disable, + { + "MDHO/FBSS HO. BS ignore all other bits when set to 1", "wmx.reg.fbss_mdho_ho_disable", + FT_BOOLEAN, 8, TFS(&tfs_reg_fbss_mdho_ho_disable), 0x01, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_feedback_header_support, + { + "Feedback header support", "wmx.reg.feedback_header_support", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x40, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_feedback_request_extended_subheader, + { + "Feedback request extended subheader", "wmx.reg.feedback_request_extended_subheader", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x1000, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_46_handover_indication_readiness_timer, + { + "Handover indication readiness timer", "wmx.reg.handover_indication_readiness_timer", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_27_handover_reserved, + { + "Reserved", "wmx.reg.handover_reserved", + FT_UINT8, BASE_DEC, NULL, 0xE0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_41_ho_connections_param_processing_time, + { + "MS HO connections parameters processing time", "wmx.reg.ho_connections_param_processing_time", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_29_ho_process_opt_ms_timer, + { + "HO Process Optimization MS Timer", "wmx.reg.ho_process_opt_ms_timer", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_42_ho_tek_processing_time, + { + "MS HO TEK processing time", "wmx.reg.ho_tek_processing_time", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_idle_mode_timeout, + { + "Idle Mode Timeout", "wmx.reg.idle_mode_timeout", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_ip_mgmt_mode, + { + "IP management mode", "wmx.reg.ip_mgmt_mode", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_reg_ip_mgmt_mode), 0x0, NULL, HFILL + } + }, + { + &hf_reg_ip_version, + { + "IP version", "wmx.reg.ip_version", + FT_UINT8, BASE_HEX, VALS(vals_reg_ip_version), 0x0, NULL, HFILL + } + }, + { + &hf_reg_mac_address, + { + "MAC Address of the SS", "wmx.reg.mac_address", + FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_mac_crc_support, + { + "MAC CRC", "wmx.reg.mac_crc_support", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_mac_crc_support), 0x0, NULL, HFILL + } + }, + { + &hf_reg_max_classifiers, + { + "Maximum number of classification rules", "wmx.reg.max_classifiers", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_23_max_num_bursts_concurrently_to_the_ms, + { + "Maximum number of bursts transmitted concurrently to the MS", "wmx.reg.max_num_bursts_to_ms", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_mca_flow_control, + { + "MCA flow control", "wmx.reg.mca_flow_control", + FT_UINT8, BASE_DEC|BASE_SPECIAL_VALS, VALS(unique_no_limit), 0x0, NULL, HFILL + } + }, + { + &hf_reg_mcast_polling_cids, + { + "Multicast polling group CID support", "wmx.reg.mcast_polling_cids", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_27_handover_mdho_ul_multiple, + { + "MDHO UL Multiple transmission", "wmx.reg.mdh_ul_multiple", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_27_handover_mdho_dl_monitoring_maps, + { + "MDHO DL soft combining with monitoring MAPs from active BSs", "wmx.reg.mdho_dl_monitor_maps", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x08, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_27_handover_mdho_dl_monitoring_single_map, + { + "MDHO DL soft Combining with monitoring single MAP from anchor BS", "wmx.reg.mdho_dl_monitor_single_map", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x04, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_mimo_mode_feedback_extended_subheader, + { + "MIMO mode feedback request extended subheader", "wmx.reg.mimo_mode_feedback_request_extended_subheader", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x2000, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_mini_feedback_extended_subheader, + { + "Mini-feedback extended subheader", "wmx.reg.mini_feedback_extended_subheader", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x8000, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_31_mobility_handover, + { + "Mobility (handover)", "wmx.reg.mobility_handover", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x01, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_31_mobility_idle_mode, + { + "Idle mode", "wmx.reg.mobility_idle_mode", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x04, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_31_mobility_sleep_mode, + { + "Sleep mode", "wmx.reg.mobility_sleep_mode", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x02, NULL, HFILL + } + }, + { + &hf_reg_num_dl_trans_cid, + { + "Number of Downlink transport CIDs the SS can support", "wmx.reg.dl_cids_supported", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_21_packing_support, + { + "Packing support", "wmx.reg.packing.support", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x01, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_pdu_sn_long_extended_subheader, + { + "PDU SN (long) extended subheader", "wmx.reg.pdu_sn_long_extended_subheader", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x40000, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_pdu_sn_short_extended_subheader, + { + "PDU SN (short) extended subheader", "wmx.reg.pdu_sn_short_extended_subheader", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x20000, NULL, HFILL + } + }, + { + &hf_reg_phs, + { + "PHS support", "wmx.reg.phs", + FT_UINT8, BASE_DEC, VALS(vals_reg_phs_support), 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_phy_channel_report_header_support, + { + "PHY channel report header support", "wmx.reg.phy_channel_report_header_support", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x8, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_reserved, + { + "Reserved", "wmx.reg.reserved", + FT_UINT24, BASE_DEC, NULL, 0xf80000, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_sdu_sn_extended_subheader_support_and_parameter, + { + "SDU_SN extended subheader support", "wmx.reg.sdu_sn_extended_subheader_support", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x80, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_sdu_sn_parameter, + { + "SDU_SN parameter", "wmx.reg.sdu_sn_parameter", + FT_UINT24, BASE_DEC, NULL, 0x700, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_sn_report_header_support, + { + "SN report header support", "wmx.reg.sn_report_header_support", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x20, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_sn_request_extended_subheader, + { + "SN request extended subheader", "wmx.reg.sn_request_extended_subheader", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x10000, NULL, HFILL + } + }, + { + &hf_reg_ss_mgmt_support, + { + "SS management support", "wmx.reg.ss_mgmt_support", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_reg_ss_mgmt_support), 0x0, NULL, HFILL + } + }, + { + &hf_reg_ul_cids, + { + "Number of Uplink transport CIDs the SS can support", "wmx.reg.ul_cids_supported", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_ul_tx_power_report_extended_subheader, + { + "UL Tx power report extended subheader", "wmx.reg.ul_tx_power_report_extended_subheader", + FT_UINT24, BASE_DEC, VALS(tfs_support), 0x4000, NULL, HFILL + } + }, + { + &hf_tlv_type, + { + "Unknown TLV Type", "wmx.reg.unknown_tlv_type", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_reg_invalid_tlv, + { + "Invalid TLV", "wmx.reg_req.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_20_1_max_mac_level_data_per_dl_frame, + { + "Maximum MAC level DL data per frame", "wmx.reg_req.max_mac_dl_data", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_20_2_max_mac_level_data_per_ul_frame, + { + "Maximum MAC level UL data per frame", "wmx.reg_req.max_mac_ul_data", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_req_min_time_for_inter_fa, + { + "Minimum time for inter-FA HO, default=3", "wmx.reg_req.min_time_for_inter_fa", + FT_UINT8, BASE_HEX, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_reg_req_min_time_for_intra_fa, + { + "Minimum time for intra-FA HO, default=2", "wmx.reg_req.min_time_for_intra_fa", + FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL + } + }, + { + &hf_reg_req_tlv_t_45_ms_periodic_ranging_timer, + { + "MS periodic ranging timer information", "wmx.reg_req.ms_periodic_ranging_timer_info", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { /* IPv4 Mask */ + &hf_ms_previous_ip_address_v4, + { + "MS Previous IP address", "wmx.reg_req.ms_prev_ip_addr_v4", + FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* IPv6 Source Address */ + &hf_ms_previous_ip_address_v6, + { + "MS Previous IP address", "wmx.reg_req.ms_prev_ip_addr_v6", + FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_req_secondary_mgmt_cid, + { + "Secondary Management CID", "wmx.reg_req.secondary_mgmt_cid", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_req_tlv_t_32_sleep_mode_recovery_time, + { + "Frames required for the MS to switch from sleep to awake-mode", "wmx.reg_req.sleep_recovery", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_power_saving_class_type_i, + { + "Power saving class type I supported", "wmx.reg.power_saving_class_type_i", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x01, NULL, HFILL + } + }, + { + &hf_reg_power_saving_class_type_ii, + { + "Power saving class type II supported", "wmx.reg.power_saving_class_type_ii", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x02, NULL, HFILL + } + }, + { + &hf_reg_power_saving_class_type_iii, + { + "Power saving class type III supported", "wmx.reg.power_saving_class_type_iii", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x04, NULL, HFILL + } + }, + { + &hf_reg_multi_active_power_saving_classes, + { + "Multiple active power saving classes supported", "wmx.reg.multi_active_power_saving_classes", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x08, NULL, HFILL + } + }, + { + &hf_reg_total_power_saving_class_instances, + { + "Total number of power saving class instances of all", "wmx.reg_req.total_power_saving_class_instances", + FT_UINT16, BASE_DEC, NULL, 0x1F0, NULL, HFILL + } + }, + { + &hf_reg_power_saving_class_reserved, + { + "Reserved", "wmx.reg.reserved", + FT_UINT16, BASE_DEC, NULL, 0xFE00, NULL, HFILL + } + }, + { + &hf_reg_power_saving_class_capability, + { + "Power saving class capability", "wmx.reg.power_saving_class_capability", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_ip_phs_sdu_encap, + { + "Classification/PHS options and SDU encapsulation support", "wmx.reg.ip_phs_sdu_encap", + FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_26_method_alloc_ip_addr_secondary_mgmnt_conn, + { + "Method for allocating IP address for the secondary management connection", "wmx.reg.method_alloc_ip_addr_secondary_mgmnt_conn", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_27_handover_supported, + { + "Handover Support", "wmx.reg.handover_supported", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_31_mobility_features_supported, + { + "Mobility Features Supported", "wmx.reg.mobility_features_supported", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_40_arq_ack_type, + { + "ARQ ACK Type", "wmx.reg.arq_ack_type", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_tlv_t_43_mac_header_ext_header_support, + { + "MAC header and extended subheader support", "wmx.reg.mac_header_ext_header_support", + FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_req_bs_switching_timer, + { + "BS switching timer", "wmx.reg.bs_switching_timer", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_reg_req_decoder + }; + + + proto_mac_mgmt_msg_reg_req_decoder = proto_register_protocol ( + "WiMax REG-REQ Messages", /* name */ + "WiMax REG-REQ", /* short name */ + "wmx.reg_req" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_reg_req_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + reg_req_handle = register_dissector("mac_mgmt_msg_reg_req_handler", dissect_mac_mgmt_msg_reg_req_decoder, proto_mac_mgmt_msg_reg_req_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_reg_req(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_REG_REQ, reg_req_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: + */ diff --git a/plugins/epan/wimax/msg_reg_rsp.c b/plugins/epan/wimax/msg_reg_rsp.c new file mode 100644 index 00000000..a5f23650 --- /dev/null +++ b/plugins/epan/wimax/msg_reg_rsp.c @@ -0,0 +1,365 @@ +/* msg_reg_rsp.c + * WiMax MAC Management REG-RSP Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#define WIMAX_16E_2005 + +#define FRAG_LAST 0x1 + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_reg_rsp(void); +void proto_reg_handoff_mac_mgmt_msg_reg_rsp(void); + +static dissector_handle_t reg_rsp_handle; + +extern gboolean include_cor2_changes; + +static dissector_handle_t dsc_rsp_handle = NULL; + +static gint proto_mac_mgmt_msg_reg_rsp_decoder = -1; +static gint ett_mac_mgmt_msg_reg_rsp_decoder = -1; +static gint ett_reg_rsp_message_tree = -1; + +/* NCT messages */ + +/* REG-RSP fields */ +static gint hf_reg_rsp_status = -1; +static gint hf_tlv_type = -1; +/* static gint hf_tlv_value = -1; */ +static gint hf_reg_rsp_secondary_mgmt_cid = -1; +static gint hf_reg_invalid_tlv = -1; +static gint hf_reg_rsp_new_cid_after_ho = -1; +static gint hf_reg_rsp_service_flow_id = -1; +static gint hf_reg_rsp_system_resource_retain_time = -1; +static gint hf_reg_total_provisioned_sf = -1; + +/* STRING RESOURCES */ + +static const value_string vals_reg_rsp_status [] = { + {0, "OK"}, + {1, "Message authentication failure"}, + {0, NULL} +}; + + + +/* Decode REG-RSP messages. */ +static int dissect_mac_mgmt_msg_reg_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tlv_offset; + guint tvb_len; + proto_item *reg_rsp_item; + proto_tree *reg_rsp_tree; + proto_item *tlv_item = NULL; + proto_tree *tlv_tree = NULL; + proto_tree *sub_tree = NULL; + gboolean hmac_found = FALSE; + tlv_info_t tlv_info; + gint tlv_type; + guint tlv_len; + guint this_offset = 0; + tlv_info_t sub_tlv_info; + gint sub_tlv_type; + gint sub_tlv_len; + guint sub_tlv_offset; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type REG-RSP */ + reg_rsp_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tvb_len, "MAC Management Message, REG-RSP"); + /* add MAC REG-RSP subtree */ + reg_rsp_tree = proto_item_add_subtree(reg_rsp_item, ett_mac_mgmt_msg_reg_rsp_decoder); + proto_tree_add_item(reg_rsp_tree, hf_reg_rsp_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + while (offset < tvb_len) + { + /* Get the TLV data. */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if (tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REG-RSP TLV error"); + proto_tree_add_item(reg_rsp_tree, hf_reg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the offset to the TLV data */ + tlv_offset = offset + get_tlv_value_offset(&tlv_info); + + switch (tlv_type) { + case REG_ARQ_PARAMETERS: + case REG_SS_MGMT_SUPPORT: + case REG_IP_MGMT_MODE: + case REG_IP_VERSION: + case REG_UL_TRANSPORT_CIDS_SUPPORTED: + case REG_IP_PHS_SDU_ENCAP: + case REG_MAX_CLASSIFIERS_SUPPORTED: + case REG_PHS_SUPPORT: + case REG_ARQ_SUPPORT: + case REG_DSX_FLOW_CONTROL: + case REG_MCA_FLOW_CONTROL: + case REG_MCAST_POLLING_CIDS: + case REG_NUM_DL_TRANS_CID: + case REG_MAC_ADDRESS: +#ifdef WIMAX_16E_2005 + case REG_TLV_T_20_MAX_MAC_DATA_PER_FRAME_SUPPORT: + case REG_TLV_T_21_PACKING_SUPPORT: + case REG_TLV_T_22_MAC_EXTENDED_RTPS_SUPPORT: + case REG_TLV_T_23_MAX_NUM_BURSTS_TRANSMITTED_CONCURRENTLY_TO_THE_MS: + case REG_TLV_T_26_METHOD_FOR_ALLOCATING_IP_ADDR_SECONDARY_MGMNT_CONNECTION: + case REG_TLV_T_27_HANDOVER_SUPPORTED: + case REG_TLV_T_29_HO_PROCESS_OPTIMIZATION_MS_TIMER: + case REG_TLV_T_31_MOBILITY_FEATURES_SUPPORTED: + case REG_TLV_T_40_ARQ_ACK_TYPE: + case REG_TLV_T_41_MS_HO_CONNECTIONS_PARAM_PROCESSING_TIME: + case REG_TLV_T_42_MS_HO_TEK_PROCESSING_TIME: + case REG_TLV_T_43_MAC_HEADER_AND_EXTENDED_SUBHEADER_SUPPORT: + case REG_POWER_SAVING_CLASS_CAPABILITY: +#endif + dissect_extended_tlv(reg_rsp_tree, tlv_type, tvb, tlv_offset, tlv_len, pinfo, offset, proto_mac_mgmt_msg_reg_rsp_decoder); + break; + case REG_RSP_SECONDARY_MGMT_CID: + add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_rsp_secondary_mgmt_cid, tvb, offset, ENC_BIG_ENDIAN); + break; + + case REG_RSP_TLV_T_36_TOTAL_PROVISIONED_SERVICE_FLOW_DSAs: + add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_total_provisioned_sf, tvb, offset, ENC_BIG_ENDIAN); + break; + + case REG_RSP_TLV_T_24_CID_UPDATE_ENCODINGS: + /* Display CID update encodings */ + /* add subtree */ + sub_tree = add_protocol_subtree(&tlv_info, ett_reg_rsp_message_tree, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "CID update encodings"); + /* Use a local copy of tlv_offset */ + this_offset = tlv_offset; + while(this_offset < tlv_len) { + /* Get the sub TLV data. */ + init_tlv_info(&sub_tlv_info, tvb, this_offset); + /* get the sub TLV type */ + sub_tlv_type = get_tlv_type(&sub_tlv_info); + /* get the TLV length */ + sub_tlv_len = get_tlv_length(&sub_tlv_info); + if (sub_tlv_type == -1 || sub_tlv_len > MAX_TLV_LEN || sub_tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REG-RSP TLV error"); + proto_tree_add_item(reg_rsp_tree, hf_reg_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the offset to the sub TLV data */ + sub_tlv_offset = this_offset + get_tlv_value_offset(&sub_tlv_info); + switch (sub_tlv_type) { + case REG_RSP_TLV_T_24_1_CID_UPDATE_ENCODINGS_NEW_CID: + add_tlv_subtree(&sub_tlv_info, sub_tree, hf_reg_rsp_new_cid_after_ho, tvb, this_offset, ENC_BIG_ENDIAN); + break; + case REG_RSP_TLV_T_24_2_CID_UPDATE_ENCODINGS_SFID: + add_tlv_subtree(&sub_tlv_info, sub_tree, hf_reg_rsp_service_flow_id, tvb, this_offset, ENC_BIG_ENDIAN); + break; + case REG_RSP_TLV_T_24_3_CID_UPDATE_ENCODINGS_CONNECTION_INFO: + tlv_tree = add_protocol_subtree(&sub_tlv_info, ett_reg_rsp_message_tree, sub_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, this_offset, sub_tlv_len, "CID Update Encodings Connection Info"); + /* Decode the DSC_RSP subTLV's */ + call_dissector(dsc_rsp_handle, tvb_new_subset_length(tvb, sub_tlv_offset, sub_tlv_len), pinfo, tlv_tree); + break; + default: + add_tlv_subtree(&sub_tlv_info, sub_tree, hf_tlv_type, tvb, this_offset, ENC_NA); + break; + } + this_offset = sub_tlv_len + sub_tlv_offset; + } + break; + case REG_RSP_TLV_T_28_HO_SYSTEM_RESOURCE_RETAIN_TIME: + tlv_item = add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_reg_rsp_system_resource_retain_time, tvb, offset, ENC_BIG_ENDIAN); + if (include_cor2_changes) { + proto_item_append_text(tlv_item, " (in units of 100 milliseconds)"); + } else { + proto_item_append_text(tlv_item, " (multiple of 100 milliseconds)"); + } + break; + case DSx_UPLINK_FLOW: + /* display Uplink Service Flow Encodings info */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Uplink Service Flow Encodings"); + /* decode and display the DL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree); + break; + case DSx_DOWNLINK_FLOW: + /* display Downlink Service Flow Encodings info */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Downlink Service Flow Encodings"); + /* decode and display the DL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, tlv_tree); + break; + case HMAC_TUPLE: /* Table 348d */ + /* decode and display the HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "HMAC Tuple"); + wimax_hmac_tuple_decoder(tlv_tree, tvb, offset+2, tlv_len); + hmac_found = TRUE; + break; + case CMAC_TUPLE: /* Table 348b */ + /* decode and display the CMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "CMAC Tuple"); + wimax_cmac_tuple_decoder(tlv_tree, tvb, offset+2, tlv_len); + break; + case SHORT_HMAC_TUPLE: + case SHORT_HMAC_TUPLE_COR2: + if ((!include_cor2_changes && (tlv_type == SHORT_HMAC_TUPLE)) || + (include_cor2_changes && (tlv_type == SHORT_HMAC_TUPLE_COR2))) { + /* decode and display the Short HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_reg_rsp_decoder, reg_rsp_tree, proto_mac_mgmt_msg_reg_rsp_decoder, tvb, offset, tlv_len, "Short HMAC Tuple"); + wimax_short_hmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tlv_len); + } else { + /* Unknown TLV Type */ + add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_tlv_type, tvb, offset, ENC_NA); + } + break; + case VENDOR_SPECIFIC_INFO: + case VENDOR_ID_ENCODING: + case MAC_VERSION_ENCODING: + wimax_common_tlv_encoding_decoder(tvb_new_subset_length(tvb, offset, (tvb_len - offset)), pinfo, reg_rsp_tree); + break; + default: + add_tlv_subtree(&tlv_info, reg_rsp_tree, hf_tlv_type, tvb, offset, ENC_NA); + break; + } + + offset = tlv_len + tlv_offset; + } /* end of TLV process while loop */ + if (!hmac_found) + proto_item_append_text(reg_rsp_tree, " (HMAC Tuple is missing !)"); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_reg_rsp(void) +{ + /* REG-RSP fields display */ + static hf_register_info hf[] = + { + { + &hf_reg_invalid_tlv, + { + "Invalid TLV", "wmx.reg_rsp.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_reg_rsp_new_cid_after_ho, + { + "New CID after handover to new BS", "wmx.reg_rsp.new_cid_after_ho", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_rsp_status, + { + "Response", "wmx.reg_rsp.response", + FT_UINT8, BASE_HEX, VALS(vals_reg_rsp_status), 0x0, NULL, HFILL + } + }, + { + &hf_reg_rsp_secondary_mgmt_cid, + { + "Secondary Management CID", "wmx.reg_rsp.secondary_mgmt_cid", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_total_provisioned_sf, + { + "Total Number of Provisional Service Flow", "wmx.reg_rsp.total_provisional_sf", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_rsp_service_flow_id, + { + "Service flow ID", "wmx.reg_rsp.service_flow_id", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_reg_rsp_system_resource_retain_time, + { + "System Resource Retain Time", "wmx.reg_rsp.system_resource_retain_time", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_tlv_type, + { + "Unknown TLV Type", "wmx.reg_rsp.unknown_tlv_type", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, +#if 0 + { + &hf_tlv_value, + { + "Value", "wmx.reg_rsp.tlv_value", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + } +#endif + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_reg_rsp_decoder, + &ett_reg_rsp_message_tree + }; + + proto_mac_mgmt_msg_reg_rsp_decoder = proto_register_protocol ( + "WiMax REG-RSP Messages", /* name */ + "WiMax REG-RSP", /* short name */ + "wmx.reg_rsp" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_reg_rsp_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + reg_rsp_handle = register_dissector("mac_mgmt_msg_reg_rsp_handler", dissect_mac_mgmt_msg_reg_rsp_decoder, proto_mac_mgmt_msg_reg_rsp_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_reg_rsp(void) +{ + dsc_rsp_handle = find_dissector("mac_mgmt_msg_dsc_rsp_handler"); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_REG_RSP, reg_rsp_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: + */ diff --git a/plugins/epan/wimax/msg_rep.c b/plugins/epan/wimax/msg_rep.c new file mode 100644 index 00000000..952e8f5f --- /dev/null +++ b/plugins/epan/wimax/msg_rep.c @@ -0,0 +1,1564 @@ +/* msg_rep.c + * WiMax MAC Management REP-REQ/RSP Messages decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#if 0 +#define DEBUG /* for debug only*/ +#endif + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_rep(void); +void proto_reg_handoff_mac_mgmt_msg_rep(void); + +static dissector_handle_t rep_req_handle; +static dissector_handle_t rep_rsp_handle; + +static gint proto_mac_mgmt_msg_rep_decoder = -1; +static gint ett_mac_mgmt_msg_rep_req_decoder = -1; +static gint ett_mac_mgmt_msg_rep_rsp_decoder = -1; + +static const value_string vals_channel_types[] = +{ + { 0, "Normal Subchannel"}, + { 1, "Band AMC Channel"}, + { 2, "Safety Channel"}, + { 3, "Sounding"}, + { 0, NULL} +}; + +static const value_string vals_type_of_zones[] = +{ + { 0, "PUSC Zone with 'use all SC=0'"}, + { 1, "PUSC Zone with 'use all SC=1'/PUSC AAS Zone"}, + { 2, "FUSC Zone"}, + { 3, "Optional FUSC Zone"}, + { 4, "Safety Channel Region"}, + { 5, "AMC Zone (only applicable to AAS zone)"}, + { 6, "Reserved"}, + { 7, "Reserved"}, + { 0, NULL} +}; + +static const value_string vals_data_cinr_measurements[] = +{ + { 0, "From Pilot Subcarriers"}, + { 1, "From Data Subcarriers"}, + { 0, NULL} +}; + +static const value_string vals_cinr_report_types[] = +{ + { 0, "Mean Of CINR Only"}, + { 1, "Both Mean And Standard Deviation Of CINR"}, + { 0, NULL} +}; + +static const value_string vals_type_of_measurements[] = +{ + { 0, "From Preamble For Frequency Reuse Configuration 1"}, + { 1, "From Preamble For Frequency Reuse Configuration 3"}, + { 2, "From Preamble For Band AMC"}, + { 3, "Reserved"}, + { 0, NULL} +}; + +/* fix fields */ +static gint hf_rep_unknown_type = -1; +static gint hf_rep_invalid_tlv = -1; + +static gint hf_rep_req_report_request = -1; +static gint hf_rep_req_report_type = -1; +static gint hf_rep_req_rep_type_bit0 = -1; +static gint hf_rep_req_rep_type_bit1 = -1; +static gint hf_rep_req_rep_type_bit2 = -1; +static gint hf_rep_req_rep_type_bit3_6 = -1; +static gint hf_rep_req_rep_type_bit7 = -1; +static gint hf_rep_req_channel_number = -1; +static gint hf_rep_req_channel_type = -1; +static gint hf_rep_req_channel_type_request = -1; +static gint hf_rep_req_channel_type_reserved = -1; +static gint hf_rep_req_zone_spec_phy_cinr_request = -1; +static gint hf_rep_req_preamble_phy_cinr_request = -1; +static gint hf_rep_req_zone_spec_effective_cinr_request = -1; +static gint hf_rep_req_preamble_effective_cinr_request = -1; +static gint hf_rep_req_channel_selectivity_report = -1; + +static gint hf_rep_req_zone_spec_phy_cinr_req_bit0_2 = -1; +static gint hf_rep_req_zone_spec_phy_cinr_req_bit3 = -1; +static gint hf_rep_req_zone_spec_phy_cinr_req_bit4 = -1; +static gint hf_rep_req_zone_spec_phy_cinr_req_bit5_6 = -1; +static gint hf_rep_req_zone_spec_phy_cinr_req_bit7 = -1; +static gint hf_rep_req_zone_spec_phy_cinr_req_bit8_13 = -1; +static gint hf_rep_req_zone_spec_phy_cinr_req_bit14_17 = -1; +static gint hf_rep_req_zone_spec_phy_cinr_req_bit18 = -1; +static gint hf_rep_req_zone_spec_phy_cinr_req_bit19_23 = -1; + +static gint hf_rep_req_zone_spec_effective_cinr_req_bit0_2 = -1; +static gint hf_rep_req_zone_spec_effective_cinr_req_bit3 = -1; +static gint hf_rep_req_zone_spec_effective_cinr_req_bit4 = -1; +static gint hf_rep_req_zone_spec_effective_cinr_req_bit5_6 = -1; +static gint hf_rep_req_zone_spec_effective_cinr_req_bit7 = -1; +static gint hf_rep_req_zone_spec_effective_cinr_req_bit8_13 = -1; +static gint hf_rep_req_zone_spec_effective_cinr_req_bit14_15 = -1; + +static gint hf_rep_req_preamble_phy_cinr_req_bit0_1 = -1; +static gint hf_rep_req_preamble_phy_cinr_req_bit2_5 = -1; +static gint hf_rep_req_preamble_phy_cinr_req_bit6 = -1; +static gint hf_rep_req_preamble_phy_cinr_req_bit7 = -1; + +static gint hf_rep_req_preamble_effective_cinr_req_bit0_1 = -1; +static gint hf_rep_req_preamble_effective_cinr_req_bit2_7 = -1; + +static gint hf_rep_req_channel_selectivity_rep_bit0 = -1; +static gint hf_rep_req_channel_selectivity_rep_bit1_7 = -1; + +static gint hf_rep_rsp_report_type = -1; +static gint hf_rep_rsp_report_type_channel_number = -1; +static gint hf_rep_rsp_report_type_frame_number = -1; +static gint hf_rep_rsp_report_type_duration = -1; +static gint hf_rep_rsp_report_type_basic_report = -1; +static gint hf_rep_rsp_report_type_basic_report_bit0 = -1; +static gint hf_rep_rsp_report_type_basic_report_bit1 = -1; +static gint hf_rep_rsp_report_type_basic_report_bit2 = -1; +static gint hf_rep_rsp_report_type_basic_report_bit3 = -1; +static gint hf_rep_rsp_report_type_basic_report_reserved = -1; +static gint hf_rep_rsp_report_type_cinr_report = -1; +static gint hf_rep_rsp_report_type_cinr_report_mean = -1; +static gint hf_rep_rsp_report_type_cinr_report_deviation = -1; +static gint hf_rep_rsp_report_type_rssi_report = -1; +static gint hf_rep_rsp_report_type_rssi_report_mean = -1; +static gint hf_rep_rsp_report_type_rssi_report_deviation = -1; +static gint hf_rep_rsp_current_transmitted_power = -1; +static gint hf_rep_rsp_channel_type_report = -1; +static gint hf_rep_rsp_channel_type_subchannel = -1; +static gint hf_rep_rsp_channel_type_band_amc = -1; +static gint hf_rep_rsp_channel_type_safety_channel = -1; +static gint hf_rep_rsp_channel_type_enhanced_band_amc = -1; +static gint hf_rep_rsp_channel_type_sounding = -1; + +static gint hf_rep_rsp_zone_spec_phy_cinr_report = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_mean = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_report_type = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_reserved1 = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_deviation = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_reserved2 = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_pusc_sc0 = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_pusc_sc1 = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_fusc = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_optional_fusc = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_safety_channel = -1; +static gint hf_rep_rsp_zone_spec_phy_cinr_rep_amc = -1; +static gint hf_rep_rsp_preamble_phy_cinr_report = -1; +static gint hf_rep_rsp_preamble_phy_cinr_rep_configuration_1 = -1; +static gint hf_rep_rsp_preamble_phy_cinr_rep_configuration_3 = -1; +static gint hf_rep_rsp_preamble_phy_cinr_rep_band_amc_zone = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_report = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_rep_report_type = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_rep_cqich_id = -1; +static gint hf_rep_rsp_preamble_effective_cinr_report = -1; +static gint hf_rep_rsp_preamble_effective_cinr_rep_cqich_id = -1; +static gint hf_rep_rsp_channel_selectivity_report = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_rep_pusc_sc0 = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_rep_pusc_sc1 = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_rep_fusc = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_rep_optional_fusc = -1; +static gint hf_rep_rsp_zone_spec_effective_cinr_rep_amc_aas = -1; +static gint hf_rep_rsp_preamble_effective_cinr_rep_configuration_1 = -1; +static gint hf_rep_rsp_preamble_effective_cinr_rep_configuration_3 = -1; +static gint hf_rep_rsp_channel_selectivity_rep_frequency_a = -1; +static gint hf_rep_rsp_channel_selectivity_rep_frequency_b = -1; +static gint hf_rep_rsp_channel_selectivity_rep_frequency_c = -1; + +/* bit masks */ +#define REP_REQ_REPORT_TYPE_BIT0 0x01 +#define REP_REQ_REPORT_TYPE_BIT1 0x02 +#define REP_REQ_REPORT_TYPE_BIT2 0x04 +#define REP_REQ_REPORT_TYPE_BIT3_6 0x78 +#define REP_REQ_REPORT_TYPE_BIT7 0x80 + +#define REP_REQ_CHANNEL_TYPE_REQUEST 0x03 +#define REP_REQ_CHANNEL_TYPE_RESERVED 0xFC + +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT0_2 0x000007 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT3 0x000008 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT4 0x000010 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT5_6 0x000060 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT7 0x000080 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT8_13 0x003F00 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT14_17 0x03C000 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT18 0x040000 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_BIT19_23 0xF80000 + +#define REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT0_2 0x0007 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT3 0x0008 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT4 0x0010 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT5_6 0x0060 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT7 0x0080 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT8_13 0x3F00 +#define REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT14_15 0xC000 + +#define REP_REQ_PREAMBLE_PHY_CINR_REQUEST_BIT0_1 0x03 +#define REP_REQ_PREAMBLE_PHY_CINR_REQUEST_BIT2_5 0x3C +#define REP_REQ_PREAMBLE_PHY_CINR_REQUEST_BIT6 0x40 +#define REP_REQ_PREAMBLE_PHY_CINR_REQUEST_BIT7 0x80 + +#define REP_REQ_PREAMBLE_EFFECTIVE_CINR_REQUEST_BIT0_1 0x03 +#define REP_REQ_PREAMBLE_EFFECTIVE_CINR_REQUEST_BIT2_7 0xFC + +#define REP_REQ_CHANNEL_SELECTIVITY_REPORT_BIT0 0x01 +#define REP_REQ_CHANNEL_SELECTIVITY_REPORT_BIT1_7 0xFE + +#define REP_RSP_REPORT_TYPE_BASIC_REPORT_BIT0 0x01 +#define REP_RSP_REPORT_TYPE_BASIC_REPORT_BIT1 0x02 +#define REP_RSP_REPORT_TYPE_BASIC_REPORT_BIT2 0x04 +#define REP_RSP_REPORT_TYPE_BASIC_REPORT_BIT3 0x08 +#define REP_RSP_REPORT_TYPE_BASIC_REPORT_RSV 0xF0 + +#define REP_RSP_ZONE_SPEC_PHY_CINR_MEAN_MASK 0x1F +#define REP_RSP_ZONE_SPEC_PHY_CINR_REP_TYPE_MASK 0x20 +#define REP_RSP_ZONE_SPEC_PHY_CINR_RSV1_MASK 0xC0 +#define REP_RSP_ZONE_SPEC_PHY_CINR_DEVIATION_MASK 0x1F +#define REP_RSP_ZONE_SPEC_PHY_CINR_RSV2_MASK 0xE0 + +#define REP_RSP_ZONE_SPEC_EFFECTIVE_CINR_EFFECTIVE_CINR_MASK 0x0F +#define REP_RSP_ZONE_SPEC_EFFECTIVE_CINR_REPORT_TYPE_MASK 0x10 +#define REP_RSP_ZONE_SPEC_EFFECTIVE_CINR_CQICH_ID_MASK 0xE0 +#define REP_RSP_ZONE_SPEC_EFFECTIVE_CINR_CQICH_ID_4_MASK 0xF0 + + +/* Wimax Mac REP-REQ Message Dissector */ +static int dissect_mac_mgmt_msg_rep_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len; + gint tlv_type, tlv_len, tlv_value_offset, length, tlv_offset; + proto_item *rep_item, *tlv_item, *ti_item; + proto_tree *rep_tree, *tlv_tree, *ti_tree; + tlv_info_t tlv_info; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type REP-REQ */ + rep_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_rep_decoder, tvb, offset, -1, "Report Request (REP-REQ)"); + /* add MAC REP-REQ subtree */ + rep_tree = proto_item_add_subtree(rep_item, ett_mac_mgmt_msg_rep_req_decoder); + + /* process the REP-REQ TLVs */ + while(offset < tvb_len) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-REQ TLV error"); + proto_tree_add_item(rep_tree, hf_rep_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(rep_tree, proto_mac_mgmt_msg_rep_decoder, tvb, offset, (tlv_len + tlv_value_offset), "REP-REQ Type: %u (%u bytes, offset=%u, length=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tlv_len, tvb_len); +#endif + /* update the offset for the TLV value */ + offset += tlv_value_offset; + /* process REP-REQ TLV Encoded information (11.11) */ + switch (tlv_type) + { + case REP_REQ_REPORT_REQUEST: + /* process the REP-REQ report request TLVs */ + tlv_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_req_report_request, tvb, offset-tlv_value_offset, FALSE); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rep_req_decoder); + for( tlv_offset = 0; tlv_offset < tlv_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-REQ Report Request TLV error"); + proto_tree_add_item(tlv_tree, hf_rep_invalid_tlv, tvb, (offset + tlv_offset), (tlv_len - offset - tlv_offset), ENC_NA); + break; + } +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(rep_tree, proto_mac_mgmt_msg_rep_decoder, tvb, offset, (length + tlv_value_offset), "REP-REQ Report Request Type: %u (%u bytes, offset=%u, length=%u, tvb_len=%u)", tlv_type, (length + tlv_value_offset), offset, length, tvb_len); +#endif + /* update the offset */ + tlv_offset += get_tlv_value_offset(&tlv_info); + switch (tlv_type) + { + case REP_REQ_REPORT_TYPE: + /* decode and display the Report type */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_req_report_type, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_req_decoder); + proto_tree_add_item(ti_tree, hf_rep_req_rep_type_bit0, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_rep_type_bit1, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_rep_type_bit2, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_rep_type_bit3_6, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); +/* proto_item_append_text(ti, " dB");*/ + proto_tree_add_item(ti_tree, hf_rep_req_rep_type_bit7, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_REQ_CHANNEL_NUMBER: + /* decode and display the Channel Number */ + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_req_channel_number, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case REP_REQ_CHANNEL_TYPE: + /* decode and display the Channel Type */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_req_channel_type, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_req_decoder); + proto_tree_add_item(ti_tree, hf_rep_req_channel_type_request, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_channel_type_reserved, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_REQ_ZONE_SPEC_PHY_CINR_REQ: + /* decode and display the zone specific physical cinr request */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_req_zone_spec_phy_cinr_request, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_req_decoder); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit0_2, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit3, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit4, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit5_6, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit7, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit8_13, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit14_17, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit18, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_phy_cinr_req_bit19_23, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_REQ_PREAMBLE_PHY_CINR_REQ: + /* decode and display the preamble phy cinr request */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_req_preamble_phy_cinr_request, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_req_decoder); + proto_tree_add_item(ti_tree, hf_rep_req_preamble_phy_cinr_req_bit0_1, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_preamble_phy_cinr_req_bit2_5, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_preamble_phy_cinr_req_bit6, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_preamble_phy_cinr_req_bit7, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_REQ_ZONE_SPEC_EFF_CINR_REQ: + /* decode and display the zone specific effective cinr request */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_req_zone_spec_effective_cinr_request, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_req_decoder); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_effective_cinr_req_bit0_2, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_effective_cinr_req_bit3, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_effective_cinr_req_bit4, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_effective_cinr_req_bit5_6, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + /* proto_item_append_text(ti, " dB");*/ + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_effective_cinr_req_bit7, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_effective_cinr_req_bit8_13, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_zone_spec_effective_cinr_req_bit14_15, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_REQ_PREAMBLE_EFF_CINR_REQ: + /* decode and display the preamble effective cinr request */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_req_preamble_effective_cinr_request, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_req_decoder); + proto_tree_add_item(ti_tree, hf_rep_req_preamble_effective_cinr_req_bit0_1, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_preamble_effective_cinr_req_bit2_7, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_REQ_CHANNEL_SELECTIVITY_REPORT: + /* decode and display the channel selectivity report */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_req_channel_selectivity_report, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_req_decoder); + proto_tree_add_item(ti_tree, hf_rep_req_channel_selectivity_rep_bit0, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_req_channel_selectivity_rep_bit1_7, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_unknown_type, tvb, (offset + tlv_offset), ENC_NA); + break; + } + tlv_offset += length; + } /* end of TLV process for loop */ + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, rep_tree, hf_rep_unknown_type, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + offset += tlv_len; + } /* end of TLV process while loop */ + } + return tvb_captured_length(tvb); +} + +/* Wimax Mac REP-RSP Message Dissector */ +static int dissect_mac_mgmt_msg_rep_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len, length, value; + gint tlv_type, tlv_len, tlv_value_offset, tlv_offset; + gint db_val; + proto_item *rep_item, *tlv_item, *ti, *ti_item; + proto_tree *rep_tree, *tlv_tree, *ti_tree; + tlv_info_t tlv_info; + gfloat current_power; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type REP-RSP */ + rep_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_rep_decoder, tvb, offset, -1, "Report Response (REP-RSP)"); + /* add MAC REP-RSP subtree */ + rep_tree = proto_item_add_subtree(rep_item, ett_mac_mgmt_msg_rep_rsp_decoder); + /* Decode and display the Report Response message (REP-RSP) */ + + /* process the REP-RSP TLVs */ + while(offset < tvb_len) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-RSP TLV error"); + proto_tree_add_item(rep_tree, hf_rep_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(rep_tree, proto_mac_mgmt_msg_rep_decoder, tvb, offset, (tlv_len + tlv_value_offset), "REP-RSP Type: %u (%u bytes, offset=%u, tlv_len=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tlv_len, tvb_len); +#endif + /* update the offset for the TLV value */ + offset += tlv_value_offset; + /* process REP-RSP TLV Encoded information (11.12) */ + switch (tlv_type) + { + case REP_RSP_REPORT_TYPE: + /* decode and display the Report type */ + tlv_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_rsp_report_type, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rep_rsp_decoder); + for( tlv_offset = 0; tlv_offset < tlv_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-RSP report subtype TLV error"); + proto_tree_add_item(tlv_tree, hf_rep_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + /* update the offset */ + tlv_offset += get_tlv_value_offset(&tlv_info); + switch (tlv_type) + { + case REP_RSP_REPORT_CHANNEL_NUMBER: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_report_type_channel_number, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case REP_RSP_REPORT_START_FRAME: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_report_type_frame_number, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case REP_RSP_REPORT_DURATION: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_report_type_duration, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case REP_RSP_REPORT_BASIC_REPORT: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_report_type_basic_report, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_report_type_basic_report_bit0, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_report_type_basic_report_bit1, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_report_type_basic_report_bit2, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_report_type_basic_report_bit3, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_report_type_basic_report_reserved, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_RSP_REPORT_CINR_REPORT: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_report_type_cinr_report, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + db_val = tvb_get_guint8(tvb, offset + tlv_offset) - 20; + if (db_val > 37) + db_val = 37; + proto_item_append_text(ti_item, " (%d dBm)", db_val); + ti = proto_tree_add_item(ti_tree, hf_rep_rsp_report_type_cinr_report_deviation, tvb, (offset + tlv_offset +1), 1, ENC_BIG_ENDIAN); + db_val = tvb_get_guint8(tvb, offset + tlv_offset + 1) - 20; + if (db_val > 37) + db_val = 37; + proto_item_append_text(ti, " (%d dBm)", db_val); + break; + case REP_RSP_REPORT_RSSI_REPORT: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_report_type_rssi_report, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + ti = proto_tree_add_item(ti_tree, hf_rep_rsp_report_type_rssi_report_mean, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + db_val = tvb_get_guint8(tvb, offset + tlv_offset) - 123; + if (db_val > -40) + db_val = -40; + proto_item_append_text(ti, " (%d dBm)", db_val); + ti = proto_tree_add_item(ti_tree, hf_rep_rsp_report_type_rssi_report_deviation, tvb, (offset + tlv_offset +1), 1, ENC_BIG_ENDIAN); + db_val = tvb_get_guint8(tvb, offset + tlv_offset + 1) - 123; + if (db_val > -40) + db_val = -40; + proto_item_append_text(ti, " (%d dBm)", db_val); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_unknown_type, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + } + tlv_offset += length; + } + break; + case REP_RSP_CHANNEL_TYPE: + /* decode and display the Channel Type */ + tlv_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_rsp_channel_type_report, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rep_rsp_decoder); + for( tlv_offset = 0; tlv_offset < tlv_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-RSP channel subtype TLV error"); + proto_tree_add_item(tlv_tree, hf_rep_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + + switch (tlv_type) + { + case REP_RSP_CHANNEL_TYPE_SUBCHANNEL: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_channel_type_subchannel, tvb, (offset + tlv_offset), ENC_BIG_ENDIAN); + break; + case REP_RSP_CHANNEL_TYPE_BAND_AMC: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_channel_type_band_amc, tvb, (offset + tlv_offset), ENC_BIG_ENDIAN); + break; + case REP_RSP_CHANNEL_TYPE_SAFETY_CHANNEL: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_channel_type_safety_channel, tvb, (offset + tlv_offset), ENC_NA); + break; + case REP_RSP_CHANNEL_TYPE_ENHANCED_BAND_AMC: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_channel_type_enhanced_band_amc, tvb, (offset + tlv_offset), ENC_NA); + break; + case REP_RSP_CHANNEL_TYPE_SOUNDING: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_channel_type_sounding, tvb, (offset + tlv_offset), ENC_BIG_ENDIAN); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_unknown_type, tvb, (offset + tlv_offset), ENC_NA); + break; + } + tlv_offset += (length + get_tlv_value_offset(&tlv_info)); + } + break; + case REP_RSP_ZONE_SPECIFIC_PHY_CINR: + /* decode and display the zone-specific physical CINR report type */ + tlv_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_rsp_zone_spec_phy_cinr_report, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rep_rsp_decoder); + for( tlv_offset = 0; tlv_offset < tlv_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-RSP zone-specific phy CINR report subtype TLV error"); + proto_tree_add_item(tlv_tree, hf_rep_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + /* update the offset */ + tlv_offset += get_tlv_value_offset(&tlv_info); + switch (tlv_type) + { + case REP_RSP_ZONE_SPECIFIC_PHY_CINR_PUSC_SC0: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_pusc_sc0, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_mean, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_report_type, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved1, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + if (length == 2) + { + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_deviation, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved2, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + } + break; + case REP_RSP_ZONE_SPECIFIC_PHY_CINR_PUSC_SC1: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_pusc_sc1, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_mean, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_report_type, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved1, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + if (length == 2) + { + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_deviation, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved2, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + } + break; + case REP_RSP_ZONE_SPECIFIC_PHY_CINR_FUSC: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_fusc, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_mean, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_report_type, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved1, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + if (length == 2) + { + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_deviation, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved2, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + } + break; + case REP_RSP_ZONE_SPECIFIC_PHY_CINR_OPTIONAL_FUSC: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_optional_fusc, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_mean, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_report_type, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved1, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + if (length == 2) + { + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_deviation, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved2, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + } + break; + case REP_RSP_ZONE_SPECIFIC_PHY_CINR_SAFETY_CHANNEL: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_safety_channel, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + case REP_RSP_ZONE_SPECIFIC_PHY_CINR_AMC: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_amc, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_mean, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_report_type, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved1, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + if (length == 2) + { + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_deviation, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_reserved2, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + } + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_unknown_type, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + } + tlv_offset += length; + } + break; + case REP_RSP_PREAMBLE_PHY_CINR: + /* decode and display the preamble physical CINR report type */ + tlv_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_rsp_preamble_phy_cinr_report, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rep_rsp_decoder); + for( tlv_offset = 0; tlv_offset < tlv_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-RSP preamble physical CINR report subtype TLV error"); + proto_tree_add_item(tlv_tree, hf_rep_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + + switch (tlv_type) + { + case REP_RSP_PREAMBLE_PHY_CINR_CONFIGURATION1: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_preamble_phy_cinr_rep_configuration_1, tvb, (offset + tlv_offset), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + if (length == 2) + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_deviation, tvb, (offset + tlv_offset + 1)+get_tlv_value_offset(&tlv_info), 1, ENC_BIG_ENDIAN); + break; + case REP_RSP_PREAMBLE_PHY_CINR_CONFIGURATION3: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_preamble_phy_cinr_rep_configuration_3, tvb, (offset + tlv_offset), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + if (length == 2) + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_phy_cinr_rep_deviation, tvb, (offset + tlv_offset + 1)+get_tlv_value_offset(&tlv_info), 1, ENC_BIG_ENDIAN); + break; + case REP_RSP_PREAMBLE_PHY_CINR_BAND_AMC: + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_preamble_phy_cinr_rep_band_amc_zone, tvb, (offset + tlv_offset), ENC_NA); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_unknown_type, tvb, (offset + tlv_offset), ENC_NA); + break; + } + tlv_offset += (length+get_tlv_value_offset(&tlv_info)); + } + break; + case REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR: + /* decode and display the zone-specific effective CINR report type */ + tlv_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_rsp_zone_spec_effective_cinr_report, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rep_rsp_decoder); + for( tlv_offset = 0; tlv_offset < tlv_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-RSP zone-specific effective CINR report subtype TLV error"); + proto_tree_add_item(tlv_tree, hf_rep_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + /* update the offset */ + tlv_offset += get_tlv_value_offset(&tlv_info); + switch (tlv_type) + { + case REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_PUSC_SC0: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_pusc_sc0, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_report_type, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_cqich_id, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_PUSC_SC1: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_pusc_sc1, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_report_type, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_cqich_id, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_FUSC: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_fusc, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_report_type, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_cqich_id, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_OPTIONAL_FUSC: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_optional_fusc, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_report_type, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_cqich_id, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_AMC_AAS: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_amc_aas, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_report_type, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_cqich_id, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_unknown_type, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + } + tlv_offset += length; + } + break; + case REP_RSP_PREAMBLE_EFFECTIVE_CINR: + /* decode and display the preamble effective CINR report type */ + tlv_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_rsp_preamble_effective_cinr_report, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rep_rsp_decoder); + for( tlv_offset = 0; tlv_offset < tlv_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset + tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "REP-RSP preamble effective CINR report subtype TLV error"); + proto_tree_add_item(tlv_tree, hf_rep_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + /* update the offset */ + tlv_offset += get_tlv_value_offset(&tlv_info); + switch (tlv_type) + { + case REP_RSP_PREAMBLE_EFFECTIVE_CINR_CONFIGURATION1: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_preamble_effective_cinr_rep_configuration_1, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_preamble_effective_cinr_rep_cqich_id, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_RSP_PREAMBLE_EFFECTIVE_CINR_CONFIGURATION3: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_rsp_preamble_effective_cinr_rep_configuration_3, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_preamble_effective_cinr_rep_cqich_id, tvb, (offset + tlv_offset), length, ENC_BIG_ENDIAN); + break; + case REP_RSP_CHANNEL_SELECTIVITY: + /* decode and display the channel selectivity report type */ + ti_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_rsp_channel_selectivity_report, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_mac_mgmt_msg_rep_rsp_decoder); + proto_tree_add_item(ti_tree, hf_rep_rsp_channel_selectivity_rep_frequency_a, tvb, (offset + tlv_offset + 2), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_channel_selectivity_rep_frequency_b, tvb, (offset + tlv_offset + 1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_rep_rsp_channel_selectivity_rep_frequency_c, tvb, (offset + tlv_offset), 1, ENC_BIG_ENDIAN); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, tlv_tree, hf_rep_unknown_type, tvb, (offset + tlv_offset)-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + } + tlv_offset += length; + } + break; + case CURRENT_TX_POWER: + tlv_item = add_tlv_subtree(&tlv_info, rep_tree, hf_rep_rsp_current_transmitted_power, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + value = tvb_get_guint8(tvb, offset); + current_power = ((gfloat)value - 128) / 2; + proto_item_append_text(tlv_item, " (%.1f dBm)", current_power); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, rep_tree, hf_rep_unknown_type, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + offset += tlv_len; + } /* end of TLV process while loop */ + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac REP-REQ Messages Dissectors */ +void proto_register_mac_mgmt_msg_rep(void) +{ + /* report display */ + static hf_register_info hf_rep[] = + { + { + &hf_rep_invalid_tlv, + { + "Invalid TLV", "wmx.rep.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { /* type 1.2 */ + &hf_rep_req_channel_number, + { + "Channel Number", "wmx.rep_req.channel_number", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { /* type 1.8 */ + &hf_rep_req_channel_selectivity_report, + { + "Channel Selectivity Report", "wmx.rep_req.channel_selectivity_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_req_channel_selectivity_rep_bit0, + { + "Include Frequency Selectivity Report", "wmx.rep_req.channel_selectivity_report.bit0", + FT_BOOLEAN, 8, NULL, REP_REQ_CHANNEL_SELECTIVITY_REPORT_BIT0, NULL, HFILL + } + }, + { + &hf_rep_req_channel_selectivity_rep_bit1_7, + { + "Reserved", "wmx.rep_req.channel_selectivity_report.bit1_7", + FT_UINT8, BASE_HEX, NULL, REP_REQ_CHANNEL_SELECTIVITY_REPORT_BIT1_7, NULL, HFILL + } + }, + { /* type 1.3 */ + &hf_rep_req_channel_type, + { + "Channel Type", "wmx.rep_req.channel_type", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_req_channel_type_request, + { + "Channel Type Request", "wmx.rep_req.channel_type.request", + FT_UINT8, BASE_DEC, VALS(vals_channel_types), 0x03, NULL, HFILL + } + }, + { + &hf_rep_req_channel_type_reserved, + { + "Reserved", "wmx.rep_req.channel_type.reserved", + FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL + } + }, + { /* type 1.7 */ + &hf_rep_req_preamble_effective_cinr_request, + { + "Preamble Effective CINR Request", "wmx.rep_req.preamble_effective_cinr_request", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_req_preamble_effective_cinr_req_bit0_1, + { + "Type Of Preamble Physical CINR Measurement", "wmx.rep_req.preamble_effective_cinr_request.bit0_1", + FT_UINT8, BASE_DEC, VALS(vals_type_of_measurements), REP_REQ_PREAMBLE_EFFECTIVE_CINR_REQUEST_BIT0_1, NULL, HFILL + } + }, + { + &hf_rep_req_preamble_effective_cinr_req_bit2_7, + { + "Reserved", "wmx.rep_req.preamble_effective_cinr_request.bit2_7", + FT_UINT8, BASE_HEX, NULL, REP_REQ_PREAMBLE_EFFECTIVE_CINR_REQUEST_BIT2_7, NULL, HFILL + } + }, + { /* type 1.5 */ + &hf_rep_req_preamble_phy_cinr_request, + { + "Preamble Physical CINR Request", "wmx.rep_req.preamble_phy_cinr_request", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_req_preamble_phy_cinr_req_bit0_1, + { + "Type Of Preamble Physical CINR Measurement", "wmx.rep_req.preamble_phy_cinr_request.bit0_1", + FT_UINT8, BASE_DEC, VALS(vals_type_of_measurements), REP_REQ_PREAMBLE_PHY_CINR_REQUEST_BIT0_1, NULL, HFILL + } + }, + { + &hf_rep_req_preamble_phy_cinr_req_bit2_5, + { + "Alpha (ave) in multiples of 1/16", "wmx.rep_req.preamble_phy_cinr_request.bit2_5", + FT_UINT8, BASE_DEC, NULL, REP_REQ_PREAMBLE_PHY_CINR_REQUEST_BIT2_5, NULL, HFILL + } + }, + { + &hf_rep_req_preamble_phy_cinr_req_bit6, + { + "CINR Report Type", "wmx.rep_req.preamble_phy_cinr_request.bit6", + FT_UINT8, BASE_DEC, VALS(vals_cinr_report_types), REP_REQ_PREAMBLE_PHY_CINR_REQUEST_BIT6, NULL, HFILL + } + }, + { + &hf_rep_req_preamble_phy_cinr_req_bit7, + { + "Reserved", "wmx.rep_req.preamble_phy_cinr_request.bit7", + FT_UINT8, BASE_HEX, NULL, REP_REQ_PREAMBLE_PHY_CINR_REQUEST_BIT7, NULL, HFILL + } + }, + { /* report request */ + &hf_rep_req_report_request, + { + "Report Request", "wmx.rep_req.report_request", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* type 1.1 */ + &hf_rep_req_report_type, + { + "Report Type", "wmx.rep_req.report_type", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_req_rep_type_bit0, + { + "Include DFS Basic Report", "wmx.rep_req.report_type.bit0", + FT_BOOLEAN, 8, NULL, REP_REQ_REPORT_TYPE_BIT0, NULL, HFILL + } + }, + { + &hf_rep_req_rep_type_bit1, + { + "Include CINR Report", "wmx.rep_req.report_type.bit1", + FT_BOOLEAN, 8, NULL, REP_REQ_REPORT_TYPE_BIT1, NULL, HFILL + } + }, + { + &hf_rep_req_rep_type_bit2, + { + "Include RSSI Report", "wmx.rep_req.report_type.bit2", + FT_BOOLEAN, 8, NULL, REP_REQ_REPORT_TYPE_BIT2, NULL, HFILL + } + }, + { + &hf_rep_req_rep_type_bit3_6, + { + "Alpha (ave) in multiples of 1/32", "wmx.rep_req.report_type.bit3_6", + FT_UINT8, BASE_DEC, NULL, REP_REQ_REPORT_TYPE_BIT3_6, NULL, HFILL + } + }, + { + &hf_rep_req_rep_type_bit7, + { + "Include Current Transmit Power Report", "wmx.rep_req.report_type.bit7", + FT_BOOLEAN, 8, NULL, REP_REQ_REPORT_TYPE_BIT7, NULL, HFILL + } + }, + { + &hf_rep_rsp_preamble_effective_cinr_rep_cqich_id, + { + "The 4 least significant bits of CQICH_ID", "wmx.rep_req.zone_spec_effective_cinr_report.cqich_id_4", + FT_UINT8, BASE_HEX, NULL, REP_RSP_ZONE_SPEC_EFFECTIVE_CINR_CQICH_ID_4_MASK, NULL, HFILL + } + }, + { + &hf_rep_rsp_zone_spec_effective_cinr_rep_cqich_id, + { + "The 3 least significant bits of CQICH_ID", "wmx.rep_req.zone_spec_effective_cinr_report.cqich_id", + FT_UINT8, BASE_HEX, NULL, REP_RSP_ZONE_SPEC_EFFECTIVE_CINR_CQICH_ID_MASK, NULL, HFILL + } + }, + { + &hf_rep_rsp_zone_spec_effective_cinr_rep_effective_cinr, + { + "Effective CINR", "wmx.rep_req.zone_spec_effective_cinr_report.effective_cinr", + FT_UINT8, BASE_DEC, NULL, REP_RSP_ZONE_SPEC_EFFECTIVE_CINR_EFFECTIVE_CINR_MASK, NULL, HFILL + } + }, + { + &hf_rep_rsp_zone_spec_effective_cinr_rep_report_type, + { + "Effective CINR Report", "wmx.rep_req.zone_spec_effective_cinr_report.report_type", + FT_UINT8, BASE_DEC, VALS(vals_data_cinr_measurements), REP_RSP_ZONE_SPEC_EFFECTIVE_CINR_REPORT_TYPE_MASK, NULL, HFILL + } + }, + { /* type 1.6 */ + &hf_rep_req_zone_spec_effective_cinr_request, + { + "Zone-specific Effective CINR Request", "wmx.rep_req.zone_spec_effective_cinr_request", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_effective_cinr_req_bit0_2, + { + "Type Of Zone On Which CINR Is To Be Reported", "wmx.rep_req.zone_spec_effective_cinr_request.bit0_2", + FT_UINT16, BASE_HEX, VALS(vals_type_of_zones), REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT0_2, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_effective_cinr_req_bit3, + { + "STC Zone", "wmx.rep_req.zone_spec_effective_cinr_request.bit3", + FT_BOOLEAN, 16, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT3, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_effective_cinr_req_bit4, + { + "AAS Zone", "wmx.rep_req.zone_spec_effective_cinr_request.bit4", + FT_BOOLEAN, 16, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT4, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_effective_cinr_req_bit5_6, + { + "PRBS ID", "wmx.rep_req.zone_spec_effective_cinr_request.bit5_6", + FT_UINT16, BASE_HEX, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT5_6, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_effective_cinr_req_bit7, + { + "CINR Measurement Report", "wmx.rep_req.zone_spec_effective_cinr_request.bit7", + FT_UINT16, BASE_HEX, VALS(vals_data_cinr_measurements), REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT7, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_effective_cinr_req_bit8_13, + { + "PUSC Major Group Map", "wmx.rep_req.zone_spec_effective_cinr_request.bit8_13", + FT_UINT16, BASE_HEX, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT8_13, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_effective_cinr_req_bit14_15, + { + "Reserved", "wmx.rep_req.zone_spec_effective_cinr_request.bit14_15", + FT_UINT16, BASE_HEX, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_16_BIT14_15, NULL, HFILL + } + }, + { /* second byte */ + &hf_rep_rsp_zone_spec_phy_cinr_rep_deviation, + { + "Standard Deviation of CINR", "wmx.rep_req.zone_spec_phy_cinr_report.deviation", + FT_UINT8, BASE_DEC, NULL, REP_RSP_ZONE_SPEC_PHY_CINR_DEVIATION_MASK, NULL, HFILL + } + }, + { /* first byte */ + &hf_rep_rsp_zone_spec_phy_cinr_rep_mean, + { + "Mean of Physical CINR", "wmx.rep_req.zone_spec_phy_cinr_report.mean", + FT_UINT8, BASE_DEC, NULL, REP_RSP_ZONE_SPEC_PHY_CINR_MEAN_MASK, NULL, HFILL + } + }, + { + &hf_rep_rsp_zone_spec_phy_cinr_rep_report_type, + { + "CINR Report Type", "wmx.rep_req.zone_spec_phy_cinr_report.report_type", + FT_UINT8, BASE_DEC, VALS(vals_data_cinr_measurements), REP_RSP_ZONE_SPEC_PHY_CINR_REP_TYPE_MASK, NULL, HFILL + } + }, + { + &hf_rep_rsp_zone_spec_phy_cinr_rep_reserved1, + { + "Reserved", "wmx.rep_req.zone_spec_phy_cinr_report.reserved1", + FT_UINT8, BASE_HEX, NULL, REP_RSP_ZONE_SPEC_PHY_CINR_RSV1_MASK, NULL, HFILL + } + }, + { + &hf_rep_rsp_zone_spec_phy_cinr_rep_reserved2, + { + "Reserved", "wmx.rep_req.zone_spec_phy_cinr_report.reserved2", + FT_UINT8, BASE_HEX, NULL, REP_RSP_ZONE_SPEC_PHY_CINR_RSV2_MASK, NULL, HFILL + } + }, + { /* type 1.4 */ + &hf_rep_req_zone_spec_phy_cinr_request, + { + "Zone-specific Physical CINR Request", "wmx.rep_req.zone_spec_phy_cinr_request", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit0_2, + { + "Type Of Zone On Which CINR Is To Be Reported", "wmx.rep_req.zone_spec_phy_cinr_request.bit0_2", + FT_UINT24, BASE_HEX, VALS(vals_type_of_zones), REP_REQ_TYPE_OF_ZONE_REQUEST_BIT0_2, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit3, + { + "STC Zone", "wmx.rep_req.zone_spec_phy_cinr_request.bit3", + FT_BOOLEAN, 24, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_BIT3, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit4, + { + "AAS Zone", "wmx.rep_req.zone_spec_phy_cinr_request.bit4", + FT_BOOLEAN, 24, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_BIT4, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit5_6, + { + "PRBS ID", "wmx.rep_req.zone_spec_phy_cinr_request.bit5_6", + FT_UINT24, BASE_HEX, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_BIT5_6, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit7, + { + "CINR Measurement Report", "wmx.rep_req.zone_spec_phy_cinr_request.bit7", + FT_UINT24, BASE_HEX, VALS(vals_data_cinr_measurements), REP_REQ_TYPE_OF_ZONE_REQUEST_BIT7, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit8_13, + { + "PUSC Major Group Map", "wmx.rep_req.zone_spec_phy_cinr_request.bit8_13", + FT_UINT24, BASE_HEX, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_BIT8_13, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit14_17, + { + "Alpha (ave) in multiples of 1/16", "wmx.rep_req.zone_spec_phy_cinr_request.bit14_17", + FT_UINT24, BASE_DEC, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_BIT14_17, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit18, + { + "CINR Report Type", "wmx.rep_req.zone_spec_phy_cinr_request.bit18", + FT_UINT24, BASE_HEX, VALS(vals_cinr_report_types), REP_REQ_TYPE_OF_ZONE_REQUEST_BIT18, NULL, HFILL + } + }, + { + &hf_rep_req_zone_spec_phy_cinr_req_bit19_23, + { + "Reserved", "wmx.rep_req.zone_spec_phy_cinr_request.bit19_23", + FT_UINT24, BASE_HEX, NULL, REP_REQ_TYPE_OF_ZONE_REQUEST_BIT19_23, NULL, HFILL + } + }, + { /* 6.3 */ + &hf_rep_rsp_channel_selectivity_report, + { + "Channel Selectivity Report", "wmx.rep_rsp.channel_selectivity_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_selectivity_rep_frequency_a, + { + "Frequency Selectivity Report a", "wmx.rep_rsp.channel_selectivity_report.frequency_a", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_selectivity_rep_frequency_b, + { + "Frequency Selectivity Report b", "wmx.rep_rsp.channel_selectivity_report.frequency_b", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_selectivity_rep_frequency_c, + { + "Frequency Selectivity Report c", "wmx.rep_rsp.channel_selectivity_report.frequency_c", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_type_report, + { + "Channel Type Report", "wmx.rep_rsp.channel_type_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_type_band_amc, + { + "Band AMC", "wmx.rep_rsp.channel_type_report.band_amc", + FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_type_enhanced_band_amc, + { + "Enhanced Band AMC", "wmx.rep_rsp.channel_type_report.enhanced_band_amc", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_type_safety_channel, + { + "Safety Channel", "wmx.rep_rsp.channel_type_report.safety_channel", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_type_sounding, + { + "Sounding", "wmx.rep_rsp.channel_type_report.sounding", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_channel_type_subchannel, + { + "Normal Subchannel", "wmx.rep_rsp.channel_type_report.subchannel", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_preamble_effective_cinr_report, + { + "Preamble Effective CINR Report", "wmx.rep_rsp.preamble_effective_cinr_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 6.1 */ + &hf_rep_rsp_preamble_effective_cinr_rep_configuration_1, + { + "The Estimation Of Effective CINR Measured From Preamble For Frequency Reuse Configuration=1", "wmx.rep_rsp.preamble_effective_cinr_report.configuration_1", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 6.2 */ + &hf_rep_rsp_preamble_effective_cinr_rep_configuration_3, + { + "The Estimation Of Effective CINR Measured From Preamble For Frequency Reuse Configuration=3", "wmx.rep_rsp.preamble_effective_cinr_report.configuration_3", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_preamble_phy_cinr_report, + { + "Preamble Physical CINR Report", "wmx.rep_rsp.preamble_phy_cinr_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 4.3 */ + &hf_rep_rsp_preamble_phy_cinr_rep_band_amc_zone, + { + "The Estimation Of Physical CINR Measured From Preamble For Band AMC Zone", "wmx.rep_rsp.preamble_phy_cinr_report.band_amc_zone", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 4.1 */ + &hf_rep_rsp_preamble_phy_cinr_rep_configuration_1, + { + "The Estimation Of Physical CINR Measured From Preamble For Frequency Reuse Configuration=1", "wmx.rep_rsp.preamble_phy_cinr_report.configuration_1", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 4.2 */ + &hf_rep_rsp_preamble_phy_cinr_rep_configuration_3, + { + "The Estimation Of Physical CINR Measured From Preamble For Frequency Reuse Configuration=3", "wmx.rep_rsp.preamble_phy_cinr_report.configuration_3", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + /* Report Response */ + { + &hf_rep_rsp_report_type, + { + "Report Type", "wmx.rep_rsp.report_type", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_basic_report, + { + "Basic Report", "wmx.rep_rsp.report_type.basic_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_basic_report_bit0, + { + "Wireless HUMAN Detected", "wmx.rep_rsp.report_type.basic_report.bit0", + FT_BOOLEAN, 8, NULL, REP_RSP_REPORT_TYPE_BASIC_REPORT_BIT0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_basic_report_bit1, + { + "Unknown Transmission Detected", "wmx.rep_rsp.report_type.basic_report.bit1", + FT_BOOLEAN, 8, NULL, REP_RSP_REPORT_TYPE_BASIC_REPORT_BIT1, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_basic_report_bit2, + { + "Specific Spectrum User Detected", "wmx.rep_rsp.report_type.basic_report.bit2", + FT_BOOLEAN, 8, NULL, REP_RSP_REPORT_TYPE_BASIC_REPORT_BIT2, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_basic_report_bit3, + { + "Channel Not Measured", "wmx.rep_rsp.report_type.basic_report.bit3", + FT_BOOLEAN, 8, NULL, REP_RSP_REPORT_TYPE_BASIC_REPORT_BIT3, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_basic_report_reserved, + { + "Reserved", "wmx.rep_rsp.report_type.basic_report.reserved", + FT_UINT8, BASE_HEX, NULL, REP_RSP_REPORT_TYPE_BASIC_REPORT_RSV, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_channel_number, + { + "Channel Number", "wmx.rep_rsp.report_type.channel_number", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_cinr_report, + { + "CINR Report", "wmx.rep_rsp.report_type.cinr_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_cinr_report_deviation, + { + "CINR Standard Deviation", "wmx.rep_rsp.report_type.cinr_report_deviation", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_cinr_report_mean, + { + "CINR Mean", "wmx.rep_rsp.report_type.cinr_report_mean", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_duration, + { + "Duration", "wmx.rep_rsp.report_type.duration", + FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_frame_number, + { + "Start Frame", "wmx.rep_rsp.report_type.frame_number", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_rssi_report, + { + "RSSI Report", "wmx.rep_rsp.report_type.rssi_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_rssi_report_deviation, + { + "RSSI Standard Deviation", "wmx.rep_rsp.report_type.rssi_report_deviation", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_current_transmitted_power, + { + "Current Transmitted Power", "wmx.rep_rsp.current_transmitted_power", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_report_type_rssi_report_mean, + { + "RSSI Mean", "wmx.rep_rsp.report_type.rssi_report_mean", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_zone_spec_effective_cinr_report, + { + "Zone-specific Effective CINR Report", "wmx.rep_rsp.zone_spec_effective_cinr_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 5.5 */ + &hf_rep_rsp_zone_spec_effective_cinr_rep_amc_aas, + { + "AMC AAS Zone", "wmx.rep_rsp.zone_spec_effective_cinr_report.amc_aas", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 5.3 */ + &hf_rep_rsp_zone_spec_effective_cinr_rep_fusc, + { + "FUSC Zone", "wmx.rep_rsp.zone_spec_effective_cinr_report.fusc", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 5.4 */ + &hf_rep_rsp_zone_spec_effective_cinr_rep_optional_fusc, + { + "Optional FUSC Zone", "wmx.rep_rsp.zone_spec_effective_cinr_report.optional_fusc", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 5.1 */ + &hf_rep_rsp_zone_spec_effective_cinr_rep_pusc_sc0, + { + "PUSC Zone (use all SC=0)", "wmx.rep_rsp.zone_spec_effective_cinr_report.pusc_sc0", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 5.2 */ + &hf_rep_rsp_zone_spec_effective_cinr_rep_pusc_sc1, + { + "PUSC Zone (use all SC=1)", "wmx.rep_rsp.zone_spec_effective_cinr_report.pusc_sc1", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_rsp_zone_spec_phy_cinr_report, + { + "Zone-specific Physical CINR Report", "wmx.rep_rsp.zone_spec_phy_cinr_report", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 3.6 */ + &hf_rep_rsp_zone_spec_phy_cinr_rep_amc, + { + "AMC Zone", "wmx.rep_rsp.zone_spec_phy_cinr_report.amc", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 3.3 */ + &hf_rep_rsp_zone_spec_phy_cinr_rep_fusc, + { + "FUSC Zone", "wmx.rep_rsp.zone_spec_phy_cinr_report.fusc", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 3.4 */ + &hf_rep_rsp_zone_spec_phy_cinr_rep_optional_fusc, + { + "Optional FUSC Zone", "wmx.rep_rsp.zone_spec_phy_cinr_report.optional_fusc", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 3.1 */ + &hf_rep_rsp_zone_spec_phy_cinr_rep_pusc_sc0, + { + "PUSC Zone (use all SC=0)", "wmx.rep_rsp.zone_spec_phy_cinr_report.pusc_sc0", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 3.2 */ + &hf_rep_rsp_zone_spec_phy_cinr_rep_pusc_sc1, + { + "PUSC Zone (use all SC=1)", "wmx.rep_rsp.zone_spec_phy_cinr_report.pusc_sc1", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 3.5 */ + &hf_rep_rsp_zone_spec_phy_cinr_rep_safety_channel, + { + "Safety Channel", "wmx.rep_rsp.zone_spec_phy_cinr_report.safety_channel", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rep_unknown_type, + { + "Unknown TLV type", "wmx.rep.unknown_tlv_type", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett_rep[] = + { + &ett_mac_mgmt_msg_rep_req_decoder, + &ett_mac_mgmt_msg_rep_rsp_decoder, + }; + + proto_mac_mgmt_msg_rep_decoder = proto_register_protocol ( + "WiMax REP-REQ/RSP Messages", /* name */ + "WiMax REP-REQ/RSP (rep)", /* short name */ + "wmx.rep" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_rep_decoder, hf_rep, array_length(hf_rep)); + proto_register_subtree_array(ett_rep, array_length(ett_rep)); + rep_req_handle = register_dissector("mac_mgmt_msg_rep_req_handler", dissect_mac_mgmt_msg_rep_req_decoder, proto_mac_mgmt_msg_rep_decoder); + rep_rsp_handle = register_dissector("mac_mgmt_msg_rep_rsp_handler", dissect_mac_mgmt_msg_rep_rsp_decoder, proto_mac_mgmt_msg_rep_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_rep(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_REP_REQ, rep_req_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_REP_RSP, rep_rsp_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: + */ diff --git a/plugins/epan/wimax/msg_res_cmd.c b/plugins/epan/wimax/msg_res_cmd.c new file mode 100644 index 00000000..67d321da --- /dev/null +++ b/plugins/epan/wimax/msg_res_cmd.c @@ -0,0 +1,154 @@ +/* msg_res_cmd.c + * WiMax MAC Management RES-CMD Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#if 0 +#define DEBUG /* for debug only */ +#endif + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_res_cmd(void); +void proto_reg_handoff_mac_mgmt_msg_res_cmd(void); + +static dissector_handle_t res_cmd_handle; + +static gint proto_mac_mgmt_msg_res_cmd_decoder = -1; +static gint ett_mac_mgmt_msg_res_cmd_decoder = -1; + +/* fix fields */ +static gint hf_res_cmd_unknown_type = -1; +static gint hf_res_cmd_invalid_tlv = -1; + + +/* Wimax Mac RES-CMD Message Dissector */ +static int dissect_mac_mgmt_msg_res_cmd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len; + gint tlv_type, tlv_len, tlv_value_offset; + proto_item *res_cmd_item; + proto_tree *res_cmd_tree; + proto_tree *tlv_tree = NULL; + tlv_info_t tlv_info; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type RES-CMD */ + res_cmd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_res_cmd_decoder, tvb, offset, -1, "Reset Command (RES-CMD)"); + /* add MAC RES-CMD subtree */ + res_cmd_tree = proto_item_add_subtree(res_cmd_item, ett_mac_mgmt_msg_res_cmd_decoder); + /* Decode and display the Reset Command (RES-CMD) */ + /* process the RES-CMD TLVs */ + while(offset < tvb_len) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RES-CMD TLV error"); + proto_tree_add_item(res_cmd_tree, hf_res_cmd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(res_cmd_tree, proto_mac_mgmt_msg_res_cmd_decoder, tvb, offset, (tlv_len + tlv_value_offset), "RES-CMD Type: %u (%u bytes, offset=%u, tlv_len=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tlv_len, tvb_len); +#endif + /* process RES-CMD TLV Encoded information */ + switch (tlv_type) + { + case HMAC_TUPLE: /* Table 348d */ + /* decode and display the HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_res_cmd_decoder, res_cmd_tree, proto_mac_mgmt_msg_res_cmd_decoder, tvb, offset, tlv_len, "HMAC Tuple"); + wimax_hmac_tuple_decoder(tlv_tree, tvb, offset+tlv_value_offset, tlv_len); + break; + case CMAC_TUPLE: /* Table 348b */ + /* decode and display the CMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_res_cmd_decoder, res_cmd_tree, proto_mac_mgmt_msg_res_cmd_decoder, tvb, offset, tlv_len, "CMAC Tuple"); + wimax_cmac_tuple_decoder(tlv_tree, tvb, offset+tlv_value_offset, tlv_len); + break; + default: + /* display the unknown tlv in hex */ + add_tlv_subtree(&tlv_info, res_cmd_tree, hf_res_cmd_unknown_type, tvb, offset, ENC_NA); + break; + } + offset += (tlv_len+tlv_value_offset); + } /* end of TLV process while loop */ + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac RES-CMD Message Dissector */ +void proto_register_mac_mgmt_msg_res_cmd(void) +{ + /* DSx display */ + static hf_register_info hf_res_cmd[] = + { + { + &hf_res_cmd_invalid_tlv, + {"Invalid TLV", "wmx.res_cmd.invalid_tlv", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL} + }, + { + &hf_res_cmd_unknown_type, + {"Unknown TLV type", "wmx.res_cmd.unknown_tlv_type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + } + }; + + /* Setup protocol subtree array */ + static gint *ett_res_cmd[] = + { + &ett_mac_mgmt_msg_res_cmd_decoder, + }; + + proto_mac_mgmt_msg_res_cmd_decoder = proto_register_protocol ( + "WiMax RES-CMD Message", /* name */ + "WiMax RES-CMD (res)", /* short name */ + "wmx.res" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_res_cmd_decoder, hf_res_cmd, array_length(hf_res_cmd)); + proto_register_subtree_array(ett_res_cmd, array_length(ett_res_cmd)); + res_cmd_handle = register_dissector("mac_mgmt_msg_res_handler", dissect_mac_mgmt_msg_res_cmd_decoder, proto_mac_mgmt_msg_res_cmd_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_res_cmd(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_RES_CMD, res_cmd_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: + */ diff --git a/plugins/epan/wimax/msg_rng_req.c b/plugins/epan/wimax/msg_rng_req.c new file mode 100644 index 00000000..68f9569b --- /dev/null +++ b/plugins/epan/wimax/msg_rng_req.c @@ -0,0 +1,631 @@ +/* msg_rng_req.c + * WiMax MAC Management RNG-REQ Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_rng_req(void); +void proto_reg_handoff_mac_mgmt_msg_rng_req(void); + +static dissector_handle_t rng_req_handle; + +extern gboolean include_cor2_changes; + +static gint proto_mac_mgmt_msg_rng_req_decoder = -1; +static gint ett_mac_mgmt_msg_rng_req_decoder = -1; + +/* RNG-REQ fields */ +static gint hf_rng_req_reserved = -1; +static gint hf_rng_req_dl_burst_profile_diuc = -1; +static gint hf_rng_req_dl_burst_profile_lsb_ccc = -1; +static gint hf_rng_req_ss_mac_address = -1; +static gint hf_rng_req_ranging_anomalies_max_power = -1; +static gint hf_rng_req_ranging_anomalies_min_power = -1; +static gint hf_rng_req_ranging_anomalies_timing_adj = -1; +static gint hf_rng_req_aas_broadcast = -1; +static gint hf_rng_req_serving_bs_id = -1; +static gint hf_rng_req_ranging_purpose_ho_indication = -1; +static gint hf_rng_req_ranging_purpose_location_update_request = -1; +static gint hf_rng_req_ranging_purpose_reserved = -1; +static gint hf_rng_req_ho_id = -1; +static gint hf_rng_req_power_down_indicator = -1; +static gint hf_rng_req_repetition_coding_level = -1; +static gint hf_rng_req_requested_downlink_repetition_coding_level_reserved = -1; +static gint hf_rng_req_cmac_key_count = -1; +static gint hf_rng_definition_of_power_saving_class_present = -1; +static gint hf_rng_activation_of_power_saving_class = -1; +static gint hf_rng_trf_ind_required = -1; +static gint hf_rng_power_saving_class_reserved = -1; +static gint hf_rng_power_saving_class_id = -1; +static gint hf_rng_power_saving_class_type = -1; +static gint hf_rng_power_saving_first_sleep_window_frame = -1; +static gint hf_rng_power_saving_initial_sleep_window = -1; +static gint hf_rng_power_saving_listening_window = -1; +static gint hf_rng_power_saving_final_sleep_window_base = -1; +static gint hf_rng_power_saving_final_sleep_window_exp = -1; +static gint hf_rng_power_saving_slpid = -1; +static gint hf_rng_power_saving_included_cid = -1; +static gint hf_rng_power_saving_mgmt_connection_direction = -1; +static gint hf_tlv_type = -1; +static gint hf_rng_invalid_tlv = -1; +static gint hf_rng_power_saving_class_flags = -1; +static gint hf_rng_req_dl_burst_profile = -1; +static gint hf_rng_req_ranging_anomalies = -1; +static gint hf_rng_req_ranging_purpose_indication = -1; +static gint hf_rng_req_requested_rep_coding_level = -1; + +/* STRING RESOURCES */ + +static const true_false_string tfs_rng_req_aas_broadcast = { + "SS cannot receive broadcast messages", + "SS can receive broadcast messages" +}; + +static const value_string vals_rng_req_ranging_purpose_location_update_request[] = { + {1, "MS action of Idle Mode Location Update Process"}, + {0, NULL} +}; + +static const value_string vals_rng_req_repetition_coding_level[] = { + {0, "No repetition"}, + {1, "Repetition coding of 2"}, + {2, "Repetition coding of 4"}, + {3, "Repetition coding of 6"}, + {0, NULL} +}; + +static const true_false_string tfs_rng_activate = { + "Activate", + "Deactivate" +}; + +static const true_false_string tfs_rng_max_power = { + "SS is already at maximum power", + "SS is not at maximum power" +}; + +static const true_false_string tfs_rng_min_power = { + "SS is already at minimum power", + "SS is not at minimum power" +}; + +static const true_false_string tfs_rng_timing_adj = { + "Sum of commanded timing adjustments is too large", + "Sum of commanded timing adjustments is within bounds" +}; + +/* Decode RNG Power Saving Class parameters (Sub TLV's). */ +void dissect_power_saving_class(proto_tree *rng_req_tree, gint tlv_type, tvbuff_t *tvb, guint compound_tlv_len, packet_info *pinfo, guint offset) +{ + proto_item *tlv_item; + proto_tree *tlv_tree; + proto_tree *power_saving_class_tree = NULL; + guint tlv_len; + guint tlv_offset; + tlv_info_t tlv_info; + + /* Add a subtree for the power saving class parameters */ + tlv_item = proto_tree_add_protocol_format(rng_req_tree, proto_mac_mgmt_msg_rng_req_decoder, tvb, offset, compound_tlv_len, "Power saving class parameters (%u bytes)", compound_tlv_len); + power_saving_class_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rng_req_decoder); + + /* Update the compound_tlv_len to include the offset */ + compound_tlv_len += offset; + + while(offset < compound_tlv_len) + { + /* Get the TLV data. */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RNG-REQ TLV error"); + proto_tree_add_item(power_saving_class_tree, hf_rng_invalid_tlv, tvb, offset, (compound_tlv_len - offset), ENC_NA); + break; + } + /* get the offset to the TLV data */ + tlv_offset = offset + get_tlv_value_offset(&tlv_info); + + switch (tlv_type) { + case RNG_POWER_SAVING_CLASS_FLAGS: + /* display Power Saving Class Flags */ + /* add subtree */ + tlv_item = add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_class_flags, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rng_req_decoder); + proto_tree_add_item(tlv_tree, hf_rng_definition_of_power_saving_class_present, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_activation_of_power_saving_class, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_trf_ind_required, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_power_saving_class_reserved, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case RNG_POWER_SAVING_CLASS_ID: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_class_id, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_POWER_SAVING_CLASS_TYPE: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_class_type, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_START_FRAME_NUMBER: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_first_sleep_window_frame, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_INITIAL_SLEEP_WINDOW: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_initial_sleep_window, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_LISTENING_WINDOW: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_listening_window, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_FINAL_SLEEP_WINDOW_BASE: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_final_sleep_window_base, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_FINAL_SLEEP_WINDOW_EXPONENT: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_final_sleep_window_exp, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_SLPID: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_slpid, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_CID: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_included_cid, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_DIRECTION: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_rng_power_saving_mgmt_connection_direction, tvb, offset, ENC_BIG_ENDIAN); + break; + default: + add_tlv_subtree(&tlv_info, power_saving_class_tree, hf_tlv_type, tvb, offset, ENC_NA); + break; + } + /* update the offset */ + offset = tlv_len + tlv_offset; + } /* end of TLV process while loop */ +} + + +/* Decode RNG-REQ messages. */ +static int dissect_mac_mgmt_msg_rng_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tlv_offset; + guint tvb_len; + proto_item *rng_req_item, *tlv_item; + proto_tree *rng_req_tree, *tlv_tree; + tlv_info_t tlv_info; + gint tlv_type; + gint tlv_len; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type RNG-REQ */ + rng_req_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_rng_req_decoder, tvb, offset, tvb_len, "MAC Management Message, RNG-REQ"); + /* add MAC RNG-REQ subtree */ + rng_req_tree = proto_item_add_subtree(rng_req_item, ett_mac_mgmt_msg_rng_req_decoder); + /* display the Message Type */ + proto_tree_add_item(rng_req_tree, hf_rng_req_reserved, tvb, 0, 1, ENC_BIG_ENDIAN); + offset += 1; + + while(offset < tvb_len) + { + /* Get the TLV data. */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RNG-REQ TLV error"); + proto_tree_add_item(rng_req_tree, hf_rng_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the offset to the TLV data */ + tlv_offset = offset + get_tlv_value_offset(&tlv_info); + + switch (tlv_type) { + case RNG_REQ_DL_BURST_PROFILE: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_dl_burst_profile, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rng_req_decoder); + proto_tree_add_item(tlv_tree, hf_rng_req_dl_burst_profile_diuc, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_req_dl_burst_profile_lsb_ccc, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case RNG_REQ_SS_MAC_ADDRESS: + add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_ss_mac_address, tvb, offset, ENC_NA); + break; + case RNG_REQ_RANGING_ANOMALIES: + tlv_item = add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_ranging_anomalies, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rng_req_decoder); + proto_tree_add_item(tlv_tree, hf_rng_req_ranging_anomalies_max_power, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_req_ranging_anomalies_min_power, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_req_ranging_anomalies_timing_adj, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case RNG_REQ_AAS_BROADCAST: + add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_aas_broadcast, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_REQ_SERVING_BS_ID: + add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_serving_bs_id, tvb, offset, ENC_NA); + break; + case RNG_REQ_RANGING_PURPOSE_INDICATION: + /* display the Ranging Purpose Flags */ + tlv_item = add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_ranging_purpose_indication, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rng_req_decoder); + proto_tree_add_item(tlv_tree, hf_rng_req_ranging_purpose_ho_indication, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_req_ranging_purpose_location_update_request, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_req_ranging_purpose_reserved, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case RNG_REQ_HO_ID: + add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_ho_id, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_REQ_POWER_DOWN_INDICATOR: + add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_power_down_indicator, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_REQ_REQUESTED_DNLK_REP_CODING_LEVEL: + tlv_item = add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_requested_rep_coding_level, tvb, offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_mac_mgmt_msg_rng_req_decoder); + proto_tree_add_item(tlv_tree, hf_rng_req_repetition_coding_level, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_rng_req_requested_downlink_repetition_coding_level_reserved, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case RNG_REQ_CMAC_KEY_COUNT: + if (include_cor2_changes) { + add_tlv_subtree(&tlv_info, rng_req_tree, hf_rng_req_cmac_key_count, tvb, offset, ENC_BIG_ENDIAN); + } else { + /* Unknown TLV type */ + add_tlv_subtree(&tlv_info, rng_req_tree, hf_tlv_type, tvb, offset, ENC_NA); + } + break; + case SHORT_HMAC_TUPLE: + case SHORT_HMAC_TUPLE_COR2: + if ((!include_cor2_changes && (tlv_type == SHORT_HMAC_TUPLE)) || + (include_cor2_changes && (tlv_type == SHORT_HMAC_TUPLE_COR2))) { + /* decode and display the Short HMAC Tuple */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_rng_req_decoder, rng_req_tree, proto_mac_mgmt_msg_rng_req_decoder, tvb, offset, tlv_len, "Short HMAC Tuple"); + wimax_short_hmac_tuple_decoder(tlv_tree, tvb, tlv_offset, tvb_len - offset); + } else { + /* Unknown TLV Type */ + add_tlv_subtree(&tlv_info, rng_req_tree, hf_tlv_type, tvb, offset, ENC_NA); + } + break; + case MAC_VERSION_ENCODING: + offset += wimax_common_tlv_encoding_decoder(tvb_new_subset_remaining(tvb, offset), pinfo, rng_req_tree); + continue; + break; + case RNG_REQ_POWER_SAVING_CLASS_PARAMETERS: + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_rng_req_decoder, rng_req_tree, proto_mac_mgmt_msg_rng_req_decoder, tvb, offset, tlv_len, "Power Saving Class Parameters"); + dissect_power_saving_class(tlv_tree, tlv_type, tvb, tlv_len, pinfo, tlv_offset); + break; + default: + add_tlv_subtree(&tlv_info, rng_req_tree, hf_tlv_type, tvb, offset, ENC_NA); + break; + } + /* update the offset */ + offset = tlv_len + tlv_offset; + } /* end of TLV process while loop */ + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_rng_req(void) +{ + /* RNG-REQ fields display */ + static hf_register_info hf[] = + { + { + &hf_rng_activation_of_power_saving_class, + { + "Activation of Power Saving Class (Types 1 and 2 only)", "wmx.rng.power_save.activate", + FT_BOOLEAN, 8, TFS(&tfs_rng_activate), 0x02, NULL, HFILL + } + }, + { + &hf_rng_power_saving_class_id, + { + "Power Saving Class ID", "wmx.rng.power_save.class_id", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_power_saving_class_type, + { + "Power Saving Class Type", "wmx.rng.power_save.class_type", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_definition_of_power_saving_class_present, + { + "Definition of Power Saving Class present", "wmx.rng.power_save.definition_present", + FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_rng_power_saving_final_sleep_window_base, + { + "Final-sleep window base (measured in frames)", "wmx.rng.power_save.final_sleep_window_base", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_power_saving_final_sleep_window_exp, + { + "Final-sleep window exponent (measured in frames)", "wmx.rng.power_save.final_sleep_window_exp", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_power_saving_first_sleep_window_frame, + { + "Start frame number for first sleep window", "wmx.rng.power_save.first_sleep_window_frame", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_power_saving_included_cid, + { + "CID of connection to be included into the Power Saving Class.", "wmx.rng.power_save.included_cid", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_power_saving_initial_sleep_window, + { + "Initial-sleep window", "wmx.rng.power_save.initial_sleep_window", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_power_saving_listening_window, + { + "Listening window duration (measured in frames)", "wmx.rng.power_save.listening_window", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_power_saving_mgmt_connection_direction, + { + "Direction for management connection added to Power Saving Class", "wmx.rng.power_save.mgmt_connection_direction", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_power_saving_class_reserved, + { + "Reserved", "wmx.rng.power_save.reserved", + FT_UINT8, BASE_DEC, NULL, 0xF8, NULL, HFILL + } + }, + { + &hf_rng_power_saving_slpid, + { + "SLPID assigned by the BS whenever an MS is instructed to enter sleep mode", "wmx.rng.power_save.slpid", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_trf_ind_required, + { + "BS shall transmit at least one TRF-IND message during each listening window of the Power Saving Class", "wmx.rng.power_save.trf_ind_required", + FT_BOOLEAN, 8, TFS(&tfs_rng_activate), 0x04, NULL, HFILL + } + }, + { + &hf_rng_req_aas_broadcast, + { + "AAS broadcast capability", "wmx.rng_req.aas_broadcast", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_rng_req_aas_broadcast), 0x0, NULL, HFILL + } + }, + { + &hf_rng_req_ranging_anomalies_max_power, + { + "Meaning", "wmx.rng_req.anomalies.max_power", + FT_BOOLEAN, 8, TFS(&tfs_rng_max_power), 0x04, NULL, HFILL + } + }, + { + &hf_rng_req_ranging_anomalies_min_power, + { + "Meaning", "wmx.rng_req.anomalies.min_power", + FT_BOOLEAN, 8, TFS(&tfs_rng_min_power), 0x02, NULL, HFILL + } + }, + { + &hf_rng_req_ranging_anomalies_timing_adj, + { + "Meaning", "wmx.rng_req.anomalies.timing_adj", + FT_BOOLEAN, 8, TFS(&tfs_rng_timing_adj), 0x01, NULL, HFILL + } + }, + { + &hf_rng_req_cmac_key_count, + { + "CMAC Key Count", "wmx.rng_req.cmac_key_count", + FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_req_dl_burst_profile_lsb_ccc, + { + "LSB of CCC of DCD associated with DIUC", "wmx.rng_req.dl_burst_profile.ccc", + FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_rng_req_dl_burst_profile_diuc, + { + "DIUC", "wmx.rng_req.dl_burst_profile.diuc", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, + { + &hf_tlv_type, + { + "Unknown TLV Type", "wmx.rng_req.unknown_tlv_type", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_rng_invalid_tlv, + { + "Invalid TLV", "wmx.rng_req.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_rng_req_ho_id, + { + "ID from the target BS for use in initial ranging during MS handover to it", "wmx.rng_req.ho_id", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_req_power_down_indicator, + { + "Power down Indicator", "wmx.rng_req.power_down_indicator", + FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_req_ranging_purpose_ho_indication, + { + "MS HO indication", "wmx.rng_req.ranging_purpose.ho_indication", + FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_rng_req_ranging_purpose_reserved, + { + "Reserved", "wmx.rng_req.ranging_purpose.reserved", + FT_UINT8, BASE_DEC, NULL, 0xFC, NULL, HFILL + } + }, + { + &hf_rng_req_ranging_purpose_location_update_request, + { + "Location Update Request", "wmx.rng_req.ranging_purpose.loc_update_req", + FT_UINT8, BASE_DEC, VALS(vals_rng_req_ranging_purpose_location_update_request), 0x02, NULL, HFILL + } + }, + { + &hf_rng_req_repetition_coding_level, + { + "Repetition coding level", "wmx.rng_req.repetition_coding_level", + FT_UINT8, BASE_DEC, VALS(vals_rng_req_repetition_coding_level), 0x03, NULL, HFILL + } + }, + { + &hf_rng_req_requested_downlink_repetition_coding_level_reserved, + { + "Reserved", "wmx.rng_req.reserved", + FT_UINT8, BASE_DEC, NULL, 0xFC, NULL, HFILL + } + }, + { + &hf_rng_req_reserved, + { + "Reserved", "wmx.rng_req.reserved", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_req_serving_bs_id, + { + "Former serving BS ID", "wmx.rng_req.serving_bs_id", + FT_ETHER, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_req_ss_mac_address, + { + "SS MAC Address", "wmx.rng_req.ss_mac_address", + FT_ETHER, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_power_saving_class_flags, + { + "Power Saving Class", "wmx.rng.power_save.flags", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_req_dl_burst_profile, + { + "Requested Downlink Burst Profile", "wmx.rng_req.dl_burst_profile", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_req_ranging_anomalies, + { + "Ranging Anomalies", "wmx.rng_req.anomalies", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_req_ranging_purpose_indication, + { + "Ranging Purpose Flags", "wmx.rng_req.ranging_purpose.indication", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_req_requested_rep_coding_level, + { + "Requested downlink repetition coding level", "wmx.rng_req.requested_rep_coding_level", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_rng_req_decoder, + }; + + proto_mac_mgmt_msg_rng_req_decoder = proto_register_protocol ( + "WiMax RNG-REQ Messages", /* name */ + "WiMax RNG-REQ", /* short name */ + "wmx.rng_req" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_rng_req_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + rng_req_handle = register_dissector("mac_mgmt_msg_rng_req_handler", dissect_mac_mgmt_msg_rng_req_decoder, proto_mac_mgmt_msg_rng_req_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_rng_req(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_RNG_REQ, rng_req_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: + */ diff --git a/plugins/epan/wimax/msg_rng_rsp.c b/plugins/epan/wimax/msg_rng_rsp.c new file mode 100644 index 00000000..f1587ebc --- /dev/null +++ b/plugins/epan/wimax/msg_rng_rsp.c @@ -0,0 +1,963 @@ +/* msg_rng_rsp.c + * WiMax MAC Management RNG-RSP Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: John R. Underwood + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_rng_rsp(void); +void proto_reg_handoff_mac_mgmt_msg_rng_rsp(void); + +extern gboolean include_cor2_changes; + + +static dissector_handle_t rng_rsp_handle = NULL; +static dissector_handle_t sbc_rsp_handle = NULL; +static dissector_handle_t reg_rsp_handle = NULL; + +static gint proto_mac_mgmt_msg_rng_rsp_decoder = -1; +static gint ett_mac_mgmt_msg_rng_rsp_decoder = -1; +static gint ett_rng_rsp_message_tree = -1; + +/* RNG-RSP fields */ +static gint hf_rng_req_reserved = -1; +/* static gint hf_rng_rsp_ul_channel_id = -1; */ +static gint hf_rng_rsp_timing_adjust = -1; +static gint hf_rng_rsp_power_level_adjust = -1; +static gint hf_rng_rsp_offset_freq_adjust = -1; +static gint hf_rng_rsp_ranging_status = -1; +static gint hf_rng_rsp_dl_freq_override = -1; +static gint hf_rng_rsp_ul_chan_id_override = -1; +static gint hf_rng_rsp_dl_operational_burst_profile = -1; +static gint hf_rng_rsp_dl_operational_burst_profile_diuc = -1; +static gint hf_rng_rsp_dl_operational_burst_profile_ccc = -1; +static gint hf_rng_rsp_ss_mac_address = -1; +static gint hf_rng_rsp_basic_cid = -1; +static gint hf_rng_rsp_primary_mgmt_cid = -1; +static gint hf_rng_rsp_broadcast = -1; +static gint hf_rng_rsp_frame_number = -1; +static gint hf_rng_rsp_opportunity_number = -1; +static gint hf_rng_rsp_service_level_prediction = -1; +static gint hf_rng_rsp_resource_retain_flag = -1; +static gint hf_rng_rsp_ho_process_optimization = -1; +static gint hf_rng_rsp_ho_process_optimization_0 = -1; +static gint hf_rng_rsp_ho_process_optimization_1_2 = -1; +static gint hf_rng_rsp_ho_process_optimization_3 = -1; +static gint hf_rng_rsp_ho_process_optimization_4 = -1; +static gint hf_rng_rsp_ho_process_optimization_5 = -1; +static gint hf_rng_rsp_ho_process_optimization_6 = -1; +static gint hf_rng_rsp_ho_process_optimization_7 = -1; +static gint hf_rng_rsp_ho_process_optimization_8 = -1; +static gint hf_rng_rsp_ho_process_optimization_9 = -1; +static gint hf_rng_rsp_ho_process_optimization_10 = -1; +static gint hf_rng_rsp_ho_process_optimization_11 = -1; +static gint hf_rng_rsp_ho_process_optimization_12 = -1; +static gint hf_rng_rsp_ho_process_optimization_13 = -1; +static gint hf_rng_rsp_ho_process_optimization_14 = -1; +static gint hf_rng_rsp_ho_process_optimization_15 = -1; +/* Added the following to help implement RNG-RSP message encoding 33 (Table 367 in IEEE 802.16e-2007) */ +static gint hf_rng_rsp_dl_op_burst_profile_ofdma = -1; +static gint hf_rng_rsp_least_robust_diuc = -1; +static gint hf_rng_rsp_repetition_coding_indication = -1; +static gint hf_rng_rsp_config_change_count_of_dcd = -1; +/* Added the following to help implement RNG-RSP message encoding 22 (Table 367 in IEEE 802.16e-2007) */ +static gint hf_rng_rsp_ho_id = -1; +static gint hf_rng_rsp_location_update_response = -1; +/* Added the following to help implement RNG-RSP message encoding 24 (Table 367 in IEEE 802.16e-2007) */ +static gint hf_rng_rsp_paging_information = -1; +static gint hf_rng_rsp_paging_cycle = -1; +static gint hf_rng_rsp_paging_offset = -1; +static gint hf_rng_rsp_paging_group_id = -1; +static gint hf_rng_rsp_bs_random = -1; +static gint hf_rng_rsp_akid = -1; +static gint hf_rng_rsp_ranging_subchan = -1; +static gint hf_rng_rsp_time_symbol_reference = -1; +static gint hf_rng_rsp_subchannel_reference = -1; +static gint hf_rng_rsp_ranging_code_index = -1; +static gint hf_rng_rsp_frame_number2 = -1; +static gint hf_tlv_type = -1; +/* static gint hf_tlv_value = -1; */ +static gint hf_rng_invalid_tlv = -1; + +/* STRING RESOURCES */ + +static const true_false_string tfs_rng_rsp_aas_broadcast = { + "SS shall not issue contention-based Bandwidth Request", + "SS may issue contention-based Bandwidth Request" +}; + +static const true_false_string tfs_rng_rsp_resource_retain_flag = { + "Retained by the BS", + "Deleted by the BS" +}; + +static const value_string vals_rng_rsp_ranging_status[] = { + {1, "continue"}, + {2, "abort"}, + {3, "success"}, + {4, "rerange"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_level_of_service[] = { + {0, "No service possible for this MS"}, + {1, "Some service is available for one or" + " several service flows authorized for the MS"}, + {2, "For each authorized service flow, a MAC" + " connection can be established with QoS" + " specified by the AuthorizedQoSParamSet"}, + {3, "No service level prediction available"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_0[] = { + {0, "SBC-REQ management messages during current re-entry" + " processing required"}, + {1, "Omit SBC-REQ management messages during current" + " re-entry processing"}, + {0, NULL}, +}; + +static const value_string vals_rng_rsp_ho_process_optimization_1_2[] = { + {0, "Perform re-authentication and SA-TEK 3-way handshake." + " BS should include SA-TEK-Update TLV in the" + " SA-TEK-Response message. In addition, the RNG-RSP" + " message does not include SA-TEK-Update TLV or SA" + " Challenge Tuple TLV."}, + {1, "SA-TEK-Update TLV is included in the RNG-RSP message." + " In this case, SA-TEK 3-way handshake is avoided and" + " SA Challenge Tuple TLV shall not be included in the" + " RNG-RSP message."}, + {2, "Reserved"}, + {3, "Re-authentication and SA-TEK 3-way handshake is not" + " performed. The RNG-RSP message does not include" + " SA-TEK-Update TLV nor SA Challenge Tuple TLV. All the" + " TEKs received from the serving BS are reused"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_3[] = { + {0, "Network Address Acquisition management messages during" + " current reentry processing required"}, + {1, "Omit Network Address Acquisition management messages" + " during current reentry processing"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_4[] = { + {0, "Time of Day Acquisition management messages during" + " current reentry processing required"}, + {1, "Omit Time of Day Acquisition management messages" + " during current reentry processing"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_5[] = { + {0, "TFTP management messages during current re-entry" + " processing required"}, + {1, "Omit TFTP management messages during current re-entry" + " processing"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_6[] = { + {0, "Full service and operational state transfer or sharing" + " between Serving BS and Target BS required"}, + {1, "Omit Full service and operational state transfer or" + " sharing between Serving BS and Target BS"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_7[] = { + {0, "REG-REQ management message during current re-entry" + " processing required"}, + {1, "Omit REG-REQ management message during current re-entry" + " processing"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_8[] = { + {0, "BS shall send not send an unsolicited SBC-RSP" + " management message"}, + {1, "BS shall send an unsolicited SBC-RSP management message"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_9[] = { + {0, "No post-HO re-entry MS DL data pending at target BS"}, + {1, "post-HO re-entry MS DL data pending at target BS"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_10[] = { + {0, "BS shall not send an unsolicited REG-RSP management" + " message"}, + {1, "BS shall send an unsolicited REG-RSP management message"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_11[] = { + {0, "(Target) BS does not support virtual SDU SN"}, + {1, "(Target} BS supports virtual SDU SN"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_12[] = { + {0, "MS shall not send a notification of MS's successful" + " re-entry registration"}, + {1, "MS shall send a notification of MS's successful" + " re-entry registration"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_ho_process_optimization_13[] = { + {0, "MS shall not trigger a higher layer protocol required" + " to refresh its traffic IP address"}, + {1, "MS shall trigger a higher layer protocol required to" + " refresh its traffic IP address"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_repetition_coding_indication[] = { + {0, "No repetition coding"}, + {1, "Repetition coding of 2"}, + {2, "Repetition coding of 4"}, + {3, "Repetition coding of 6"}, + {0, NULL} +}; + +static const value_string vals_rng_rsp_location_update_response[] = { + {0, "Success of Location Update"}, + {1, "Failure of Location Update"}, + {3, "Success of location update and DL traffic pending"}, + {4, "Reserved"}, + {0, NULL} +}; + + +/* Decode RNG-RSP messages. */ +static int dissect_mac_mgmt_msg_rng_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_item *ranging_status_item = NULL; + proto_item *dl_freq_override_item = NULL; + proto_item *ss_mac_address_item = NULL; + proto_item *frame_number_item = NULL; + proto_item *opportunity_number_item = NULL; + + guint offset = 0; + guint tlv_offset; + guint tvb_len; + proto_item *rng_rsp_item, *sub_item; + proto_item *tlv_item = NULL; + proto_tree *rng_rsp_tree; + proto_tree *sub_tree = NULL; + tlv_info_t tlv_info; + gint tlv_type; + guint tlv_len; + guint this_offset = 0; + tlv_info_t sub_tlv_info; + gint sub_tlv_type; + gint sub_tlv_len; + guint sub_tlv_offset; + float timing_adjust; + float power_level_adjust; + + { /* we are being asked for details */ + + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type RNG-RSP */ + rng_rsp_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_rng_rsp_decoder, tvb, offset, tvb_len, "MAC Management Message, RNG-RSP"); + /* add MAC RNG-RSP subtree */ + rng_rsp_tree = proto_item_add_subtree(rng_rsp_item, ett_mac_mgmt_msg_rng_rsp_decoder); + + proto_tree_add_item(rng_rsp_tree, hf_rng_req_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + while(offset < tvb_len) + { + /* Get the TLV data. */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RNG-RSP TLV error"); + proto_tree_add_item(rng_rsp_tree, hf_rng_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the offset to the TLV data */ + tlv_offset = offset + get_tlv_value_offset(&tlv_info); + + switch (tlv_type) { + case RNG_RSP_TIMING_ADJUST: { + sub_tree = add_tlv_subtree_no_item(&tlv_info, rng_rsp_tree, hf_rng_rsp_timing_adjust, tvb, offset); + timing_adjust = (float)(tvb_get_ntohl(tvb, tlv_offset) / 4.0); + tlv_item = proto_tree_add_float_format_value(sub_tree, hf_rng_rsp_timing_adjust, tvb, + tlv_offset, 4, timing_adjust, " %.2f modulation symbols", timing_adjust); + if ((timing_adjust < -2) || (timing_adjust > 2)) + proto_item_append_text(tlv_item, " (during periodic ranging shall not exceed +- 2)"); + break; + } + case RNG_RSP_POWER_LEVEL_ADJUST: { + sub_tree = add_tlv_subtree_no_item(&tlv_info, rng_rsp_tree, hf_rng_rsp_power_level_adjust, tvb, offset); + power_level_adjust = (float)(tvb_get_guint8(tvb, tlv_offset) / 4.0); + proto_tree_add_float_format_value(sub_tree, hf_rng_rsp_power_level_adjust, tvb, tlv_offset, 1, + power_level_adjust, " %.2f dB", power_level_adjust); + break; + } + case RNG_RSP_OFFSET_FREQ_ADJUST: { + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_offset_freq_adjust, tvb, offset, ENC_BIG_ENDIAN); + break; + } + case RNG_RSP_RANGING_STATUS: + ranging_status_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_ranging_status, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_DL_FREQ_OVERRIDE: { + dl_freq_override_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_dl_freq_override, tvb, offset, ENC_BIG_ENDIAN); + break; + } + case RNG_RSP_UL_CHANNEL_ID_OVERRIDE: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_ul_chan_id_override, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_DL_OPERATIONAL_BURST_PROFILE: + sub_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_dl_operational_burst_profile, tvb, offset, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_rng_rsp_message_tree); + proto_tree_add_item(sub_tree, hf_rng_rsp_dl_operational_burst_profile_diuc, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_dl_operational_burst_profile_ccc, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + break; + case RNG_RSP_SS_MAC_ADDRESS: + if (tlv_len == 6) + { + ss_mac_address_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_ss_mac_address, tvb, offset, ENC_NA); + } else { + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_invalid_tlv, tvb, offset, ENC_NA); + } + break; + case RNG_RSP_BASIC_CID: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_basic_cid, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_PRIMARY_MGMT_CID: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_primary_mgmt_cid, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_AAS_BROADCAST_PERMISSION: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_broadcast, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_FRAME_NUMBER: + frame_number_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_frame_number, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_OPPORTUNITY_NUMBER: + opportunity_number_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_opportunity_number, tvb, offset, ENC_BIG_ENDIAN); + if (tvb_get_ntohl(tvb, tlv_offset) == 0) + proto_item_append_text(opportunity_number_item, " (may not be 0!)"); + break; + case RNG_RSP_SERVICE_LEVEL_PREDICTION: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_service_level_prediction, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_RESOURCE_RETAIN_FLAG: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_resource_retain_flag, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_HO_PROCESS_OPTIMIZATION: + sub_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_ho_process_optimization, tvb, offset, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_rng_rsp_message_tree); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_0, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_1_2, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_3, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_4, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_5, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_6, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_7, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_8, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_9, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_10, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_11, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_12, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_13, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_14, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ho_process_optimization_15, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + break; + case RNG_RSP_SBC_RSP_ENCODINGS: + sub_tree = add_protocol_subtree(&tlv_info, ett_rng_rsp_message_tree, rng_rsp_tree, proto_mac_mgmt_msg_rng_rsp_decoder, tvb, offset, tlv_len, "SBC-RSP Encodings"); + call_dissector(sbc_rsp_handle, tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, sub_tree); + break; + case RNG_RSP_REG_RSP_ENCODINGS: + sub_tree = add_protocol_subtree(&tlv_info, ett_rng_rsp_message_tree, rng_rsp_tree, proto_mac_mgmt_msg_rng_rsp_decoder, tvb, offset, tlv_len, "REG-RSP Encodings"); + call_dissector(reg_rsp_handle, tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, sub_tree); + break; + /* Implemented message encoding 33 (Table 367 in IEEE 802.16e-2007) */ + case RNG_RSP_DL_OP_BURST_PROFILE_OFDMA: + sub_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_dl_op_burst_profile_ofdma, tvb, offset, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_rng_rsp_message_tree); + proto_tree_add_item(sub_tree, hf_rng_rsp_least_robust_diuc, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_repetition_coding_indication, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_config_change_count_of_dcd, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + break; + case RNG_RSP_HO_ID: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_ho_id, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_LOCATION_UPDATE_RESPONSE: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_location_update_response, tvb, offset, ENC_BIG_ENDIAN); + break; + case RNG_RSP_PAGING_INFORMATION: + sub_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_paging_information, tvb, offset, ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_rng_rsp_message_tree); + proto_tree_add_item(sub_tree, hf_rng_rsp_paging_cycle, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_paging_offset, tvb, tlv_offset+2, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_paging_group_id, tvb, tlv_offset+3, 2, ENC_BIG_ENDIAN); + break; + case RNG_RSP_POWER_SAVING_CLASS_PARAMETERS: + sub_tree = add_protocol_subtree(&tlv_info, ett_rng_rsp_message_tree, rng_rsp_tree, proto_mac_mgmt_msg_rng_rsp_decoder, tvb, offset, tlv_len, "Power Saving Class Parameters"); + dissect_power_saving_class(sub_tree, tlv_type, tvb, tlv_len, pinfo, tlv_offset); + break; + case RNG_RSP_SA_CHALLENGE_TUPLE: + /* Display SA Challenge Tuple header */ + sub_tree = add_protocol_subtree(&tlv_info, ett_rng_rsp_message_tree, rng_rsp_tree, proto_mac_mgmt_msg_rng_rsp_decoder, tvb, offset, tlv_len, "SA Challenge Tuple"); + /* add subtree */ + /* Use a local copy of tlv_offset */ + this_offset = tlv_offset; + while(this_offset < tlv_len) { + /* Get the sub TLV data. */ + init_tlv_info(&sub_tlv_info, tvb, this_offset); + /* get the sub TLV type */ + sub_tlv_type = get_tlv_type(&sub_tlv_info); + /* get the TLV length */ + sub_tlv_len = get_tlv_length(&sub_tlv_info); + if(tlv_type == -1 || sub_tlv_len > MAX_TLV_LEN || sub_tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RNG-RSP TLV error"); + proto_tree_add_item(rng_rsp_tree, hf_rng_invalid_tlv, tvb, tlv_offset, (tvb_len - tlv_offset), ENC_NA); + break; + } + /* get the offset to the sub TLV data */ + sub_tlv_offset = this_offset + get_tlv_value_offset(&sub_tlv_info); + switch (sub_tlv_type) { + case RNG_RSP_SA_CHALLENGE_BS_RANDOM: + add_tlv_subtree(&sub_tlv_info, sub_tree, hf_rng_rsp_bs_random, tvb, this_offset, ENC_NA); + break; + case RNG_RSP_SA_CHALLENGE_AKID: + add_tlv_subtree(&sub_tlv_info, sub_tree, hf_rng_rsp_akid, tvb, this_offset, ENC_NA); + break; + default: + add_tlv_subtree(&sub_tlv_info, sub_tree, hf_tlv_type, tvb, this_offset, ENC_NA); + break; + } + this_offset = sub_tlv_len + sub_tlv_offset; + } + break; + case DSx_UPLINK_FLOW: + /* display Uplink Service Flow Encodings info */ + /* add subtree */ + sub_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_rng_rsp_decoder, rng_rsp_tree, proto_mac_mgmt_msg_rng_rsp_decoder, tvb, offset, tlv_len, "Uplink QOS Parameters"); + /* decode and display the DL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, sub_tree); + break; + case DSx_DOWNLINK_FLOW: + /* display Downlink Service Flow Encodings info */ + /* add subtree */ + sub_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_rng_rsp_decoder, rng_rsp_tree, proto_mac_mgmt_msg_rng_rsp_decoder, tvb, offset, tlv_len, "Downlink QOS Parameters"); + /* decode and display the DL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, tlv_offset, tlv_len), pinfo, sub_tree); + break; + case RNG_RSP_RANGING_CODE_ATTRIBUTES: + /* case SHORT_HMAC_TUPLE: */ + sub_item = add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_rng_rsp_ranging_subchan, tvb, offset, ENC_BIG_ENDIAN); + sub_tree = proto_item_add_subtree(sub_item, ett_rng_rsp_message_tree); + proto_tree_add_item(sub_tree, hf_rng_rsp_time_symbol_reference, tvb, tlv_offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_subchannel_reference, tvb, tlv_offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_ranging_code_index, tvb, tlv_offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_rng_rsp_frame_number2, tvb, tlv_offset, 4, ENC_BIG_ENDIAN); + break; + case SHORT_HMAC_TUPLE_COR2: + if (include_cor2_changes) { + sub_tree = add_protocol_subtree(&tlv_info, ett_rng_rsp_message_tree, rng_rsp_tree, proto_mac_mgmt_msg_rng_rsp_decoder, tvb, offset, tlv_len, "Short HMAC Tuple"); + wimax_short_hmac_tuple_decoder(sub_tree, tvb, tlv_offset, tvb_len - offset); + } else { + /* Unknown TLV type */ + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_tlv_type, tvb, offset, ENC_NA); + } + break; + + default: + add_tlv_subtree(&tlv_info, rng_rsp_tree, hf_tlv_type, tvb, offset, ENC_NA); + break; + + } + offset = tlv_len + tlv_offset; + } /* end of TLV process while loop */ + /* + * XXX - these should probably be expert info items. + */ + if (ranging_status_item && dl_freq_override_item) + proto_item_append_text(ranging_status_item, " (shall be set to 2 because Downlink Frequency Override is present)"); + if (ss_mac_address_item && frame_number_item) { + proto_item_append_text(frame_number_item, " (mutually exclusive with SS MAC Address!)"); + proto_item_append_text(ss_mac_address_item, " (mutually exclusive with Frame Number!)"); + } + if (ss_mac_address_item && opportunity_number_item) { + proto_item_append_text(opportunity_number_item, " (mutually exclusive with SS MAC Address!)"); + proto_item_append_text(ss_mac_address_item, " (mutually exclusive with Initial Ranging Opportunity Number!)"); + } + if (!ranging_status_item) + proto_item_append_text(rng_rsp_tree, " (Ranging status is missing!)"); + + } + return tvb_captured_length(tvb); +} + + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_rng_rsp(void) +{ + /* RNG-RSP fields display */ + static hf_register_info hf[] = + { + { + &hf_rng_rsp_broadcast, + { + "AAS broadcast permission", "wmx.rng_rsp.aas_broadcast", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_rng_rsp_aas_broadcast), 0x0, NULL, HFILL + } + }, + { + &hf_rng_rsp_akid, + { + "AKId", "wmx.rng_rsp.akid", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_basic_cid, + { + "Basic CID", "wmx.rng_rsp.basic_cid", + FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_bs_random, + { + "BS_Random", "wmx.rng_rsp.bs_random", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_config_change_count_of_dcd, + { + "Configuration Change Count value of DCD defining DIUC associated burst profile", "wmx.rng_rsp.config_change_count_of_dcd", + FT_UINT16, BASE_HEX, NULL, 0xFF00, NULL, HFILL + } + }, + { + &hf_rng_rsp_dl_freq_override, + { + "Downlink Frequency Override", "wmx.rng_rsp.dl_freq_override", + FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_hz, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_dl_operational_burst_profile_ccc, + { + "CCC value of DCD defining the burst profile associated with DIUC", "wmx.rng_rsp.dl_op_burst_prof.ccc", + FT_UINT16, BASE_DEC, NULL, 0x00FF, NULL, HFILL + } + }, + { + &hf_rng_rsp_dl_operational_burst_profile_diuc, + { + "The least robust DIUC that may be used by the BS for transmissions to the SS", "wmx.rng_rsp.dl_op_burst_prof.diuc", + FT_UINT16, BASE_DEC, NULL, 0xFF00, NULL, HFILL + } + }, + { + &hf_rng_rsp_dl_operational_burst_profile, + { + "Downlink Operational Burst Profile", "wmx.rng_rsp.dl_op_burst_profile", + FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + /* Added the following to help implement RNG-RSP message encoding 33 (Table 367 in IEEE 802.16e-2007) */ + { + &hf_rng_rsp_dl_op_burst_profile_ofdma, + { + "Downlink Operational Burst Profile for OFDMA", "wmx.rng_rsp.dl_op_burst_profile_ofdma", + FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_frame_number2, + { + "The 8 least significant bits of the frame number of the OFDMA frame where the SS sent the ranging code", "wmx.rng_rsp.eight_bit_frame_num", + FT_UINT32, BASE_DEC, NULL, 0x000000FF, NULL, HFILL + } + }, + { + &hf_rng_rsp_frame_number, + { + "Frame number", "wmx.rng_rsp.frame_number", + FT_UINT24, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + /* Added the following to help implement RNG-RSP message encoding 22 (IEEE 802.16e-2007) */ + { + &hf_rng_rsp_ho_id, + { + "HO ID", "wmx.rng_rsp.ho_id", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization, + { + "HO Process Optimization", "wmx.rng_rsp.ho_process_optimization", + FT_UINT16, BASE_HEX, NULL, 0x0000, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_0, + { + "Bit #0", "wmx.rng_rsp.ho_process_optimization.omit_sbc_req", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_0), 0x0001, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_1_2, + { + "Bits #1-2", "wmx.rng_rsp.ho_process_optimization.perform_reauthentication", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_1_2), 0x0006, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_3, + { + "Bit #3", "wmx.rng_rsp.ho_process_optimization.omit_network_address", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_3), 0x0008, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_4, + { + "Bit #4", "wmx.rng_rsp.ho_process_optimization.omit_time_of_day", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_4), 0x0010, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_5, + { + "Bit #5", "wmx.rng_rsp.ho_process_optimization.omit_tftp", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_5), 0x0020, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_6, + { + "Bit #6", "wmx.rng_rsp.ho_process_optimization.transfer_or_sharing", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_6), 0x0040, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_7, + { + "Bit #7", "wmx.rng_rsp.ho_process_optimization.omit_reg_req", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_7), 0x0080, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_8, + { + "Bit #8", "wmx.rng_rsp.ho_process_optimization.unsolicited_sbc_rsp", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_8), 0x0100, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_9, + { + "Bit #9", "wmx.rng_rsp.ho_process_optimization.post_ho_reentry", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_9), 0x0200, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_10, + { + "Bit #10", "wmx.rng_rsp.ho_process_optimization.unsolicited_reg_rsp", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_10), 0x0400, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_11, + { + "Bit #11", "wmx.rng_rsp.ho_process_optimization.virtual_sdu_sn", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_11), 0x0800, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_12, + { + "Bit #12", "wmx.rng_rsp.ho_process_optimization.send_notification", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_12), 0x1000, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_13, + { + "Bit #13", "wmx.rng_rsp.ho_process_optimization.trigger_higher_layer_protocol", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_ho_process_optimization_13), 0x2000, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_14, + { + "Bit #14: Reserved", "wmx.rng_rsp.ho_process_optimization.reserved", + FT_UINT16, BASE_HEX, NULL, 0x4000, NULL, HFILL + } + }, + { + &hf_rng_rsp_ho_process_optimization_15, + { + "Bit #15: Reserved", "wmx.rng_rsp.ho_process_optimization.reserved", + FT_UINT16, BASE_HEX, NULL, 0x8000, NULL, HFILL + } + }, + { + &hf_rng_invalid_tlv, + { + "Invalid TLV", "wmx.rng_rsp.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_rng_rsp_least_robust_diuc, + { + "Least Robust DIUC that may be used by the BS for transmissions to the MS", "wmx.rng_rsp.least_robust_diuc", + FT_UINT16, BASE_HEX, NULL, 0x000F, NULL, HFILL + } + }, + { + &hf_rng_rsp_location_update_response, + { + "Location Update Response", "wmx.rng_rsp.location_update_response", + FT_UINT8, BASE_DEC, VALS(vals_rng_rsp_location_update_response), 0xFF, NULL, HFILL + } + }, + { + &hf_rng_rsp_offset_freq_adjust, + { + "Offset Frequency Adjust", "wmx.rng_rsp.offset_freq_adjust", + FT_INT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_hz, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_opportunity_number, + { + "Initial ranging opportunity number", "wmx.rng_rsp.opportunity_number", + FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_paging_cycle, + { + "Paging Cycle", "wmx.rng_rsp.paging_cycle", + FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_paging_group_id, + { + "Paging Group ID", "wmx.rng_rsp.paging_group_id", + FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_paging_information, + { + "Paging Information", "wmx.rng_rsp.paging_information", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_paging_offset, + { + "Paging Offset", "wmx.rng_rsp.paging_offset", + FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_power_level_adjust, + { + "Power Level Adjust", "wmx.rng_rsp.power_level_adjust", + FT_FLOAT, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_primary_mgmt_cid, + { + "Primary Management CID", "wmx.rng_rsp.primary_mgmt_cid", + FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_ranging_code_index, + { + "The ranging code index that was sent by the SS", "wmx.rng_rsp.ranging_code_index", + FT_UINT32, BASE_DEC, NULL, 0x0000FF00, NULL, HFILL + } + }, + { + &hf_rng_rsp_ranging_status, + { + "Ranging status", "wmx.rng_rsp.ranging_status", + FT_UINT8, BASE_DEC, VALS(vals_rng_rsp_ranging_status), 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_ranging_subchan, + { + "Ranging code attributes", "wmx.rng_rsp.ranging_subchannel", + FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_repetition_coding_indication, + { + "Repetition Coding Indication", "wmx.rng_rsp.repetition_coding_indication", + FT_UINT16, BASE_HEX, VALS(vals_rng_rsp_repetition_coding_indication), 0x00F0, NULL, HFILL + } + }, + { + &hf_rng_req_reserved, + { + "Reserved", "wmx.rng_rsp.reserved", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_rng_rsp_resource_retain_flag, + { + "The connection information for the MS is", "wmx.rng_rsp.resource_retain_flag", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_rng_rsp_resource_retain_flag), 0x0, NULL, HFILL + } + }, + { + &hf_rng_rsp_service_level_prediction, + { + "Service Level Prediction", "wmx.rng_rsp.service_level_prediction", + FT_UINT8, BASE_DEC, VALS(vals_rng_rsp_level_of_service), 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_ss_mac_address, + { + "SS MAC Address", "wmx.rng_rsp.ss_mac_address", + FT_ETHER, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_rng_rsp_subchannel_reference, + { + "OFDMA subchannel reference used to transmit the ranging code", "wmx.rng_rsp.subchannel_reference", + FT_UINT32, BASE_DEC, NULL, 0x003f0000, NULL, HFILL + } + }, + { + &hf_rng_rsp_time_symbol_reference, + { + "OFDM time symbol reference used to transmit the ranging code", "wmx.rng_rsp.time_symbol_reference", + FT_UINT32, BASE_DEC, NULL, 0xFFC00000, NULL, HFILL + } + }, + { + &hf_rng_rsp_timing_adjust, + { + "Timing Adjust", "wmx.rng_rsp.timing_adjust", + FT_FLOAT, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, +#if 0 + { + &hf_rng_rsp_ul_channel_id, + { + "Uplink Channel ID", "wmx.rng_rsp.ul_chan_id", + FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, +#endif + { + &hf_rng_rsp_ul_chan_id_override, + { + "Uplink channel ID Override", "wmx.rng_rsp.ul_chan_id_override", + FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_tlv_type, + { + "Unknown TLV Type", "wmx.rng_rsp.unknown_tlv_type", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + }, +#if 0 + { + &hf_tlv_value, + { + "Value", "wmx.rng_rsp.tlv_value", + FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL + } + } +#endif + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_rng_rsp_decoder, + &ett_rng_rsp_message_tree + }; + + proto_mac_mgmt_msg_rng_rsp_decoder = proto_register_protocol ( + "WiMax RNG-RSP Messages", /* name */ + "WiMax RNG-RSP", /* short name */ + "wmx.rng_rsp" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_rng_rsp_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + rng_rsp_handle = register_dissector("mac_mgmt_msg_rng_rsp_handler", dissect_mac_mgmt_msg_rng_rsp_decoder, proto_mac_mgmt_msg_rng_rsp_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_rng_rsp(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_RNG_RSP, rng_rsp_handle); + + sbc_rsp_handle = find_dissector("mac_mgmt_msg_sbc_rsp_handler"); + reg_rsp_handle = find_dissector("mac_mgmt_msg_reg_rsp_handler"); +} + + +/* + * 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: + */ diff --git a/plugins/epan/wimax/msg_sbc.c b/plugins/epan/wimax/msg_sbc.c new file mode 100644 index 00000000..cfdc2393 --- /dev/null +++ b/plugins/epan/wimax/msg_sbc.c @@ -0,0 +1,2836 @@ +/* msg_sbc.c + * WiMax MAC Management SBC-REQ/RSP Messages decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#if 0 +#define DEBUG /* for debug only */ +#endif + +/* Include files */ + +#include "config.h" + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + + +void proto_register_mac_mgmt_msg_sbc(void); +void proto_reg_handoff_mac_mgmt_msg_sbc(void); + +static dissector_handle_t sbc_req_handle; +static dissector_handle_t sbc_rsp_handle; + +/* This is a global variable declared in mac_hd_generic_decoder.c, which determines whether + * or not cor2 changes are included */ +extern gboolean include_cor2_changes; + +static gint proto_mac_mgmt_msg_sbc_decoder = -1; +static gint ett_mac_mgmt_msg_sbc_decoder = -1; +static gint ett_sbc_req_tlv_subtree = -1; +static gint ett_sbc_rsp_tlv_subtree = -1; + +/* fix fields */ +static gint hf_sbc_unknown_type = -1; + +static gint hf_sbc_bw_alloc_support = -1; +static gint hf_sbc_bw_alloc_support_rsvd0 = -1; +static gint hf_sbc_bw_alloc_support_duplex = -1; +static gint hf_sbc_bw_alloc_support_rsvd1 = -1; +static gint hf_sbc_curr_transmit_power = -1; +static gint hf_sbc_transition_gaps = -1; +static gint hf_sbc_ssttg = -1; +static gint hf_sbc_ssrtg = -1; +static gint hf_sbc_mac_pdu = -1; +static gint hf_sbc_mac_pdu_piggybacked = -1; +static gint hf_sbc_mac_pdu_fsn = -1; +static gint hf_sbc_mac_pdu_rsvd = -1; +static gint hf_sbc_max_transmit_power = -1; +static gint hf_sbc_bpsk = -1; +static gint hf_sbc_qpsk = -1; +static gint hf_sbc_qam16 = -1; +static gint hf_sbc_qam64 = -1; +static gint hf_sbc_current_transmitted_power = -1; +static gint hf_sbc_ss_fft_sizes = -1; +static gint hf_sbc_ss_fft_256 = -1; +static gint hf_sbc_ss_fft_2048 = -1; +static gint hf_sbc_ss_fft_128 = -1; +static gint hf_sbc_ss_fft_512 = -1; +static gint hf_sbc_ss_fft_1024 = -1; +static gint hf_sbc_ss_cinr_measure_capability = -1; +static gint hf_sbc_ss_phy_cinr_measurement_preamble = -1; +static gint hf_sbc_ss_phy_cinr_measurement_permutation_zone_from_pilot_subcarriers = -1; +static gint hf_sbc_ss_phy_cinr_measurement_permutation_zone_from_data_subcarriers = -1; +static gint hf_sbc_ss_effective_cinr_measurement_preamble = -1; +static gint hf_sbc_ss_effective_cinr_measurement_permutation_zone_from_pilot_subcarriers = -1; +static gint hf_sbc_ss_effective_cinr_measurement_permutation_zone_from_data_subcarriers = -1; +static gint hf_sbc_ss_support_2_concurrent_cqi_channels = -1; +static gint hf_sbc_ss_frequency_selectivity_characterization_report = -1; + +static gint hf_sbc_ss_fft_rsvd1 = -1; +static gint hf_sbc_ss_fft_rsvd2 = -1; +static gint hf_sbc_ss_demodulator = -1; +static gint hf_sbc_ss_demodulator_64qam = -1; +static gint hf_sbc_ss_demodulator_btc = -1; +static gint hf_sbc_ss_demodulator_ctc = -1; +static gint hf_sbc_ss_demodulator_stc = -1; +static gint hf_sbc_ss_demodulator_cc_with_optional_interleaver = -1; +static gint hf_sbc_ss_demodulator_harq_chase = -1; +static gint hf_sbc_ss_demodulator_harq_ctc_ir = -1; +static gint hf_sbc_ss_demodulator_reserved = -1; +/* static gint hf_sbc_ss_demodulator_reserved1 = -1; */ +static gint hf_sbc_ss_demodulator_64qam_2 = -1; +static gint hf_sbc_ss_demodulator_btc_2 = -1; +static gint hf_sbc_ss_demodulator_ctc_2 = -1; +static gint hf_sbc_ss_demodulator_stc_2 = -1; +static gint hf_sbc_ss_demodulator_cc_with_optional_interleaver_2 = -1; +static gint hf_sbc_ss_demodulator_harq_chase_2 = -1; +static gint hf_sbc_ss_demodulator_harq_ctc_ir_2 = -1; +static gint hf_sbc_ss_demodulator_reserved_2 = -1; +static gint hf_sbc_ss_demodulator_harq_cc_ir_2 = -1; +static gint hf_sbc_ss_demodulator_ldpc_2 = -1; +static gint hf_sbc_ss_demodulator_dedicated_pilots_2 = -1; +static gint hf_sbc_ss_demodulator_reserved1_2 = -1; + +static gint hf_sbc_ss_modulator = -1; +static gint hf_sbc_ss_modulator_64qam = -1; +static gint hf_sbc_ss_modulator_btc = -1; +static gint hf_sbc_ss_modulator_ctc = -1; +static gint hf_sbc_ss_modulator_stc = -1; +static gint hf_sbc_ss_modulator_harq_chase = -1; +static gint hf_sbc_ss_modulator_ctc_ir = -1; +static gint hf_sbc_ss_modulator_cc_ir = -1; +static gint hf_sbc_ss_modulator_ldpc = -1; + +static gint hf_sbc_number_ul_arq_ack_channel = -1; +static gint hf_sbc_number_dl_arq_ack_channel = -1; +static gint hf_sbc_ss_permutation_support = -1; +static gint hf_sbc_ss_optimal_pusc = -1; +static gint hf_sbc_ss_optimal_fusc = -1; +static gint hf_sbc_ss_amc_1x6 = -1; +static gint hf_sbc_ss_amc_2x3 = -1; +static gint hf_sbc_ss_amc_3x2 = -1; +static gint hf_sbc_ss_amc_with_harq_map = -1; +static gint hf_sbc_ss_tusc1_support = -1; +static gint hf_sbc_ss_tusc2_support = -1; +static gint hf_sbc_ss_ofdma_aas_private = -1; +static gint hf_sbc_ofdma_aas_harq_map_capability = -1; +static gint hf_sbc_ofdma_aas_private_map_support = -1; +static gint hf_sbc_ofdma_aas_reduced_private_map_support = -1; +static gint hf_sbc_ofdma_aas_private_chain_enable = -1; +static gint hf_sbc_ofdma_aas_private_map_dl_frame_offset = -1; +static gint hf_sbc_ofdma_aas_private_ul_frame_offset = -1; +static gint hf_sbc_ofdma_aas_private_map_concurrency = -1; +static gint hf_sbc_ofdma_aas_capabilities = -1; +static gint hf_sbc_ss_ofdma_aas_zone = -1; +static gint hf_sbc_ss_ofdma_aas_diversity_map_scan = -1; +static gint hf_sbc_ss_ofdma_aas_fbck_rsp_support = -1; +static gint hf_sbc_ss_ofdma_downlink_aas_preamble = -1; +static gint hf_sbc_ss_ofdma_uplink_aas_preamble = -1; +static gint hf_sbc_ss_ofdma_aas_capabilities_rsvd = -1; + +static gint hf_sbc_tlv_t_167_association_type_support = -1; +static gint hf_sbc_tlv_t_167_association_type_support_bit0 = -1; +static gint hf_sbc_tlv_t_167_association_type_support_bit1 = -1; +static gint hf_sbc_tlv_t_167_association_type_support_bit2 = -1; +static gint hf_sbc_tlv_t_167_association_type_support_bit3 = -1; +static gint hf_sbc_tlv_t_167_association_type_support_bit4 = -1; +static gint hf_sbc_tlv_t_167_association_type_support_reserved = -1; +static gint hf_sbc_ofdma_ss_uplink_power_control_support = -1; +static gint hf_sbc_ofdma_ss_uplink_power_control_support_open_loop = -1; +static gint hf_sbc_ofdma_ss_uplink_power_control_support_aas_preamble = -1; +static gint hf_sbc_ofdma_ss_uplink_power_control_support_rsvd = -1; +/* static gint hf_sbc_ofdm_ss_minimum_num_of_frames = -1; */ +static gint hf_sbc_tlv_t_27_extension_capability = -1; +static gint hf_sbc_tlv_t_27_extension_capability_bit0 = -1; +static gint hf_sbc_tlv_t_27_extension_capability_reserved = -1; +static gint hf_sbc_tlv_t_28_ho_trigger_metric_support = -1; +static gint hf_sbc_tlv_t_28_ho_trigger_metric_support_bit0 = -1; +static gint hf_sbc_tlv_t_28_ho_trigger_metric_support_bit1 = -1; +static gint hf_sbc_tlv_t_28_ho_trigger_metric_support_bit2 = -1; +static gint hf_sbc_tlv_t_28_ho_trigger_metric_support_bit3 = -1; +static gint hf_sbc_tlv_t_28_ho_trigger_metric_support_reserved = -1; +static gint hf_sbc_tlv_t_171_minimum_num_of_frames = -1; +static gint hf_sbc_tlv_t_172_harq_map_capability = -1; +static gint hf_sbc_tlv_t_172_extended_harq_ie_capability = -1; +static gint hf_sbc_tlv_t_172_sub_map_capability_first_zone = -1; +static gint hf_sbc_tlv_t_172_sub_map_capability_other_zones = -1; +static gint hf_sbc_tlv_t_172_dl_region_definition_support = -1; +static gint hf_sbc_tlv_t_172_reserved = -1; +static gint hf_sbc_tlv_t_172 = -1; +static gint hf_sbc_tlv_t_173_ul_ctl_channel_support = -1; +static gint hf_sbc_tlv_t_173_3_bit_mimo_fast_feedback = -1; +static gint hf_sbc_tlv_t_173_enhanced_fast_feedback = -1; +static gint hf_sbc_tlv_t_173_ul_ack = -1; +static gint hf_sbc_tlv_t_173_reserved = -1; +static gint hf_sbc_tlv_t_173_uep_fast_feedback = -1; +static gint hf_sbc_tlv_t_173_measurement_report = -1; +static gint hf_sbc_tlv_t_173_primary_secondary_fast_feedback = -1; +static gint hf_sbc_tlv_t_173_diuc_cqi_fast_feedback = -1; +static gint hf_sbc_tlv_t_174_ofdma_ms_csit_capability = -1; +static gint hf_sbc_tlv_t_174_csit_compatibility_type_a = -1; +static gint hf_sbc_tlv_t_174_csit_compatibility_type_b = -1; +static gint hf_sbc_tlv_t_174_power_assignment_capability = -1; +static gint hf_sbc_tlv_t_174_sounding_rsp_time_capability = -1; +static gint hf_sbc_tlv_t_174_max_num_simultanous_sounding_instructions = -1; +static gint hf_sbc_tlv_t_174_ss_csit_type_a_support = -1; +static gint hf_sbc_tlv_t_204_ofdma_parameters_sets = -1; +static gint hf_sbc_tlv_t_204_ofdma_parameters_sets_phy_set_a = -1; +static gint hf_sbc_tlv_t_204_ofdma_parameters_sets_phy_set_b = -1; +static gint hf_sbc_tlv_t_204_ofdma_parameters_sets_harq_parameters_set = -1; +static gint hf_sbc_tlv_t_204_ofdma_parameters_sets_mac_set_a = -1; +static gint hf_sbc_tlv_t_204_ofdma_parameters_sets_mac_set_b = -1; +static gint hf_sbc_tlv_t_204_ofdma_parameters_sets_reserved = -1; +static gint hf_sbc_tlv_t_174_ss_csit_reserved = -1; +static gint hf_sbc_tlv_t_175_max_num_bst_per_frm_capability_harq = -1; +static gint hf_sbc_tlv_t_175_max_num_ul_harq_bst = -1; +static gint hf_sbc_tlv_t_175_max_num_ul_harq_per_frm_include_one_non_harq_bst = -1; +static gint hf_sbc_tlv_t_175_max_num_dl_harq_bst_per_harq_per_frm = -1; +static gint hf_sbc_tlv_t_176 = -1; +static gint hf_sbc_tlv_t_176_bit0 = -1; +static gint hf_sbc_tlv_t_176_bit1 = -1; +static gint hf_sbc_tlv_t_176_bit2 = -1; +/* static gint hf_sbc_tlv_t_176_bit2_cor2 = -1; */ +static gint hf_sbc_tlv_t_176_bit3 = -1; +static gint hf_sbc_tlv_t_176_bit4 = -1; +static gint hf_sbc_tlv_t_176_bit5 = -1; +static gint hf_sbc_tlv_t_176_bit6 = -1; +static gint hf_sbc_tlv_t_176_bit7 = -1; +static gint hf_sbc_tlv_t_176_bit8 = -1; +static gint hf_sbc_tlv_t_176_bit9 = -1; +static gint hf_sbc_tlv_t_176_bit10 = -1; +static gint hf_sbc_tlv_t_176_bit11 = -1; +static gint hf_sbc_tlv_t_176_bit12 = -1; +static gint hf_sbc_tlv_t_176_bit13 = -1; +static gint hf_sbc_tlv_t_176_bit14 = -1; +static gint hf_sbc_tlv_t_176_bit15 = -1; +static gint hf_sbc_tlv_t_176_bit16 = -1; +static gint hf_sbc_tlv_t_176_bit17 = -1; +static gint hf_sbc_tlv_t_176_bit18 = -1; +static gint hf_sbc_tlv_t_176_bit19 = -1; +static gint hf_sbc_tlv_t_176_reserved = -1; +static gint hf_sbc_tlv_t_177_ofdma_ss_modulator_for_mimo_support = -1; +static gint hf_sbc_tlv_t_177_stc_matrix_a = -1; +static gint hf_sbc_tlv_t_177_stc_matrix_b_vertical = -1; +static gint hf_sbc_tlv_t_177_stc_matrix_b_horizontal = -1; +static gint hf_sbc_tlv_t_177_two_transmit_antennas = -1; +static gint hf_sbc_tlv_t_177_capable_of_transmit_diversity = -1; +static gint hf_sbc_tlv_t_177_capable_of_spacial_multiplexing = -1; +static gint hf_sbc_tlv_t_177_beamforming = -1; +static gint hf_sbc_tlv_t_177_adaptive_rate_ctl = -1; +static gint hf_sbc_tlv_t_177_single_antenna = -1; +static gint hf_sbc_tlv_t_177_collaborative_sm_with_one_antenna = -1; +static gint hf_sbc_tlv_t_177_collaborative_sm_with_two_antennas = -1; +static gint hf_sbc_tlv_t_177_capable_of_two_antenna = -1; +static gint hf_sbc_tlv_t_177_rsvd = -1; +static gint hf_sbc_tlv_t_178_sdma_pilot_capability = -1; +static gint hf_sbc_tlv_t_178_sdma_pilot_pattern_support_for_amc_zone = -1; +static gint hf_sbc_tlv_t_178_reserved = -1; +static gint hf_sbc_tlv_t_179_ofdma_multiple_dl_burst_profile_support = -1; +static gint hf_sbc_tlv_t_179_dl_bst_profile_for_multiple_fec = -1; +static gint hf_sbc_tlv_t_179_ul_bst_profile_for_multiple_fec = -1; +static gint hf_sbc_tlv_t_179_reserved = -1; +static gint hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability = -1; +static gint hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_NEP = -1; +static gint hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_aggregation_flag_for_dl = -1; +static gint hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_aggregation_flag_for_ul = -1; +static gint hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_reserved1 = -1; +static gint hf_sbc_tlv_t_162_ul_harq_incremental_redundancy_buffer_capability_NEP = -1; +static gint hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_reserved2 = -1; +static gint hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability = -1; +static gint hf_sbc_tlv_t_163_dl_harq_buffering_capability_for_chase_combining = -1; +static gint hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_aggregation_flag_dl = -1; +static gint hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_reserved1 = -1; +static gint hf_sbc_tlv_t_163_ul_harq_buffering_capability_for_chase_combining = -1; +static gint hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_aggregation_flag_ul = -1; +static gint hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_reserved2 = -1; + +static gint hf_sbc_ss_demodulator_mimo_support = -1; +static gint hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_a = -1; +static gint hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_b_vertical = -1; +static gint hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_b_horizontal = -1; +static gint hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_a = -1; +static gint hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_b_vertical = -1; +static gint hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_b_horizontal = -1; +static gint hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_c_vertical = -1; +static gint hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_c_horizontal = -1; +static gint hf_sbc_ss_demodulator_mimo_rsvd = -1; +static gint hf_sbc_ss_mimo_uplink_support = -1; +static gint hf_sbc_ss_mimo_uplink_support_2_ann_sttd = -1; +static gint hf_sbc_ss_mimo_uplink_support_2_ann_sm_vertical = -1; +static gint hf_sbc_ss_mimo_uplink_support_1_ann_coop_sm = -1; +static gint hf_sbc_ss_mimo_uplink_support_rsvd = -1; + +static gint hf_sbc_power_save_class_types_capability = -1; +static gint hf_sbc_power_save_class_types_capability_bit0 = -1; +static gint hf_sbc_power_save_class_types_capability_bit1 = -1; +static gint hf_sbc_power_save_class_types_capability_bit2 = -1; +static gint hf_sbc_power_save_class_types_capability_bits34 = -1; +static gint hf_sbc_power_save_class_types_capability_bits567 = -1; + +static gint hf_sbc_pkm_flow_control = -1; +static gint hf_sbc_auth_policy = -1; +static gint hf_sbc_privacy_802_16 = -1; +static gint hf_sbc_privacy_rsvd = -1; +static gint hf_sbc_max_security_associations = -1; + +static gint hf_sbc_invalid_tlv = -1; + +static const true_false_string tfs_sbc_bw_alloc_support_duplex = +{ + "Full-Duplex", + "Half-Duplex" +}; + +#if 0 +static const value_string vals_sbc_mac_pdu_fsn[] = +{ + {0, "Only 11-bit FSN values are supported"}, + {1, "Only 3-bit FSN values are supported"}, + {0, NULL} +}; +#endif + +#if 0 +static const true_false_string tfs_sbc_mac_pdu_fsn = +{ + "Only 3-bit FSN values are supported", + "Only 11-bit FSN values are supported" +}; +#endif + +#if 0 +/* DCD DIUC messages (table 143) */ +static const value_string diuc_msgs[] = +{ + { 0, "Downlink Burst Profile 1" }, + { 1, "Downlink Burst Profile 2" }, + { 2, "Downlink Burst Profile 3" }, + { 3, "Downlink Burst Profile 4" }, + { 4, "Downlink Burst Profile 5" }, + { 5, "Downlink Burst Profile 6" }, + { 6, "Downlink Burst Profile 7" }, + { 7, "Downlink Burst Profile 8" }, + { 8, "Downlink Burst Profile 9" }, + { 9, "Downlink Burst Profile 10" }, + { 10, "Downlink Burst Profile 11" }, + { 11, "Downlink Burst Profile 12" }, + { 12, "Downlink Burst Profile 13" }, + { 13, "Reserved" }, + { 14, "Gap" }, + { 15, "End of DL-MAP" }, + {0, NULL} +}; +#endif + +#if 0 +static const value_string vals_sbc_type[] = +{ + {0, "CINR metric"}, + {1, "RSSI metric"}, + {2, "RTD metric"}, + {3, "Reserved"}, + {0, NULL} +}; +#endif + +#if 0 +static const value_string vals_sbc_function[] = +{ + {0, "Reserved"}, + {1, "Metric of neighbor BS is greater than absolute value"}, + {2, "Metric of neighbor BS is less than absolute value"}, + {3, "Metric of neighbor BS is greater than serving BS metric by relative value"}, + {4, "Metric of neighbor BS is less than serving BS metric by relative value"}, + {5, "Metric of serving BS greater than absolute value"}, + {6, "Metric of serving BS less than absolute value"}, + {7, "Reserved"}, + {0, NULL} +}; +#endif + +#if 0 +static const value_string vals_sbc_action[] = +{ + {0, "Reserved"}, + {1, "Respond on trigger with MOB_SCN-REP after the end of each scanning interval"}, + {2, "Respond on trigger with MOB_MSH-REQ"}, + {3, "On trigger, MS starts neighbor BS scanning process by sending MOB_SCN-REQ"}, + {4, "Reserved"}, + {0, NULL} +}; +#endif + +#if 0 +static const value_string vals_sbc_power_adjustmnt[] = +{ + {0, "Preserve Peak Power"}, + {1, "Preserve Mean Power"}, + {0, NULL} +}; +#endif + +#if 0 +static const true_false_string tfs_sbc_power_adjustment = +{ + "Preserve Mean Power", + "Preserve Peak Power" +}; +#endif + +#if 0 +static const value_string vals_reg_rsp_status[] = +{ + {0, "OK"}, + {1, "Message authentication failure"}, + {0, NULL} +}; +#endif + +#if 0 +static const value_string vals_sbc_burst_tcs[] = +{ + {0, "TCS disabled"}, + {1, "TCS enabled"}, + {0, NULL} +}; +#endif + +#if 0 +static const true_false_string tfs_sbc_burst_tcs = +{ + "TCS enabled", + "TCS disabled" +}; +#endif + +#if 0 +static const value_string vals_sbc_frame_duration[] = +{ + {0, "2.5"}, + {1, "4"}, + {2, "5"}, + {3, "8"}, + {4, "10"}, + {5, "12.5"}, + {6, "20"}, + {0, NULL} +}; +#endif + +#if 0 +static const value_string vals_sbc_mac_version[] = +{ + {1, "Conformance with IEEE Std 802.16-2001"}, + {2, "Conformance with IEEE Std 802.16c-2002 and its predecessors"}, + {3, "Conformance with IEEE Std 802.16a-2003 and its predecessors"}, + {4, "Conformance with IEEE Std 802.16-2004"}, + {5, "Conformance with IEEE Std 802.16-2004 and IEEE Std 802.16e-2005"}, + {6, "reserved"}, + {0, NULL} +}; +#endif + +#if 0 +static const value_string vals_sbc_burst_fec[] = +{ + { 0, "QPSK (CC) 1/2"}, + { 1, "QPSK (CC) 3/4"}, + { 2, "16-QAM (CC) 1/2"}, + { 3, "16-QAM (CC) 3/4"}, + { 4, "64-QAM (CC) 1/2"}, + { 5, "64-QAM (CC) 2/3"}, + { 6, "64-QAM (CC) 3/4"}, + { 7, "QPSK (BTC) 1/2"}, + { 8, "QPSK (BTC) 3/4 or 2/3"}, + { 9, "16-QAM (BTC) 3/5"}, + {10, "16-QAM (BTC) 4/5"}, + {11, "64-QAM (BTC) 2/3 or 5/8"}, + {12, "64-QAM (BTC) 5/6 or 4/5"}, + {13, "QPSK (CTC) 1/2"}, + {14, "Reserved"}, + {15, "QPSK (CTC) 3/4"}, + {16, "16-QAM (CTC) 1/2"}, + {17, "16-QAM (CTC) 3/4"}, + {18, "64-QAM (CTC) 1/2"}, + {19, "64-QAM (CTC) 2/3"}, + {20, "64-QAM (CTC) 3/4"}, + {21, "64-QAM (CTC) 5/6"}, + {22, "QPSK (ZT CC) 1/2"}, + {23, "QPSK (ZT CC) 3/4"}, + {24, "16-QAM (ZT CC) 1/2"}, + {25, "16-QAM (ZT CC) 3/4"}, + {26, "64-QAM (ZT CC) 1/2"}, + {27, "64-QAM (ZT CC) 2/3"}, + {28, "64-QAM (ZT CC) 3/4"}, + {29, "QPSK (LDPC) 1/2"}, + {30, "QPSK (LDPC) 2/3 A code"}, + {31, "16-QAM (LDPC) 3/4 A code"}, + {32, "16-QAM (LDPC) 1/2"}, + {33, "16-QAM (LDPC) 2/3 A code"}, + {34, "16-QAM (LDPC) 3/4 A code"}, + {35, "64-QAM (LDPC) 1/2"}, + {36, "64-QAM (LDPC) 2/3 A code"}, + {37, "64-QAM (LDPC) 3/4 A code"}, + {38, "QPSK (LDPC) 2/3 B code"}, + {39, "QPSK (LDPC) 3/4 B code"}, + {40, "16-QAM (LDPC) 2/3 B code"}, + {41, "16-QAM (LDPC) 3/4 B code"}, + {42, "64-QAM (LDPC) 2/3 B code"}, + {43, "64-QAM (LDPC) 3/4 B code"}, + {44, "QPSK (CC with optional interleaver) 1/2"}, + {45, "QPSK (CC with optional interleaver) 3/4"}, + {46, "16-QAM (CC with optional interleaver) 1/2"}, + {47, "16-QAM (CC optional interleaver) 0%00"}, + {48, "64-QAM (CC with optional interleaver) 2/3"}, + {49, "64-QAM (CC with optional interleaver) 3/4"}, + {50, "QPSK (LDPC) 5/6"}, + {51, "16-QAM (LDPC) 5/6"}, + {52, "64-QAM (LDPC) 5/6"}, + {0, NULL} +}; +#endif + +#if 0 +static const value_string vals_sbc_permutation_type[] = +{ + {0, "PUSC" }, + {1, "FUSC" }, + {2, "optional FUSC"}, + {3, "AMC"}, + {0, NULL} +}; +#endif + +static const value_string vals_sbc_harq_parameters_set[] = +{ + {0, "HARQ set 1"}, + {1, "HARQ set 2"}, + {2, "HARQ set 3"}, + {3, "HARQ set 4"}, + {4, "HARQ set 5"}, + {5, "Reserved"}, + {0, NULL} +}; + +static const true_false_string tfs_supported = +{ + "supported", + "not supported" +}; + +static const true_false_string tfs_yes_no_sbc = +{ + "yes", + "no" +}; + +static const value_string vals_sounding_rsp_time_cap_codings[] = +{ + {0, "0.5ms" }, + {1, "0.75ms" }, + {2, "1ms"}, + {3, "1.25ms"}, + {4, "1.5ms"}, + {5, "min(2, Next Frame)"}, + {6, "min(5, Next Frame)"}, + {7, "Next Frame"}, + {0, NULL} +}; + +static const value_string vals_sbc_sdma_str[ ] = +{ + {0, "no support"}, + {1, "support SDMA pilot patterns #A and #B"}, + {2, "support all SDMA pilot patterns"}, + {3, "reserved"}, + {0, NULL} +}; + + +static void sbc_tlv_decoder(tlv_info_t* tlv_info, int ett, proto_tree* sbc_tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint tlv_offset) +{ + proto_item *tlv_item, *ti; + proto_tree *tlv_tree; + gint tlv_type = get_tlv_type(tlv_info), + tlv_len = get_tlv_length(tlv_info), + value; + gfloat power_bpsk; + gfloat power_qpsk; + gfloat power_qam16; + gfloat power_qam64; + gfloat current_power; + + /* process SBC TLV Encoded information */ + switch (tlv_type) + { + case SBC_BW_ALLOC_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_bw_alloc_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_bw_alloc_support_rsvd0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_bw_alloc_support_duplex, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_bw_alloc_support_rsvd1, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TRANSITION_GAPS: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_transition_gaps, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + ti = proto_tree_add_item(tlv_tree, hf_sbc_ssttg, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti, " us (ranges: TDD 0-50; H-FDD 0-100)"); + ti = proto_tree_add_item(tlv_tree, hf_sbc_ssrtg, tvb, (offset + 1), 1, ENC_BIG_ENDIAN); + proto_item_append_text(ti, " us (ranges: TDD 0-50; H-FDD 0-100)"); + break; + case SBC_MAC_PDU: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_mac_pdu, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_mac_pdu_piggybacked, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_mac_pdu_fsn, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_mac_pdu_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_REQ_MAX_TRANSMIT_POWER: /* TODO: This TLV comes up as INVALID in wireshark... why? */ + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_max_transmit_power, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + power_bpsk = (gfloat)(tvb_get_guint8(tvb, offset) - 128) / 2; + power_qpsk = (gfloat)(tvb_get_guint8(tvb, (offset + 1)) - 128) / 2; + power_qam16 = (gfloat)(tvb_get_guint8(tvb, (offset + 2)) - 128) / 2; + power_qam64 = (gfloat)(tvb_get_guint8(tvb, (offset + 3)) - 128) / 2; + proto_tree_add_float_format_value(tlv_tree, hf_sbc_bpsk, tvb, offset, 1, power_bpsk, "%.2f dBm", (gdouble)power_bpsk); + proto_tree_add_float_format_value(tlv_tree, hf_sbc_qpsk, tvb, (offset + 1), 1, power_qpsk, "%.2f dBm", (gdouble)power_qpsk); + proto_tree_add_float_format_value(tlv_tree, hf_sbc_qam16, tvb, (offset + 2), 1, power_qam16, "%.2f dBm", (gdouble)power_qam16); + proto_tree_add_float_format_value(tlv_tree, hf_sbc_qam64, tvb, (offset + 3), 1, power_qam64, "%.2f dBm", (gdouble)power_qam64); + break; + case SBC_REQ_CURR_TRANSMITTED_POWER: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_curr_transmit_power, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + value = tvb_get_guint8(tvb, offset); + current_power = (gfloat)(value - 128) / 2; + proto_tree_add_float_format_value(tlv_tree, hf_sbc_current_transmitted_power, tvb, offset, 1, current_power, "%.2f dBm (Value: 0x%x)", (gdouble)current_power, value); + break; + case SBC_SS_FFT_SIZES: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ss_fft_sizes, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + if (include_cor2_changes) + { + proto_tree_add_item(tlv_tree, hf_sbc_ss_fft_rsvd1, tvb, offset, 1, ENC_BIG_ENDIAN); + } else { + proto_tree_add_item(tlv_tree, hf_sbc_ss_fft_256, tvb, offset, 1, ENC_BIG_ENDIAN); + } + proto_tree_add_item(tlv_tree, hf_sbc_ss_fft_2048, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_fft_128, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_fft_512, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_fft_1024, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_fft_rsvd2, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_SS_DEMODULATOR: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ss_demodulator, tvb, tlv_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + if (tlv_len == 1) /* && (num_dl_harq_chans < 8)) */ + { + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_64qam, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_btc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_ctc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_stc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_cc_with_optional_interleaver, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_harq_chase, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_harq_ctc_ir, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_64qam_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_btc_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_ctc_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_stc_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_cc_with_optional_interleaver_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_harq_chase_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_harq_ctc_ir_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_reserved_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_harq_cc_ir_2, tvb, offset , 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_ldpc_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_dedicated_pilots_2, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_reserved1_2, tvb, offset, 2, ENC_BIG_ENDIAN); + } + break; + case SBC_SS_MODULATOR: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ss_modulator, tvb, tlv_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_ss_modulator_64qam, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_modulator_btc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_modulator_ctc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_modulator_stc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_modulator_harq_chase, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_modulator_ctc_ir, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_modulator_cc_ir, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_modulator_ldpc, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_SS_NUM_UL_ARQ_ACK_CHANNEL: + /* add TLV subtree */ + add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_number_ul_arq_ack_channel, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case SBC_SS_NUM_DL_ARQ_ACK_CHANNEL: + /* add TLV subtree */ + add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_number_dl_arq_ack_channel, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case SBC_SS_PERMUTATION_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ss_permutation_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_ss_optimal_pusc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_optimal_fusc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_amc_1x6, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_amc_2x3, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_amc_3x2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_amc_with_harq_map, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_tusc1_support, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_tusc2_support, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_SS_DEMODULATOR_MIMO_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ss_demodulator_mimo_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_a, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_b_vertical, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_b_horizontal, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_a, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_b_vertical, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_b_horizontal, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_c_vertical, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_c_horizontal, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_demodulator_mimo_rsvd, tvb, offset, 2, ENC_BIG_ENDIAN); + break; + case SBC_SS_MIMO_UPLINK_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ss_mimo_uplink_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_ss_mimo_uplink_support_2_ann_sttd, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_mimo_uplink_support_2_ann_sm_vertical, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_mimo_uplink_support_1_ann_coop_sm, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_mimo_uplink_support_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_SS_OFDMA_AAS_PRIVATE_MAP_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ss_ofdma_aas_private, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_aas_harq_map_capability, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_aas_private_map_support, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_aas_reduced_private_map_support, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_aas_private_chain_enable, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_aas_private_map_dl_frame_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_aas_private_ul_frame_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_aas_private_map_concurrency, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_SS_OFDMA_AAS_CAPABILITIES: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ofdma_aas_capabilities, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_ss_ofdma_aas_zone, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_ofdma_aas_diversity_map_scan, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_ofdma_aas_fbck_rsp_support, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_ofdma_downlink_aas_preamble, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_ofdma_uplink_aas_preamble, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_ofdma_aas_capabilities_rsvd, tvb, offset, 2, ENC_BIG_ENDIAN); + break; + case SBC_SS_CINR_MEASUREMENT_CAPABILITY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ss_cinr_measure_capability, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_ss_phy_cinr_measurement_preamble, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_phy_cinr_measurement_permutation_zone_from_pilot_subcarriers, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_phy_cinr_measurement_permutation_zone_from_data_subcarriers, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_effective_cinr_measurement_preamble, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_effective_cinr_measurement_permutation_zone_from_pilot_subcarriers, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_effective_cinr_measurement_permutation_zone_from_data_subcarriers, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_support_2_concurrent_cqi_channels,tvb,offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ss_frequency_selectivity_characterization_report,tvb,offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_PKM_FLOW_CONTROL: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_pkm_flow_control, tvb, tlv_offset, ENC_BIG_ENDIAN); + if(tvb_get_guint8(tvb, offset) == 0) + proto_item_append_text(tlv_item, " (default - no limit)"); + break; + case SBC_AUTH_POLICY_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_auth_policy, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_privacy_802_16, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_privacy_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_MAX_SECURITY_ASSOCIATIONS: + add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_max_security_associations, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_27_EXTENSION_CAPABILITY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_27_extension_capability, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_27_extension_capability_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_27_extension_capability_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_28_HO_TRIGGER_METRIC_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_28_ho_trigger_metric_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_28_ho_trigger_metric_support_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_28_ho_trigger_metric_support_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_28_ho_trigger_metric_support_bit2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_28_ho_trigger_metric_support_bit3, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_28_ho_trigger_metric_support_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_167_ASSOCIATION_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_167_association_type_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_167_association_type_support_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_167_association_type_support_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_167_association_type_support_bit2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_167_association_type_support_bit3, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_167_association_type_support_bit4, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_167_association_type_support_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_170_UPLINK_POWER_CONTROL_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_ofdma_ss_uplink_power_control_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_ss_uplink_power_control_support_open_loop, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_ss_uplink_power_control_support_aas_preamble, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_ofdma_ss_uplink_power_control_support_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_171_MINIMUM_NUM_OF_FRAMES: + /* add TLV subtree */ + add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_171_minimum_num_of_frames, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_172: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_172, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_172_harq_map_capability, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_172_extended_harq_ie_capability, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_172_sub_map_capability_first_zone, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_172_sub_map_capability_other_zones, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_172_dl_region_definition_support, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_172_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_173_UL_CONTROL_CHANNEL_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_173_ul_ctl_channel_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_173_3_bit_mimo_fast_feedback, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_173_enhanced_fast_feedback, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_173_ul_ack, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_173_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_173_uep_fast_feedback, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_173_measurement_report, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_173_primary_secondary_fast_feedback, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_173_diuc_cqi_fast_feedback, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_174_OFDMA_MS_CSIT_CAPABILITY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_174_ofdma_ms_csit_capability, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_174_csit_compatibility_type_a, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_174_csit_compatibility_type_b, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_174_power_assignment_capability, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_174_sounding_rsp_time_capability, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_174_max_num_simultanous_sounding_instructions, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_174_ss_csit_type_a_support, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_174_ss_csit_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_175_MAX_NUM_BST_PER_FRM_CAPABILITY_HARQ: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_175_max_num_bst_per_frm_capability_harq, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_175_max_num_ul_harq_bst, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_175_max_num_ul_harq_per_frm_include_one_non_harq_bst, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_175_max_num_dl_harq_bst_per_harq_per_frm, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_176: /* TODO: Get an invalid TLV whenever this TLV is used. Could it be + that lengths above 2 cause this problem? */ + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_176, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit0, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit1, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit2, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit3, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit4, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit5, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit6, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit7, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit8, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit9, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit10, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit11, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit12, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit13, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit14, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit15, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit16, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit17, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit18, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_bit19, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_176_reserved, tvb, offset, 3, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_177_OFDMA_SS_MODULATOR_FOR_MIMO_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_177_ofdma_ss_modulator_for_mimo_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + if (include_cor2_changes) + { + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_stc_matrix_a, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_stc_matrix_b_vertical, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_stc_matrix_b_horizontal, tvb, offset, 1, ENC_BIG_ENDIAN); + } else { + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_two_transmit_antennas, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_capable_of_transmit_diversity, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_capable_of_spacial_multiplexing, tvb, offset, 1, ENC_BIG_ENDIAN); + } + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_beamforming, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_adaptive_rate_ctl, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_single_antenna, tvb, offset, 1, ENC_BIG_ENDIAN); + if (include_cor2_changes) + { + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_collaborative_sm_with_one_antenna, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_collaborative_sm_with_two_antennas, tvb, offset, 1, ENC_BIG_ENDIAN); + } else { + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_capable_of_two_antenna, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_177_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + } + break; + case SBC_TLV_T_178_SDMA_PILOT_CAPABILITY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_178_sdma_pilot_capability, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_178_sdma_pilot_pattern_support_for_amc_zone, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_178_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_179_OFDMA_MULTIPLE_DL_BURST_PROFILE_CAPABILITY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_179_ofdma_multiple_dl_burst_profile_support, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_179_dl_bst_profile_for_multiple_fec, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_179_ul_bst_profile_for_multiple_fec, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_179_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_204_OFDMA_PARAMETERS_SETS: + if (include_cor2_changes) + { + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_204_ofdma_parameters_sets, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_204_ofdma_parameters_sets_phy_set_a, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_204_ofdma_parameters_sets_phy_set_b, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_204_ofdma_parameters_sets_harq_parameters_set, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_204_ofdma_parameters_sets_mac_set_a, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_204_ofdma_parameters_sets_mac_set_b, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_204_ofdma_parameters_sets_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + } + break; + case SBC_TLV_T_162_HARQ_INCREMENTAL_REDUNDANCY_BUFFER_CAPABILITY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_NEP, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_aggregation_flag_for_dl, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_reserved1, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_162_ul_harq_incremental_redundancy_buffer_capability_NEP, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_aggregation_flag_for_ul, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN); + break; + case SBC_TLV_T_163_HARQ_CHASE_COMBINING_AND_CC_IR_BUFFER_CAPABILITY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_163_dl_harq_buffering_capability_for_chase_combining, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_aggregation_flag_dl, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_reserved1, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_163_ul_harq_buffering_capability_for_chase_combining, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_aggregation_flag_ul, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SECURITY_NEGOTIATION_PARAMETERS: + /* display Security Negotiation Parameters Title */ + /* add Security Negotiation Parameters subtree */ + tlv_tree = add_protocol_subtree(tlv_info, ett, sbc_tree, proto_mac_mgmt_msg_sbc_decoder, tvb, tlv_offset, tlv_len, "Security Negotiation Parameters"); + /* call the Security Negotiation Parameters decoder */ + wimax_security_negotiation_parameters_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case SBC_TLV_T_26_POWER_SAVE_CLASS_TYPES_CAPABILITY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_power_save_class_types_capability, tvb, tlv_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett); + /* display the detail meanings of the TLV value */ + proto_tree_add_item(tlv_tree, hf_sbc_power_save_class_types_capability_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_power_save_class_types_capability_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_power_save_class_types_capability_bit2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_power_save_class_types_capability_bits34, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sbc_power_save_class_types_capability_bits567, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + default: + /* add TLV subtree */ + add_tlv_subtree(tlv_info, sbc_tree, hf_sbc_unknown_type, tvb, tlv_offset, ENC_NA); + break; + } +} + +/* Wimax Mac SBC-REQ Message Dissector */ +static int dissect_mac_mgmt_msg_sbc_req_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len; + gint tlv_type, tlv_len, tlv_value_offset; + proto_item *sbc_item; + proto_tree *sbc_tree; + tlv_info_t tlv_info; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type SBC-REQ */ + sbc_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_sbc_decoder, tvb, offset, -1, "SS Basic Capability Request (SBC-REQ)"); + /* add MAC SBC subtree */ + sbc_tree = proto_item_add_subtree(sbc_item, ett_mac_mgmt_msg_sbc_decoder); + /* Decode and display the SS Basic Capability Request (SBC-REQ) */ + /* process the SBC TLVs */ + while(offset < tvb_len) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if (tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "SBC-REQ TLV error"); + proto_tree_add_item(sbc_tree, hf_sbc_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + if (tlv_type == 0) + { /* invalid tlv type */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid SBC TLV type"); + proto_tree_add_item(sbc_tree, hf_sbc_unknown_type, tvb, offset, 1, ENC_NA); + offset++; + continue; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(sbc_tree, proto_mac_mgmt_msg_sbc_decoder, tvb, offset, (tlv_len + tlv_value_offset), "SBC-REQ Type: %u (%u bytes, offset=%u, tlv_len=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tlv_len, tvb_len); +#endif + /* process SBC TLV Encoded information */ + sbc_tlv_decoder(&tlv_info, ett_sbc_req_tlv_subtree, sbc_tree, pinfo, tvb, offset+tlv_value_offset, offset); + + offset += (tlv_len+tlv_value_offset); + } /* end of TLV process while loop */ + } + return tvb_captured_length(tvb); +} + +/* Wimax Mac SBC-RSP Message Dissector */ +static int dissect_mac_mgmt_msg_sbc_rsp_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len; + gint tlv_type, tlv_len, tlv_value_offset; + proto_item *sbc_item; + proto_tree *sbc_tree; + tlv_info_t tlv_info; + + { /* we are being asked for details */ + /* Get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type SBC-RSP */ + sbc_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_sbc_decoder, tvb, offset, -1, "SS Basic Capability Response (SBC-RSP)"); + /* add MAC SBC subtree */ + sbc_tree = proto_item_add_subtree(sbc_item, ett_mac_mgmt_msg_sbc_decoder); + /* Decode and display the SS Basic Capability Response (SBC-RSP) */ + /* process the SBC TLVs */ + while(offset < tvb_len) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if (tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "SBC-RSP TLV error"); + proto_tree_add_item(sbc_tree, hf_sbc_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + if (tlv_type == 0) + { /* invalid tlv type */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid SBC TLV type"); + proto_tree_add_item(sbc_tree, hf_sbc_unknown_type, tvb, offset, 1, ENC_NA); + offset++; + continue; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(sbc_tree, proto_mac_mgmt_msg_sbc_decoder, tvb, offset, (tlv_len + tlv_value_offset), "SBC-RSP Type: %u (%u bytes, offset=%u, tlv_len=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tlv_len, tvb_len); +#endif + + /* process SBC TLV Encoded information */ + sbc_tlv_decoder(&tlv_info, ett_sbc_rsp_tlv_subtree, sbc_tree, pinfo, tvb, offset+tlv_value_offset, offset); + + offset += (tlv_len+tlv_value_offset); + } /* end of TLV process while loop */ + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac SBC-REQ/RSP Messages Dissectors */ +void proto_register_mac_mgmt_msg_sbc(void) +{ + /* SBC display */ + static hf_register_info hf_sbc[] = + { + { /* 11.8.8 */ + &hf_sbc_tlv_t_167_association_type_support, + { + "Association Type Support", "wmx.sbc.association_type_support", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_167_association_type_support_bit0, + { + "Scanning Without Association: association not supported", "wmx.sbc.association_type_support.bit0", + FT_BOOLEAN, 8, TFS(&tfs_yes_no_sbc), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_167_association_type_support_bit1, + { + "Association Level 0: scanning or association without coordination", "wmx.sbc.association_type_support.bit1", + FT_BOOLEAN, 8, TFS(&tfs_yes_no_sbc), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_167_association_type_support_bit2, + { + "Association Level 1: association with coordination", "wmx.sbc.association_type_support.bit2", + FT_BOOLEAN, 8, TFS(&tfs_yes_no_sbc), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_167_association_type_support_bit3, + { + "Association Level 2: network assisted association", "wmx.sbc.association_type_support.bit3", + FT_BOOLEAN, 8, TFS(&tfs_yes_no_sbc), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_167_association_type_support_bit4, + { + "Desired Association Support", "wmx.sbc.association_type_support.bit4", + FT_BOOLEAN, 8, TFS(&tfs_yes_no_sbc), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_167_association_type_support_reserved, + { + "Reserved", "wmx.sbc.association_type_support.reserved", + FT_UINT8, BASE_HEX, NULL, 0xE0, NULL, HFILL + } + }, + { /* 11.7.8.7 */ + &hf_sbc_auth_policy, + { + "Authorization Policy Support", "wmx.sbc.auth_policy", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_privacy_802_16, + { + "IEEE 802.16 Privacy", "wmx.sbc.auth_policy.802_16", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_privacy_rsvd, + { + "Reserved", "wmx.sbc.auth_policy.rsvd", + FT_UINT8, BASE_HEX, NULL, 0xFE, NULL, HFILL + } + }, + { /* 11.8.1 */ + &hf_sbc_bw_alloc_support, + { + "Bandwidth Allocation Support", "wmx.sbc.bw_alloc_support", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_sbc_bw_alloc_support_duplex, + { + "Duplex", "wmx.sbc.bw_alloc_support.duplex", + FT_BOOLEAN, 8, TFS(&tfs_sbc_bw_alloc_support_duplex), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_bw_alloc_support_rsvd0, + { + "Reserved", "wmx.sbc.bw_alloc_support.rsvd0", + FT_UINT8, BASE_HEX, NULL, 0x1, NULL, HFILL + } + }, + { + &hf_sbc_bw_alloc_support_rsvd1, + { + "Reserved", "wmx.sbc.bw_alloc_support.rsvd1", + FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL + } + }, + { + &hf_sbc_curr_transmit_power, + { + "Current transmitted power", "wmx.sbc.curr_transmit_power", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_sbc_ss_effective_cinr_measurement_preamble, + { + "Effective CINR Measurement For A Permutation Zone From Preamble", "wmx.sbc.effective_cinr_measure_permutation_zone_preamble", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_ss_effective_cinr_measurement_permutation_zone_from_pilot_subcarriers, + { + "Effective CINR Measurement For A Permutation Zone From Pilot Subcarriers", "wmx.sbc.effective_cinr_measure_permutation_zone.pilot_subcarriers", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ss_effective_cinr_measurement_permutation_zone_from_data_subcarriers, + { + "Effective CINR Measurement For A Permutation Zone From Data Subcarriers", "wmx.sbc.effective_cinr_measure_permutation_zone.data_subcarriers", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { /* 11.8.6 */ + &hf_sbc_tlv_t_27_extension_capability, + { + "Extension Capability", "wmx.sbc.extension_capability", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_27_extension_capability_bit0, + { + "Supported Extended Subheader Format", "wmx.sbc.extension_capability.bit0", + FT_BOOLEAN, 8, TFS(&tfs_yes_no_sbc), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_27_extension_capability_reserved, + { + "Reserved", "wmx.sbc.extension_capability.reserved", + FT_UINT8, BASE_HEX, NULL, 0xFE, NULL, HFILL + } + }, + { + &hf_sbc_ss_frequency_selectivity_characterization_report, + { + "Frequency Selectivity Characterization Report", "wmx.sbc.frequency_selectivity_characterization_report", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x80, NULL, HFILL + } + }, + { /* 11.8.3.7.19.2 */ + &hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability, + { + "HARQ Chase Combining And CC-IR Buffer Capability", "wmx.sbc.harq_chase_combining_and_cc_ir_buffer_capability", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_aggregation_flag_dl, + { + "Aggregation Flag For DL", "wmx.sbc.harq_chase_combining_and_cc_ir_buffer_capability.aggregation_flag_dl", + FT_UINT16, BASE_HEX, NULL, 0x40, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_aggregation_flag_ul, + { + "Aggregation Flag for UL", "wmx.sbc.harq_chase_combining_and_cc_ir_buffer_capability.aggregation_flag_ul", + FT_UINT16, BASE_HEX, NULL, 0x4000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_163_dl_harq_buffering_capability_for_chase_combining, + { + "Downlink HARQ Buffering Capability For Chase Combining (K)", "wmx.sbc.harq_chase_combining_and_cc_ir_buffer_capability.dl_harq_buffering_capability_for_chase_combining", + FT_UINT16, BASE_HEX, NULL, 0x3F, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_reserved1, + { + "Reserved", "wmx.sbc.harq_chase_combining_and_cc_ir_buffer_capability.reserved1", + FT_UINT16, BASE_HEX, NULL, 0x80, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_163_harq_chase_combining_and_cc_ir_buffer_capability_reserved2, + { + "Reserved", "wmx.sbc.harq_chase_combining_and_cc_ir_buffer_capability.reserved2", + FT_UINT16, BASE_HEX, NULL, 0x8000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_163_ul_harq_buffering_capability_for_chase_combining, + { + "Uplink HARQ buffering capability for chase combining (K)", "wmx.sbc.harq_chase_combining_and_cc_ir_buffer_capability.ul_harq_buffering_capability_for_chase_combining", + FT_UINT16, BASE_HEX, NULL, 0x3F00, NULL, HFILL + } + }, + { /* 11.8.3.7.19.1 */ + &hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability, + { + "HARQ Incremental Buffer Capability", "wmx.sbc.harq_incremental_redundancy_buffer_capability", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_aggregation_flag_for_dl, + { + "Aggregation Flag for DL", "wmx.sbc.harq_incremental_redundancy_buffer_capability.aggregation_flag_for_dl", + FT_UINT16, BASE_HEX, NULL, 0x10, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_aggregation_flag_for_ul, + { + "Aggregation Flag For UL", "wmx.sbc.harq_incremental_redundancy_buffer_capability.aggregation_flag_for_ul", + FT_UINT16, BASE_HEX, NULL, 0x1000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_NEP, + { + "NEP Value Indicating Downlink HARQ Buffering Capability For Incremental Redundancy CTC", "wmx.sbc.harq_incremental_redundancy_buffer_capability.dl_incremental_redundancy_ctc", + FT_UINT16, BASE_HEX, NULL, 0xF, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_reserved1, + { + "Reserved", "wmx.sbc.harq_incremental_redundancy_buffer_capability.reserved", + FT_UINT16, BASE_HEX, NULL, 0xE0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_162_harq_incremental_redundancy_buffer_capability_reserved2, + { + "Reserved", "wmx.sbc.harq_incremental_redundancy_buffer_capability.reserved2", + FT_UINT16, BASE_HEX, NULL, 0xE000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_162_ul_harq_incremental_redundancy_buffer_capability_NEP, + { + "NEP Value Indicating Uplink HARQ Buffering Capability For Incremental Redundancy CTC", "wmx.sbc.harq_incremental_redundancy_buffer_capability.ul_incremental_redundancy_ctc", + FT_UINT16,BASE_HEX, NULL, 0xF00, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_aas_harq_map_capability, + { + "H-ARQ MAP Capability", "wmx.sbc.harq_map_capability", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { /* 11.8.7 */ + &hf_sbc_tlv_t_28_ho_trigger_metric_support, + { + "HO Trigger Metric Support", "wmx.sbc.ho_trigger_metric_support", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_28_ho_trigger_metric_support_bit0, + { + "BS CINR Mean", "wmx.sbc.ho_trigger_metric_support.bit0", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_28_ho_trigger_metric_support_bit1, + { + "BS RSSI Mean", "wmx.sbc.ho_trigger_metric_support.bit1", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_28_ho_trigger_metric_support_bit2, + { + "BS Relative Delay", "wmx.sbc.ho_trigger_metric_support.bit2", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_28_ho_trigger_metric_support_bit3, + { + "BS RTD", "wmx.sbc.ho_trigger_metric_support.bit3", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_28_ho_trigger_metric_support_reserved, + { + "Reserved", "wmx.sbc.ho_trigger_metric_support.reserved", + FT_UINT8, BASE_HEX, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_sbc_invalid_tlv, + { + "Invalid TLV", "wmx.sbc.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 11.8.2 */ + &hf_sbc_mac_pdu, + { + "Capabilities For Construction And Transmission Of MAC PDUs", "wmx.sbc.mac_pdu", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_mac_pdu_piggybacked, + { + "Ability To Receive Requests Piggybacked With Data", "wmx.sbc.mac_pdu.bit0", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_mac_pdu_fsn, + { + "Ability To Use 3-bit FSN Values Used When Forming MAC PDUs On Non-ARQ Connections", "wmx.sbc.mac_pdu.bit1", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { /* 11.8.3.7.15 */ + &hf_sbc_tlv_t_175_max_num_bst_per_frm_capability_harq, + { + "Maximum Number Of Burst Per Frame Capability In HARQ", "wmx.sbc.max_num_bst_per_frm_capability_harq", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_175_max_num_dl_harq_bst_per_harq_per_frm, + { + "Maximum Numbers Of DL HARQ Bursts Per HARQ Enabled Of MS Per Frame (default(0)=1)", "wmx.sbc.max_num_bst_per_frm_capability_harq.max_num_dl_harq_bst_per_harq_per_frm", + FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_175_max_num_ul_harq_bst, + { + "Maximum Number Of UL HARQ Burst Per HARQ Enabled MS Per Frame (default(0)=1)", "wmx.sbc.max_num_bst_per_frm_capability_harq.max_num_ul_harq_bst", + FT_UINT8, BASE_DEC, NULL, 0x7, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_175_max_num_ul_harq_per_frm_include_one_non_harq_bst, + { + "Whether The Maximum Number Of UL HARQ Bursts Per Frame (i.e. Bits# 2-0) Includes The One Non-HARQ Burst", "wmx.sbc.max_num_bst_per_frm_capability_harq.max_num_ul_harq_per_frm_include_one_non_harq_bst", + FT_BOOLEAN, 8, TFS(&tfs_yes_no_sbc), 0x8, NULL, HFILL + } + }, + { /* 11.7.8.8 */ + &hf_sbc_max_security_associations, + { + "Maximum Number Of Security Association Supported By The SS", "wmx.sbc.max_security_associations", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { /* 11.8.3.7.2 - type 161 */ + &hf_sbc_number_dl_arq_ack_channel, + { + "The Number Of DL HARQ ACK Channel", "wmx.sbc.number_dl_arq_ack_channel", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { /* 11.8.3.7.3 - type 153 */ + &hf_sbc_number_ul_arq_ack_channel, + { + "The Number Of UL HARQ ACK Channel", "wmx.sbc.number_ul_arq_ack_channel", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { /* 11.8.3.7.8 */ + &hf_sbc_ofdma_aas_capabilities, + { + "OFDMA AAS Capability", "wmx.sbc.ofdma_aas_capability", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_ss_ofdma_aas_capabilities_rsvd, + { + "Reserved", "wmx.sbc.ofdma_aas_capabilities.rsvd", + FT_UINT16, BASE_HEX, NULL, 0xFFE0, NULL, HFILL + } + }, + { + &hf_sbc_ss_ofdma_aas_diversity_map_scan, + { + "AAS Diversity Map Scan (AAS DLFP)", "wmx.sbc.ofdma_aas_diversity_map_scan", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_ofdma_aas_fbck_rsp_support, + { + "AAS-FBCK-RSP Support", "wmx.sbc.ofdma_aas_fbck_rsp_support", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_ss_ofdma_aas_zone, + { + "AAS Zone", "wmx.sbc.ofdma_aas_zone", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_ss_ofdma_downlink_aas_preamble, + { + "Downlink AAS Preamble", "wmx.sbc.ofdma_downlink_aas_preamble", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { /* 11.8.3.7.5 - 3 bytes */ + &hf_sbc_tlv_t_176, + { + "OFDMA MS Demodulator For MIMO Support In DL", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl", + FT_BOOLEAN, BASE_NONE, TFS(&tfs_supported), 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit0, + { + "2-antenna STC Matrix A", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit0", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit1, + { + "2-antenna STC Matrix B, vertical coding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit1", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit2, + { + "Four Receive Antennas", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit2", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, +#if 0 + { + &hf_sbc_tlv_t_176_bit2_cor2, + { + "2-antenna STC matrix B, horizontal coding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit2", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, +#endif + { + &hf_sbc_tlv_t_176_bit3, + { + "4-antenna STC Matrix A", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit3", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit4, + { + "4-antenna STC Matrix B, vertical coding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit4", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit5, + { + "4-antenna STC Matrix B, horizontal coding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit5", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit6, + { + "4-antenna STC Matrix C, vertical coding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit6", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit7, + { + "4-antenna STC Matrix C, horizontal coding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit7", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x80, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit8, + { + "3-antenna STC Matrix A", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit8", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x100, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit9, + { + "3-antenna STC Matrix B", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit9", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x200, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit10, + { + "3-antenna STC Matrix C, vertical coding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit10", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x400, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit11, + { + "3-antenna STC Matrix C, horizontal coding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit11", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x800, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit12, + { + "Capable Of Calculating Precoding Weight", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit12", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x1000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit13, + { + "Capable Of Adaptive Rate Control", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit13", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x2000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit14, + { + "Capable Of Calculating Channel Matrix", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit14", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x4000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit15, + { + "Capable Of Antenna Grouping", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit15", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x8000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit16, + { + "Capable Of Antenna Selection", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit16", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x10000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit17, + { + "Capable Of Codebook Based Precoding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit17", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x20000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit18, + { + "Capable Of Long-term Precoding", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit18", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x40000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_bit19, + { + "Capable Of MIMO Midamble", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.bit19", + FT_BOOLEAN, 24, TFS(&tfs_supported), 0x80000, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_176_reserved, + { + "Reserved", "wmx.sbc.ofdma_ms_demodulator_for_mimo_support_in_dl.reserved", + FT_UINT24, BASE_HEX, NULL, 0xF00000, NULL, HFILL + } + }, + { /* 11.8.3.7.18 */ + &hf_sbc_tlv_t_179_ofdma_multiple_dl_burst_profile_support, + { + "OFDMA Multiple Downlink Burst Profile Capability", "wmx.sbc.ofdma_multiple_dl_burst_profile_support", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_179_dl_bst_profile_for_multiple_fec, + { + "Downlink burst profile for multiple FEC types", "wmx.sbc.ofdma_multiple_dl_burst_profile_support.dl_bst_profile_for_multiple_fec", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_179_reserved, + { + "Reserved", "wmx.sbc.ofdma_multiple_dl_burst_profile_support.reserved", + FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_179_ul_bst_profile_for_multiple_fec, + { + "Uplink burst profile for multiple FEC types", "wmx.sbc.ofdma_multiple_dl_burst_profile_support.ul_burst_profile_for_multiple_fec_types", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { /* 11.8.3.7.9 */ + &hf_sbc_ss_cinr_measure_capability, + { + "OFDMA SS CINR Measurement Capability", "wmx.sbc.ofdma_ss_cinr_measure_capability", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { /* 11.8.3.7.6 */ + &hf_sbc_ss_mimo_uplink_support, + { + "OFDMA SS MIMO uplink support", "wmx.sbc.ofdma_ss_mimo_uplink_support", + FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_sbc_ss_mimo_uplink_support_2_ann_sttd, + { + "2-antenna STTD", "wmx.sbc.ofdma_ss_mimo_uplink_support.2_antenna_sttd", + FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_sbc_ss_mimo_uplink_support_2_ann_sm_vertical, + { + "2-antenna SM with vertical coding", "wmx.sbc.ofdma_ss_mimo_uplink_support.2_antenna_sm_with_vertical_coding", + FT_UINT8, BASE_HEX, NULL, 0x02, NULL, HFILL + } + }, + { + &hf_sbc_ss_mimo_uplink_support_1_ann_coop_sm, + { + "Single-antenna cooperative SM", "wmx.sbc.ofdma_ss_mimo_uplink_support.single_antenna_coop_sm", + FT_UINT8, BASE_HEX, NULL, 0x04, NULL, HFILL + } + }, + { + &hf_sbc_ss_ofdma_uplink_aas_preamble, + { + "Uplink AAS Preamble", "wmx.sbc.ofdma_uplink_aas_preamble", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ss_phy_cinr_measurement_preamble, + { + "Physical CINR Measurement From The Preamble", "wmx.sbc.phy_cinr_measure_preamble", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_ss_phy_cinr_measurement_permutation_zone_from_pilot_subcarriers, + { + "Physical CINR Measurement For A Permutation Zone From Pilot Subcarriers", "wmx.sbc.phy_cinr_measure_permutation_zone.pilot_subcarriers", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_phy_cinr_measurement_permutation_zone_from_data_subcarriers, + { + "Physical CINR Measurement For A Permutation Zone From Data Subcarriers", "wmx.sbc.phy_cinr_measure_permutation_zone.data_subcarriers", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { /* 11.7.8.6 */ + &hf_sbc_pkm_flow_control, + { + "PKM Flow Control", "wmx.sbc.pkm_flow_control", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { /* 11.8.5 */ + &hf_sbc_power_save_class_types_capability, + { + "Power Save Class Types Capability", "wmx.sbc.power_save_class_types_capability", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_power_save_class_types_capability_bit0, + { + "Power Save Class Type I", "wmx.sbc.power_save_class_types_capability.bit0", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_power_save_class_types_capability_bit1, + { + "Power Save Class Type II", "wmx.sbc.power_save_class_types_capability.bit1", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_power_save_class_types_capability_bit2, + { + "Power Save Class Type III", "wmx.sbc.power_save_class_types_capability.bit2", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_power_save_class_types_capability_bits34, + { + "Number Of Power Save Class Type Instances Supported From Class Type I and II", "wmx.sbc.power_save_class_types_capability.bits34", + FT_UINT8, BASE_DEC, NULL, 0x18, NULL, HFILL + } + }, + { + &hf_sbc_power_save_class_types_capability_bits567, + { + "Number Of Power Save Class Type Instances Supported From Class Type III", "wmx.sbc.power_save_class_types_capability.bits567", + FT_UINT8, BASE_DEC, NULL, 0xE0, NULL, HFILL + } + }, + { /* 11.8.3.7.7 */ + &hf_sbc_ofdma_aas_private_chain_enable, + { + "Private Map Chain Enable", "wmx.sbc.private_chain_enable", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_aas_private_map_concurrency, + { + "Private Map Chain Concurrency", "wmx.sbc.private_map_concurrency", + FT_UINT8, BASE_HEX, NULL, 0xC0, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_aas_private_map_dl_frame_offset, + { + "Private Map DL Frame Offset", "wmx.sbc.private_map_dl_frame_offset", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_aas_private_map_support, + { + "Private Map Support", "wmx.sbc.private_map_support", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_ofdma_aas_private, + { + "OFDMA AAS Private Map Support", "wmx.sbc.private_map_support.ofdma_aas", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_aas_reduced_private_map_support, + { + "Reduced Private Map Support", "wmx.sbc.private_map_support.reduced", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_aas_private_ul_frame_offset, + { + "Private Map UL Frame Offset", "wmx.sbc.private_ul_frame_offset", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_mac_pdu_rsvd, + { + "Reserved", "wmx.sbc.mac_pdu.rsvd", + FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL + } + }, + { /* 11.8.3.2 */ + &hf_sbc_max_transmit_power, + { + "Maximum Transmit Power", "wmx.sbc.max_transmit_power", + FT_UINT32, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { + &hf_sbc_bpsk, + { + "BPSK", "wmx.sbc.bpsk", + FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_qpsk, + { + "QPSK", "wmx.sbc.qpsk", + FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_qam16, + { + "QAM16", "wmx.sbc.qam16", + FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_qam64, + { + "QAM64", "wmx.sbc.qam64", + FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_current_transmitted_power, + { + "Current Transmitted Power", "wmx.sbc.current_transmitted_power", + FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { /* 11.8.3.7.5 - 2 bytes */ + &hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_a, + { + "2-antenna STC Matrix A", "wmx.sbc.ss_demodulator.mimo.2.antenna.stc.matrix.a", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_b_horizontal, + { + "2-antenna STC Matrix B, horizontal coding", "wmx.sbc.ss_demodulator.mimo.2.antenna.stc.matrix.b.horizontal", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_2_ann_stc_matrix_b_vertical, + { + "2-antenna STC Matrix B, vertical coding", "wmx.sbc.ss_demodulator.mimo.2.antenna.stc.matrix.b.vertical", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_a, + { + "4-antenna STC Matrix A", "wmx.sbc.ss_demodulator.mimo.4.antenna.stc.matrix.a", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_b_horizontal, + { + "4-antenna STC Matrix B, horizontal coding", "wmx.sbc.ss_demodulator.mimo.4.antenna.stc.matrix.b.horizontal", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_b_vertical, + { + "4-antenna STC Matrix B, vertical coding", "wmx.sbc.ss_demodulator.mimo.4.antenna.stc.matrix.b.vertical", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_c_horizontal, + { + "4-antenna STC Matrix C, horizontal coding", "wmx.sbc.ss_demodulator.mimo.4.antenna.stc.matrix.c.horizontal", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x80, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_4_ann_stc_matrix_c_vertical, + { + "4-antenna STC Matrix C, vertical coding", "wmx.sbc.ss_demodulator.mimo.4.antenna.stc.matrix.c.vertical", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_rsvd, + { + "Reserved", "wmx.sbc.ss_demodulator.mimo.reserved", + FT_UINT16, BASE_HEX, NULL, 0xFF00, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_mimo_support, + { + "OFDMA SS Demodulator For MIMO Support", "wmx.sbc.ss_demodulator.mimo.support", + FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + /*11.8.3.7.11 ??? */ + { /* 11.8.3.7.12 - 170 */ + &hf_sbc_ofdma_ss_uplink_power_control_support, + { + "OFDMA SS uplink power control support", "wmx.sbc.ofdma_ss_uplink_power_control_support", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_ss_uplink_power_control_support_open_loop, + { + "Open loop", "wmx.sbc.ofdma_ss_uplink_power_control_support.open_loop", + FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_ss_uplink_power_control_support_aas_preamble, + { + "AAS preamble", "wmx.sbc.ofdma_ss_uplink_power_control_support.aas_preamble", + FT_UINT8, BASE_HEX, NULL, 0x02, NULL, HFILL + } + }, + { + &hf_sbc_ofdma_ss_uplink_power_control_support_rsvd, + { + "Reserved", "wmx.sbc.ofdma_ss_uplink_power_control_support.rsvd", + FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_172_dl_region_definition_support, + { + "DL Region Definition Support", "wmx.sbc.ofdma_map_capability.dl_region_definition_support", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { /* 11.8.3.7.12 - 172 */ + &hf_sbc_tlv_t_172, + { + "Support For Extended HARQ", "wmx.sbc.ofdma_map_capability.extended_harq", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_172_extended_harq_ie_capability, + { + "Extended HARQ IE Capability", "wmx.sbc.ofdma_map_capability.extended_harq_ie_capability", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_172_harq_map_capability, + { + "HARQ MAP Capability", "wmx.sbc.ofdma_map_capability.harq_map_capability", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { /* 11.8.3.7.12 - 171 */ + &hf_sbc_tlv_t_171_minimum_num_of_frames, + { + "The Minimum Number Of Frames That SS Takes To Switch From The Open Loop Power Control Scheme To The Closed Loop Power Control Scheme Or Vice Versa", "wmx.sbc.ofdma_ss_uplink_power_control_support.minimum_num_of_frames", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_172_reserved, + { + "Reserved", "wmx.sbc.ofdma_map_capability.reserved", + FT_UINT8, BASE_HEX, NULL, 0xE0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_172_sub_map_capability_first_zone, + { + "Sub MAP Capability For First Zone", "wmx.sbc.ofdma_map_capability.sub_map_capability_first_zone", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_172_sub_map_capability_other_zones, + { + "Sub MAP Capability For Other Zones", "wmx.sbc.ofdma_map_capability.sub_map_capability_other_zones", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { /* 11.8.3.7.14 */ + &hf_sbc_tlv_t_174_ofdma_ms_csit_capability, + { + "OFDMA MS CSIT Capability", "wmx.sbc.ofdma_ms_csit_capability", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_174_csit_compatibility_type_a, + { + "CSIT Compatibility Type A", "wmx.sbc.ofdma_ms_csit_capability.csit_compatibility_type_a", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_174_csit_compatibility_type_b, + { + "CSIT Compatibility Type B", "wmx.sbc.ofdma_ms_csit_capability.csit_compatibility_type_b", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_174_max_num_simultanous_sounding_instructions, + { + "Max Number Of Simultaneous Sounding Instructions", "wmx.sbc.ofdma_ms_csit_capability.max_num_simultaneous_sounding_instructions", + FT_UINT16, BASE_DEC, NULL, 0x03C0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_174_power_assignment_capability, + { + "Power Assignment Capability", "wmx.sbc.ofdma_ms_csit_capability.power_assignment_capability", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_174_ss_csit_reserved, + { + "Reserved", "wmx.sbc.ofdma_ms_csit_capability.reserved", + FT_UINT16, BASE_HEX, NULL, 0xF800, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_174_sounding_rsp_time_capability, + { + "Sounding Response Time Capability", "wmx.sbc.ofdma_ms_csit_capability.sounding_response_time_capability", + FT_UINT16, BASE_HEX, VALS(vals_sounding_rsp_time_cap_codings), 0x0038, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_174_ss_csit_type_a_support, + { + "SS Does Not Support P Values Of 9 And 18 When Supporting CSIT Type A", "wmx.sbc.ofdma_ms_csit_capability.type_a_support", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x0400, NULL, HFILL + } + }, + { + /* 11.8.3.7.20 */ + &hf_sbc_tlv_t_204_ofdma_parameters_sets, + { + "OFDMA parameters sets", "wmx.sbc.ofdma_parameters_sets", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_204_ofdma_parameters_sets_phy_set_a, + { + "Support OFDMA PHY parameter set A", "wmx.sbc.ofdma_parameters_sets.phy_set_a", + FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_204_ofdma_parameters_sets_phy_set_b, + { + "Support OFDMA PHY parameter set B", "wmx.sbc.ofdma_parameters_sets.phy_set_b", + FT_UINT8, BASE_HEX, NULL, 0x02, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_204_ofdma_parameters_sets_harq_parameters_set, + { + "HARQ parameters set", "wmx.sbc.ofdma_parameters_sets.harq_parameters_set", + FT_UINT8, BASE_HEX, VALS(vals_sbc_harq_parameters_set), 0x1C, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_204_ofdma_parameters_sets_mac_set_a, + { + "Support OFDMA MAC parameters set A", "wmx.sbc.ofdma_parameters_sets.mac_set_a", + FT_UINT8, BASE_HEX, NULL, 0x20, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_204_ofdma_parameters_sets_mac_set_b, + { + "Support OFDMA MAC parameters set B", "wmx.sbc.ofdma_parameters_sets.mac_set_b", + FT_UINT8, BASE_HEX, NULL, 0x40, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_204_ofdma_parameters_sets_reserved, + { + "Reserved", "wmx.sbc.ofdma_parameters_sets.reserved", + FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL + } + }, + { /* 11.8.3.7.16 */ + &hf_sbc_tlv_t_177_ofdma_ss_modulator_for_mimo_support, + { + "OFDMA SS Modulator For MIMO Support", "wmx.sbc.ofdma_ss_modulator_for_mimo_support", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_adaptive_rate_ctl, + { + "Capable Of Adaptive Rate Control", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.capable_adaptive_rate_control", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_beamforming, + { + "Capable Of Beamforming", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.capable_beamforming", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_single_antenna, + { + "Capable of single antenna transmission", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.capable_single_antenna", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_stc_matrix_b_horizontal, + { + "Capable of 2-antenna STC Matrix B, Horizontal coding", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.stc_matrix_b_horizontal", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_two_transmit_antennas, + { + "Two transmit antennas", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.two_transmit_antennas", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_capable_of_transmit_diversity, + { + "Capable of transmit diversity", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.capable_of_transmit_diversity", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_capable_of_spacial_multiplexing, + { + "Capable of spatial multiplexing", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.capable_of_spatial_multiplexing", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_stc_matrix_b_vertical, + { + "Capable of 2-antenna STC Matrix B, Vertical coding", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.stc_matrix_b_vertical", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_collaborative_sm_with_one_antenna, + { + "Capable of collaborative SM with one antenna", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.collaborative_sm_with_one_antenna", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_collaborative_sm_with_two_antennas, + { + "Collaborative SM with two antennas", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.collaborative_sm_with_two_antennas", + FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_capable_of_two_antenna, + { + "Capable of two antenna", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.capable_of_two_antenna", + FT_UINT8, BASE_HEX, NULL, 0x40, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_rsvd, + { + "Reserved", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.rsvd", + FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_177_stc_matrix_a, + { + "Capable of 2-antenna STC Matrix A", "wmx.sbc.ofdma_ss_modulator_for_mimo_support.stc_matrix_a", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { /* 11.8.3.7.17 */ + &hf_sbc_tlv_t_178_sdma_pilot_capability, + { + "SDMA Pilot Capability", "wmx.sbc.sdma_pilot_capability", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_178_reserved, + { + "Reserved", "wmx.sbc.sdma_pilot_capability.reserved", + FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_178_sdma_pilot_pattern_support_for_amc_zone, + { + "SDMA Pilot Patterns Support For AMC Zone", "wmx.sbc.sdma_pilot_capability.sdma_pilot_pattern_support_for_amc_zone", + FT_UINT8, BASE_HEX, VALS(vals_sbc_sdma_str), 0x03, NULL, HFILL + } + }, + { /* 11.8.3.7.2 - type 151 */ + &hf_sbc_ss_demodulator, + { + "OFDMA SS Demodulator", "wmx.sbc.ss_demodulator", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + /* tlv length = 1 byte */ + { + &hf_sbc_ss_demodulator_64qam, + { + "64-QAM", "wmx.sbc.ss_demodulator.64qam", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_btc, + { + "BTC", "wmx.sbc.ss_demodulator.btc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_cc_with_optional_interleaver, + { + "CC with Optional Interleaver", "wmx.sbc.ss_demodulator.cc_with_optional_interleaver", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_ctc, + { + "CTC", "wmx.sbc.ss_demodulator.ctc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + /* tlv length = 2 bytes */ + { + &hf_sbc_ss_demodulator_64qam_2, + { + "64-QAM", "wmx.sbc.ss_demodulator.64qam", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_btc_2, + { + "BTC", "wmx.sbc.ss_demodulator.btc", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_cc_with_optional_interleaver_2, + { + "CC with Optional Interleaver", "wmx.sbc.ss_demodulator.cc_with_optional_interleaver", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_ctc_2, + { + "CTC", "wmx.sbc.ss_demodulator.ctc", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_dedicated_pilots_2, + { + "Dedicated Pilots", "wmx.sbc.ss_demodulator.dedicated_pilots", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x400, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_harq_cc_ir_2, + { + "HARQ CC_IR", "wmx.sbc.ss_demodulator.harq.cc.ir", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x100, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_harq_chase, + { + "HARQ Chase", "wmx.sbc.ss_demodulator.harq.chase", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_harq_chase_2, + { + "HARQ Chase", "wmx.sbc.ss_demodulator.harq.chase", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_harq_ctc_ir, + { + "HARQ CTC_IR", "wmx.sbc.ss_demodulator.harq.ctc.ir", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_harq_ctc_ir_2, + { + "HARQ CTC_IR", "wmx.sbc.ss_demodulator.harq.ctc.ir", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_ldpc_2, + { + "LDPC", "wmx.sbc.ss_demodulator.ldpc", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x200, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_reserved, + { + "Reserved", "wmx.sbc.ss_demodulator.reserved1", + FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_reserved_2, + { + "Reserved", "wmx.sbc.ss_demodulator.reserved2", + FT_UINT16, BASE_HEX, NULL, 0x80, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_reserved1_2, + { + "Reserved", "wmx.sbc.ss_demodulator.reserved2", + FT_UINT16, BASE_HEX, NULL, 0x800, NULL, HFILL + } + }, +#if 0 + { /* if the number of DL H-ARQ channels > 7 but tlv length = 1 */ + &hf_sbc_ss_demodulator_reserved1, + { + "Reserved", "wmx.sbc.ss_demodulator.reserved1", + FT_UINT16, BASE_HEX, NULL, 0xFFFF, NULL, HFILL + } + }, +#endif + { + &hf_sbc_ss_demodulator_stc, + { + "STC", "wmx.sbc.ss_demodulator.stc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_ss_demodulator_stc_2, + { + "STC", "wmx.sbc.ss_demodulator.stc", + FT_BOOLEAN, 16, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + /* 11.8.3.4 - 11.8.3.6 are not supported for now */ + { /* 11.8.3.7.1 */ + &hf_sbc_ss_fft_sizes, + { + "OFDMA SS FFT Sizes", "wmx.sbc.ss_fft_sizes", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_ss_fft_128, + { + "FFT-128", "wmx.sbc.ss_fft_sizes.128", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_ss_fft_256, + { + "FFT-256", "wmx.sbc.ss_fft_sizes.256", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_ss_fft_512, + { + "FFT-512", "wmx.sbc.ss_fft_sizes.512", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_ss_fft_1024, + { + "FFT-1024", "wmx.sbc.ss_fft_sizes.1024", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ss_fft_2048, + { + "FFT-2048", "wmx.sbc.ss_fft_sizes.2048", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_fft_rsvd1, + { + "Reserved", "wmx.sbc_ss_fft_sizes_rsvd1", + FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_sbc_ss_fft_rsvd2, + { + "Reserved", "wmx.sbc.ss_fft_sizes.rsvd2", + FT_UINT8, BASE_HEX, NULL, 0xE0, NULL, HFILL + } + }, +#if 0 + { + &hf_sbc_ofdm_ss_minimum_num_of_frames, + { + "SS minimum number of frames", "wmx.sbc.ss_minimum_num_of_frames", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, +#endif + { + &hf_sbc_ss_mimo_uplink_support_rsvd, + { + "Reserved", "wmx.sbc.ss_mimo_ul_support.rsvd", + FT_UINT8, BASE_HEX, NULL, 0xF8, NULL, HFILL + } + }, + { /* 11.8.3.7.3 - type 152 */ + &hf_sbc_ss_modulator, + { + "OFDMA SS Modulator", "wmx.sbc.ss_modulator", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_ss_modulator_64qam, + { + "64-QAM", "wmx.sbc.ss_modulator.64qam", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_ss_modulator_btc, + { + "BTC", "wmx.sbc.ss_modulator.btc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_modulator_cc_ir, + { + "CC_IR", "wmx.sbc.ss_modulator.cc_ir", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { + &hf_sbc_ss_modulator_ctc, + { + "CTC", "wmx.sbc.ss_modulator.ctc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_ss_modulator_ctc_ir, + { + "CTC_IR", "wmx.sbc.ss_modulator.ctc_ir", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_ss_modulator_harq_chase, + { + "HARQ Chase", "wmx.sbc.ss_modulator.harq_chase", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ss_modulator_ldpc, + { + "LDPC", "wmx.sbc.ss_modulator.ldpc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x80, NULL, HFILL + } + }, + { + &hf_sbc_ss_modulator_stc, + { + "STC", "wmx.sbc.ss_modulator.stc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { /* 11.8.3.7.4 */ + &hf_sbc_ss_permutation_support, + { + "OFMDA SS Permutation Support", "wmx.sbc.ss_permutation_support", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_ss_amc_1x6, + { + "AMC 1x6", "wmx.sbc.ss_permutation_support.amc_1x6", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_ss_amc_2x3, + { + "AMC 2x3", "wmx.sbc.ss_permutation_support.amc_2x3", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x8, NULL, HFILL + } + }, + { + &hf_sbc_ss_amc_3x2, + { + "AMC 3x2", "wmx.sbc.ss_permutation_support.amc_3x2", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_ss_amc_with_harq_map, + { + "AMC Support With H-ARQ Map", "wmx.sbc.ss_permutation_support.amc_support_harq_map", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_ss_optimal_fusc, + { + "Optional FUSC", "wmx.sbc.ss_permutation_support.optimal_fusc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_ss_optimal_pusc, + { + "Optional PUSC", "wmx.sbc.ss_permutation_support.optimal_pusc", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_ss_tusc1_support, + { + "TUSC1", "wmx.sbc.ss_permutation_support.tusc1_support", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { + &hf_sbc_ss_tusc2_support, + { + "TUSC2", "wmx.sbc.ss_permutation_support.tusc2_support", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x80, NULL, HFILL + } + }, + { + &hf_sbc_ssrtg, + { + "SSRTG", "wmx.sbc.ssrtg", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_ssttg, + { + "SSTTG", "wmx.sbc.ssttg", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_ss_support_2_concurrent_cqi_channels, + { + "Support for 2 Concurrent CQI Channels", "wmx.sbc.support_2_concurrent_cqi_channels", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { /* 11.8.3.1 */ + &hf_sbc_transition_gaps, + { + "Subscriber Transition Gaps", "wmx.sbc.transition_gaps", + FT_UINT16, BASE_HEX, NULL, 0x00, NULL, HFILL + } + }, + { /* 11.8.3.7.13 */ + &hf_sbc_tlv_t_173_ul_ctl_channel_support, + { + "Uplink Control Channel Support", "wmx.sbc.ul_ctl_channel_support", + FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_173_3_bit_mimo_fast_feedback, + { + "3-bit MIMO Fast-feedback", "wmx.sbc.ul_ctl_channel_support.3bit_mimo_fast_feedback", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x1, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_173_diuc_cqi_fast_feedback, + { + "DIUC-CQI Fast-feedback", "wmx.sbc.ul_ctl_channel_support.diuc_cqi_fast_feedback", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x80, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_173_enhanced_fast_feedback, + { + "Enhanced Fast_feedback", "wmx.sbc.ul_ctl_channel_support.enhanced_fast_feedback", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x2, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_173_measurement_report, + { + "A Measurement Report Shall Be Performed On The Last DL Burst", "wmx.sbc.ul_ctl_channel_support.measurement_report", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x20, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_173_primary_secondary_fast_feedback, + { + "Primary/Secondary FAST_FEEDBACK", "wmx.sbc.ul_ctl_channel_support.primary_secondary_fast_feedback", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x40, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_173_reserved, + { + "Reserved", "wmx.sbc.ul_ctl_channel_support.reserved", + FT_UINT8, BASE_HEX, NULL, 0x8, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_173_uep_fast_feedback, + { + "UEP Fast-feedback", "wmx.sbc.ul_ctl_channel_support.uep_fast_feedback", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x10, NULL, HFILL + } + }, + { + &hf_sbc_tlv_t_173_ul_ack, + { + "UL ACK", "wmx.sbc.ul_ctl_channel_support.ul_ack", + FT_BOOLEAN, 8, TFS(&tfs_supported), 0x4, NULL, HFILL + } + }, + { + &hf_sbc_unknown_type, + { + "Unknown SBC type", "wmx.sbc.unknown_tlv_type", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett_sbc[] = + { + &ett_mac_mgmt_msg_sbc_decoder, + &ett_sbc_req_tlv_subtree, + &ett_sbc_rsp_tlv_subtree, + }; + + proto_mac_mgmt_msg_sbc_decoder = proto_register_protocol ( + "WiMax SBC-REQ/RSP Messages", /* name */ + "WiMax SBC-REQ/RSP (sbc)", /* short name */ + "wmx.sbc" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_sbc_decoder, hf_sbc, array_length(hf_sbc)); + proto_register_subtree_array(ett_sbc, array_length(ett_sbc)); + + sbc_req_handle = register_dissector("mac_mgmt_msg_sbc_req_handler", dissect_mac_mgmt_msg_sbc_req_decoder, proto_mac_mgmt_msg_sbc_decoder); + sbc_rsp_handle = register_dissector("mac_mgmt_msg_sbc_rsp_handler", dissect_mac_mgmt_msg_sbc_rsp_decoder, proto_mac_mgmt_msg_sbc_decoder); +} + +void +proto_reg_handoff_mac_mgmt_msg_sbc(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_SBC_REQ, sbc_req_handle); + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_SBC_RSP, sbc_rsp_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: + */ diff --git a/plugins/epan/wimax/msg_ucd.c b/plugins/epan/wimax/msg_ucd.c new file mode 100644 index 00000000..ab6d811d --- /dev/null +++ b/plugins/epan/wimax/msg_ucd.c @@ -0,0 +1,1243 @@ +/* msg_ucd.c + * WiMax MAC Management UCD Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +/* +#define DEBUG +*/ + +#include +#include "wimax_tlv.h" +#include "wimax_mac.h" +#include "wimax_utils.h" + +void proto_register_mac_mgmt_msg_ucd(void); +void proto_reg_handoff_mac_mgmt_msg_ucd(void); + +static dissector_handle_t ucd_handle; + +extern gboolean include_cor2_changes; + +guint cqich_id_size; /* Set for CQICH_Alloc_IE */ + +static gint proto_mac_mgmt_msg_ucd_decoder = -1; +static gint ett_mac_mgmt_msg_ucd_decoder = -1; + +/* fix fields */ +static gint hf_ucd_res_timeout = -1; +static gint hf_ucd_bw_req_size = -1; +static gint hf_ucd_ranging_req_size = -1; +static gint hf_ucd_freq = -1; +/* static gint hf_ucd_subchan_params_num_chan = -1; */ +static gint hf_ucd_ul_allocated_subchannles_bitmap = -1; +/* static gint hf_ucd_subchan_params_num_sym = -1; */ +/* static gint hf_ucd_subchan_codes = -1; */ + +static gint hf_ucd_ul_burst_reserved = -1; +static gint hf_ucd_ul_burst_uiuc = -1; +static gint hf_ucd_burst_fec = -1; +static gint hf_ucd_burst_ranging_data_ratio = -1; +/*static gint hf_ucd_burst_power_boost = -1; +*static gint hf_ucd_burst_tcs_enable = -1; +*/ + +static gint hf_ucd_tlv_t_159_band_amc_allocation_threshold = -1; +static gint hf_ucd_tlv_t_158_optional_permutation_ul_allocated_subchannels_bitmap = -1; +static gint hf_ucd_tlv_t_160_band_amc_release_threshold = -1; +static gint hf_ucd_tlv_t_161_band_amc_allocation_timer = -1; +static gint hf_ucd_tlv_t_162_band_amc_release_timer = -1; +static gint hf_ucd_tlv_t_163_band_status_report_max_period = -1; +static gint hf_ucd_tlv_t_164_band_amc_retry_timer = -1; +static gint hf_ucd_tlv_t_171_harq_ack_delay_dl_burst = -1; +static gint hf_ucd_tlv_t_170_safety_channel_retry_timer = -1; +static gint hf_ucd_tlv_t_172_cqich_band_amc_transition_delay = -1; +static gint hf_ucd_tlv_t_174_maximum_retransmission = -1; +static gint hf_ucd_tlv_t_177_normalized_cn_override2 = -1; +static gint hf_ucd_tlv_t_177_normalized_cn_override2_first_line = -1; +static gint hf_ucd_tlv_t_177_normalized_cn_override2_list = -1; +static gint hf_ucd_tlv_t_176_size_of_cqich_id_field = -1; +static gint hf_ucd_tlv_t_186_upper_bound_aas_preamble = -1; +static gint hf_ucd_tlv_t_187_lower_bound_aas_preamble = -1; +static gint hf_ucd_tlv_t_188_allow_aas_beam_select_message = -1; +static gint hf_ucd_tlv_t_189_use_cqich_indication_flag = -1; +static gint hf_ucd_tlv_t_190_ms_specific_up_power_addjustment_step = -1; +static gint hf_ucd_tlv_t_191_ms_specific_down_power_addjustment_step = -1; +static gint hf_ucd_tlv_t_192_min_level_power_offset_adjustment = -1; +static gint hf_ucd_tlv_t_193_max_level_power_offset_adjustment = -1; +static gint hf_ucd_tlv_t_194_handover_ranging_codes = -1; +static gint hf_ucd_tlv_t_195_initial_ranging_interval = -1; +static gint hf_ucd_tlv_t_196_tx_power_report = -1; +static gint hf_ucd_tlv_t_196_tx_power_report_threshold = -1; +static gint hf_ucd_tlv_t_196_tx_power_report_interval = -1; +static gint hf_ucd_tlv_t_196_tx_power_report_a_p_avg = -1; +static gint hf_ucd_tlv_t_196_tx_power_report_threshold_icqch = -1; +static gint hf_ucd_tlv_t_196_tx_power_report_interval_icqch = -1; +static gint hf_ucd_tlv_t_196_tx_power_report_a_p_avg_icqch = -1; +/* static gint hf_ucd_tlv_t_197_normalized_cn_channel_sounding = -1; */ +static gint hf_ucd_tlv_t_202_uplink_burst_profile_for_multiple_fec_types = -1; +static gint hf_ucd_tlv_t_203_ul_pusc_subchannel_rotation = -1; +static gint hf_ucd_tlv_t_205_relative_power_offset_ul_harq_burst = -1; +static gint hf_ucd_tlv_t_206_relative_power_offset_ul_burst_containing_mac_mgmt_msg = -1; +static gint hf_ucd_tlv_t_207_ul_initial_transmit_timing = -1; +static gint hf_ucd_tlv_t_210_fast_feedback_region = -1; +static gint hf_ucd_tlv_t_211_harq_ack_region = -1; +static gint hf_ucd_tlv_t_212_ranging_region = -1; +static gint hf_ucd_tlv_t_213_sounding_region = -1; +static gint hf_ucd_tlv_t_150_initial_ranging_codes = -1; +static gint hf_ucd_tlv_t_151_periodic_ranging_codes = -1; +static gint hf_ucd_tlv_t_152_bandwidth_request_codes = -1; +static gint hf_ucd_tlv_t_155_start_of_ranging_codes_group = -1; +static gint hf_ucd_tlv_t_156_permutation_base = -1; +static gint hf_ucd_ho_ranging_start = -1; +static gint hf_ucd_ho_ranging_end = -1; +static gint hf_ucd_initial_range_backoff_start = -1; +static gint hf_ucd_initial_range_backoff_end = -1; +static gint hf_ucd_bandwidth_backoff_start = -1; +static gint hf_ucd_bandwidth_backoff_end = -1; +static gint hf_ucd_periodic_ranging_backoff_start = -1; +static gint hf_ucd_periodic_ranging_backoff_end = -1; +static gint hf_ucd_config_change_count = -1; +static gint hf_ucd_ranging_backoff_start = -1; +static gint hf_ucd_ranging_backoff_end = -1; +static gint hf_ucd_request_backoff_start = -1; +static gint hf_ucd_request_backoff_end = -1; + +/* static gint hf_ucd_unknown_type = -1; */ +static gint hf_ucd_invalid_tlv = -1; + +#if 0 +static const value_string vals_dcd_burst_tcs[] = +{ + {0, "TCS disabled"}, + {1, "TCS enabled"}, + {0, NULL} +}; +#endif + +static const value_string vals_dcd_burst_fec[] = +{ + { 0, "QPSK (CC) 1/2"}, + { 1, "QPSK (CC) 3/4"}, + { 2, "16-QAM (CC) 1/2"}, + { 3, "16-QAM (CC) 3/4"}, + { 4, "64-QAM (CC) 1/2"}, + { 5, "64-QAM (CC) 2/3"}, + { 6, "64-QAM (CC) 3/4"}, + { 7, "QPSK (BTC) 1/2"}, + { 8, "QPSK (BTC) 3/4 or 2/3"}, + { 9, "16-QAM (BTC) 3/5"}, + {10, "16-QAM (BTC) 4/5"}, + {11, "64-QAM (BTC) 2/3 or 5/8"}, + {12, "64-QAM (BTC) 5/6 or 4/5"}, + {13, "QPSK (CTC) 1/2"}, + {14, "Reserved"}, + {15, "QPSK (CTC) 3/4"}, + {16, "16-QAM (CTC) 1/2"}, + {17, "16-QAM (CTC) 3/4"}, + {18, "64-QAM (CTC) 1/2"}, + {19, "64-QAM (CTC) 2/3"}, + {20, "64-QAM (CTC) 3/4"}, + {21, "64-QAM (CTC) 5/6"}, + {22, "QPSK (ZT CC) 1/2"}, + {23, "QPSK (ZT CC) 3/4"}, + {24, "16-QAM (ZT CC) 1/2"}, + {25, "16-QAM (ZT CC) 3/4"}, + {26, "64-QAM (ZT CC) 1/2"}, + {27, "64-QAM (ZT CC) 2/3"}, + {28, "64-QAM (ZT CC) 3/4"}, + {29, "QPSK (LDPC) 1/2"}, + {30, "QPSK (LDPC) 2/3 A code"}, + {31, "16-QAM (LDPC) 3/4 A code"}, + {32, "16-QAM (LDPC) 1/2"}, + {33, "16-QAM (LDPC) 2/3 A code"}, + {34, "16-QAM (LDPC) 3/4 A code"}, + {35, "64-QAM (LDPC) 1/2"}, + {36, "64-QAM (LDPC) 2/3 A code"}, + {37, "64-QAM (LDPC) 3/4 A code"}, + {38, "QPSK (LDPC) 2/3 B code"}, + {39, "QPSK (LDPC) 3/4 B code"}, + {40, "16-QAM (LDPC) 2/3 B code"}, + {41, "16-QAM (LDPC) 3/4 B code"}, + {42, "64-QAM (LDPC) 2/3 B code"}, + {43, "64-QAM (LDPC) 3/4 B code"}, + {44, "QPSK (CC with optional interleaver) 1/2"}, + {45, "QPSK (CC with optional interleaver) 3/4"}, + {46, "16-QAM (CC with optional interleaver) 1/2"}, + {47, "16-QAM (CC optional interleaver) 0%00"}, + {48, "64-QAM (CC with optional interleaver) 2/3"}, + {49, "64-QAM (CC with optional interleaver) 3/4"}, + {50, "QPSK (LDPC) 5/6"}, + {51, "16-QAM (LDPC) 5/6"}, + {52, "64-QAM (LDPC) 5/6"}, + {0, NULL} +}; + +static const value_string vals_ucd_cqich_size[] = +{ + {0, "0 bits"}, + {1, "3 bits"}, + {2, "4 bits"}, + {3, "5 bits"}, + {4, "6 bits"}, + {5, "7 bits"}, + {6, "8 bits"}, + {7, "9 bits"}, + {0, NULL} +}; + +static const value_string vals_yes_no_str[] = +{ + {0, "No"}, + {1, "Yes"}, + {0, NULL} +}; + + +/* UCD dissector */ +static int dissect_mac_mgmt_msg_ucd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len, length; + gint tlv_type, tlv_len, tlv_offset, tlv_value_offset; + tlv_info_t tlv_info; + gchar* proto_str; + + { /* we are being asked for details */ + proto_item *ucd_item; + proto_tree *ucd_tree; + guint ucd_ranging_backoff_start; + guint ucd_ranging_backoff_end; + guint ucd_request_backoff_start; + guint ucd_request_backoff_end; + + tvb_len = tvb_reported_length(tvb); + /* display MAC payload type UCD */ + ucd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, -1, "Uplink Channel Descriptor (UCD)"); + ucd_tree = proto_item_add_subtree(ucd_item, ett_mac_mgmt_msg_ucd_decoder); + + /* Decode and display the Uplink Channel Descriptor (UCD) */ + /* display the Configuration Change Count */ + proto_tree_add_item(ucd_tree, hf_ucd_config_change_count, tvb, offset, 1, ENC_NA); + offset++; + + /* get the ranging backoff start */ + ucd_ranging_backoff_start = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(ucd_tree, hf_ucd_ranging_backoff_start, tvb, offset, 1, (1 << ucd_ranging_backoff_start), "2^%u = %u", ucd_ranging_backoff_start, (1 << ucd_ranging_backoff_start)); + offset++; + + /* get the ranging backoff end */ + ucd_ranging_backoff_end = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(ucd_tree, hf_ucd_ranging_backoff_end, tvb, offset, 1, (1 << ucd_ranging_backoff_end), "2^%u = %u", ucd_ranging_backoff_end, (1 << ucd_ranging_backoff_end)); + offset++; + + /* get the request backoff start */ + ucd_request_backoff_start = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(ucd_tree, hf_ucd_request_backoff_start, tvb, offset, 1, (1 << ucd_request_backoff_start), "2^%u = %u", ucd_request_backoff_start, (1 << ucd_request_backoff_start)); + offset++; + + /* get the request backoff end */ + ucd_request_backoff_end = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(ucd_tree, hf_ucd_request_backoff_end, tvb, offset, 1, (1 << ucd_request_backoff_end), "2^%u = %u", ucd_request_backoff_end, (1 << ucd_request_backoff_end)); + offset++; + + while(offset < tvb_len) + { + proto_tree *tlv_tree; + proto_item *tlv_item1; + guint ul_burst_uiuc; + guint utemp; + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UCD TLV error"); + proto_tree_add_item(ucd_tree,hf_ucd_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, (tlv_len + tlv_value_offset), "UCD Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len); +#endif + /* update the offset */ + offset += tlv_value_offset; + /* process UCD TLV Encoded information */ + if (include_cor2_changes) + { + switch (tlv_type) + { + case UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_203_ul_pusc_subchannel_rotation, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_205_relative_power_offset_ul_harq_burst, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_206_relative_power_offset_ul_burst_containing_mac_mgmt_msg, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_207_ul_initial_transmit_timing, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_210_FAST_FEEDBACK_REGION: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_210_fast_feedback_region, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + case UCD_TLV_T_211_HARQ_ACK_REGION: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_211_harq_ack_region, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + case UCD_TLV_T_212_RANGING_REGION: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_212_ranging_region, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + case UCD_TLV_T_213_SOUNDING_REGION: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_213_sounding_region, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + } + } + switch (tlv_type) + { + case UCD_UPLINK_BURST_PROFILE: + { + /* get the UIUC */ + ul_burst_uiuc = tvb_get_guint8(tvb, offset) & 0x0F; + /* add TLV subtree */ + proto_str = wmem_strdup_printf(pinfo->pool, "Uplink Burst Profile (UIUC = %u)", ul_burst_uiuc); + tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset-tlv_value_offset, tlv_len, proto_str); + proto_tree_add_item(tlv_tree, hf_ucd_ul_burst_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_ucd_ul_burst_uiuc, tvb, offset, 1, ENC_BIG_ENDIAN); + for (tlv_offset = 1; tlv_offset < tlv_len;) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, (offset+tlv_offset)); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + if(tlv_type == -1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UL Burst Profile error"); + proto_tree_add_item(tlv_tree, hf_ucd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), ENC_NA); + break; + } + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + + switch (tlv_type) + { + case UCD_BURST_FEC: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_fec, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); + break; + } + case UCD_BURST_RANGING_DATA_RATIO: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_ranging_data_ratio, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); + break; + } +#if 0 /* for OFDM */ + case UCD_BURST_POWER_BOOST: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_power_boost, tvb, (offset+tlv_offset), ENC_BIG_ENDIAN); + break; + } + case UCD_BURST_TCS_ENABLE: + { + add_tlv_subtree(&tlv_info, tlv_tree, hf_ucd_burst_tcs_enable, tvb, (offset+tlv_offset), 1, ENC_BIG_ENDIAN); + break; + } +#endif + default: + /* ??? */ + break; + } + tlv_offset += (length+get_tlv_value_offset(&tlv_info)); + } + break; + } + case UCD_RESERVATION_TIMEOUT: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_res_timeout, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_BW_REQ_SIZE: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_bw_req_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_RANGING_REQ_SIZE: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_ranging_req_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_FREQUENCY: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_freq, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_7_HO_RANGING_START: + { + tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_ho_ranging_start, tvb, offset-tlv_value_offset); + utemp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tlv_tree, hf_ucd_ho_ranging_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); + break; + } + case UCD_TLV_T_8_RANGING_HO_END: + { + tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_ho_ranging_end, tvb, offset-tlv_value_offset); + utemp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tlv_tree, hf_ucd_ho_ranging_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); + break; + } + case UCD_TLV_T_158_OPTIONAL_PERMUTATION_UL_ALLOCATED_SUBCHANNELS_BITMAP: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_158_optional_permutation_ul_allocated_subchannels_bitmap, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + case UCD_TLV_T_159_BAND_AMC_ALLOCATION_THRESHHOLD: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_159_band_amc_allocation_threshold, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_160_BAND_AMC_RELEASE_THRESHOLD: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_160_band_amc_release_threshold, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_161_BAND_AMC_ALLOCATION_TIMER: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_161_band_amc_allocation_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_162_BAND_AMC_RELEASE_TIMER: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_162_band_amc_release_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_163_BAND_STATUS_REPORT_MAX_PERIOD: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_163_band_status_report_max_period, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_164_BAND_AMC_RETRY_TIMER: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_164_band_amc_retry_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_170_SAFETY_CHANNEL_RETRY_TIMER: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_170_safety_channel_retry_timer, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_171_HARQ_ACK_DELAY_FOR_DL_BURST: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_171_harq_ack_delay_dl_burst, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_172_CQICH_BAND_AMC_TRANSITION_DELAY: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_172_cqich_band_amc_transition_delay, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_174_MAXIMUM_RETRANSMISSION: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_174_maximum_retransmission, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_176_SIZE_OF_CQICH_ID_FIELD: + { + utemp = tvb_get_guint8(tvb, offset); + cqich_id_size = 0; /* Default is 0 */ + if (utemp && utemp < 8) { + /* Set for CQICH_Alloc_IE */ + cqich_id_size = utemp + 2; + } + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_176_size_of_cqich_id_field, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_177_NORMALIZED_CN_OVERRIDE_2: + { + /* add TLV subtree */ + tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_177_normalized_cn_override2, tvb, offset-tlv_value_offset, ENC_NA|ENC_ASCII); + tlv_tree = proto_item_add_subtree(tlv_item1, ett_mac_mgmt_msg_ucd_decoder); + proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_177_normalized_cn_override2_first_line, tvb, offset + 2, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_177_normalized_cn_override2_list, tvb, offset + 3, 7, ENC_ASCII|ENC_NA); + break; + } + case UCD_TLV_T_186_UPPER_BOUND__AAS_PREAMBLE: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_186_upper_bound_aas_preamble, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_187_LOWER_BOUND_AAS_PREAMBLE: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_187_lower_bound_aas_preamble, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_188_ALLOW_AAS_BEAM_SELECT_MESSAGE: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_188_allow_aas_beam_select_message, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_189_USE_CQICH_INDICATION_FLAG: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_189_use_cqich_indication_flag, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_190_MS_SPECIFIC_UP_POWER_OFFSET_ADJUSTMENT_STEP: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_190_ms_specific_up_power_addjustment_step, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_191_MS_SPECIFIC_DOWN_POWER_OFSET_ADJUSTMENT_STEP: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_191_ms_specific_down_power_addjustment_step, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_192_MIN_LEVEL_POWER_OFFSET_ADJUSTMENT: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_192_min_level_power_offset_adjustment, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_193_MAX_LEVEL_POWER_OFFSETR_ADJUSTMENT: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_193_max_level_power_offset_adjustment, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_194_HANDOVER_RANGING_CODES: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_194_handover_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_195_INITIAL_RANGING_INTERVAL: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_196_TX_POWER_REPORT: + { + tlv_item1 = add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_196_tx_power_report, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item1, ett_mac_mgmt_msg_ucd_decoder); + proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_threshold, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_interval, tvb , offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_a_p_avg, tvb, (offset + 1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_threshold_icqch, tvb, (offset + 1), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_interval_icqch, tvb, (offset + 2), 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_a_p_avg_icqch, tvb, (offset + 2), 1, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_197_NORMALIZED_CN_FOR_CHANNEL_SOUNDING: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_TLV_T_198_INTIAL_RANGING_BACKOFF_START: + { + tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_initial_range_backoff_start, tvb, offset-tlv_value_offset); + utemp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tlv_tree, hf_ucd_initial_range_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); + break; + } + case UCD_TLV_T_199_INITIAL_RANGING_BACKOFF_END: + { + tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_initial_range_backoff_end, tvb, offset-tlv_value_offset); + utemp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tlv_tree, hf_ucd_initial_range_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); + break; + } + case UCD_TLV_T_200_BANDWIDTH_REQUESET_BACKOFF_START: + { + tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_bandwidth_backoff_start, tvb, offset-tlv_value_offset); + utemp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tlv_tree, hf_ucd_bandwidth_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); + break; + } + case UCD_TLV_T_201_BANDWIDTH_REQUEST_BACKOFF_END: + { + tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_bandwidth_backoff_end, tvb, offset-tlv_value_offset); + utemp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tlv_tree, hf_ucd_bandwidth_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); + break; + } + case UCD_TLV_T_202_UPLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_202_uplink_burst_profile_for_multiple_fec_types, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_INITIAL_RANGING_CODES: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_150_initial_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_PERIODIC_RANGING_CODES: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_151_periodic_ranging_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_BANDWIDTH_REQUEST_CODES: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_152_bandwidth_request_codes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_PERIODIC_RANGING_BACKOFF_START: + { + tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_periodic_ranging_backoff_start, tvb, offset-tlv_value_offset); + utemp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tlv_tree, hf_ucd_periodic_ranging_backoff_start, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); + break; + + } + case UCD_PERIODIC_RANGING_BACKOFF_END: + { + tlv_tree = add_tlv_subtree_no_item(&tlv_info, ucd_tree, hf_ucd_periodic_ranging_backoff_end, tvb, offset-tlv_value_offset); + utemp = tvb_get_guint8(tvb, offset); + proto_tree_add_uint_format_value(tlv_tree, hf_ucd_periodic_ranging_backoff_end, tvb, offset, tvb_len, utemp, "2^%u = %u", utemp, (1 << utemp)); + break; + } + case UCD_START_OF_RANGING_CODES_GROUP: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_155_start_of_ranging_codes_group, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + + } + case UCD_PERMUTATION_BASE: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_tlv_t_156_permutation_base, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + } + case UCD_UL_ALLOCATED_SUBCHANNELS_BITMAP: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_ul_allocated_subchannles_bitmap, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + case UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION: + case UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST: + case UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG: + case UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING: + case UCD_TLV_T_210_FAST_FEEDBACK_REGION: + case UCD_TLV_T_211_HARQ_ACK_REGION: + case UCD_TLV_T_212_RANGING_REGION: + case UCD_TLV_T_213_SOUNDING_REGION: + { + /* Unknown TLV type if cor2 not enabled. */ + if (!include_cor2_changes) + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_invalid_tlv, tvb, offset-tlv_value_offset, ENC_NA); + } + break; + } + default: + { + add_tlv_subtree(&tlv_info, ucd_tree, hf_ucd_invalid_tlv, tvb, offset-tlv_value_offset, ENC_NA); + } + } /* end of switch(tlv_type) */ + offset += tlv_len; + } /* end of TLV process while loop */ + } + return tvb_captured_length(tvb); +} + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_ucd(void) +{ + /* UCD display */ + static hf_register_info hf[] = + { + { + &hf_ucd_tlv_t_188_allow_aas_beam_select_message, + { + "Allow AAS Beam Select Message", "wmx.ucd.allow_aas_beam_select_message", + FT_INT8, BASE_DEC, VALS(vals_yes_no_str), 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_159_band_amc_allocation_threshold, + { + "Band AMC Allocation Threshold", "wmx.ucd.band_amc.allocation_threshold", + FT_UINT8, BASE_HEX|BASE_UNIT_STRING, &wimax_units_db, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_161_band_amc_allocation_timer, + { + "Band AMC Allocation Timer", "wmx.ucd.band_amc.allocation_timer", + FT_UINT8, BASE_HEX|BASE_UNIT_STRING, &wimax_units_frame_frames, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_160_band_amc_release_threshold, + { + "Band AMC Release Threshold", "wmx.ucd.band_amc.release_threshold", + FT_UINT8, BASE_HEX|BASE_UNIT_STRING, &wimax_units_db, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_162_band_amc_release_timer, + { + "Band AMC Release Timer", "wmx.ucd.band_amc.release_timer", + FT_UINT8, BASE_HEX|BASE_UNIT_STRING, &wimax_units_frame_frames, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_164_band_amc_retry_timer, + { + "Band AMC Retry Timer", "wmx.ucd.band_amc.retry_timer", + FT_UINT8, BASE_HEX|BASE_UNIT_STRING, &wimax_units_frame_frames, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_163_band_status_report_max_period, + { + "Band Status Report MAC Period", "wmx.ucd.band_status.report_max_period", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_frame_frames, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_152_bandwidth_request_codes, + { + "Bandwidth Request Codes", "wmx.ucd.bandwidth_request", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_burst_fec, + { + "FEC Code Type", "wmx.ucd.burst.fec", + FT_UINT8, BASE_HEX, VALS(vals_dcd_burst_fec), 0, NULL, HFILL + } + }, + { + &hf_ucd_burst_ranging_data_ratio, + { + "Ranging Data Ratio", "wmx.ucd.burst.ranging_data_ratio", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_db, 0, NULL, HFILL + } + }, + { + &hf_ucd_ul_burst_reserved, + { + "Reserved", "wmx.ucd.burst.reserved", + FT_UINT8, BASE_HEX, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_ucd_ul_burst_uiuc, + { + "UIUC", "wmx.ucd.burst.uiuc", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, +#if 0 + { + &hf_ucd_burst_power_boost, + {"Focused Contention Power Boost", "wmx.ucd.burst.power_boost", FT_UINT8, BASE_HEX|BASE_UNIT_STRING, &wimax_units_db, 0, NULL, HFILL} + }, + { + &hf_ucd_burst_tcs_enable, + {"TCS", "wmx.ucd.burst.tcs", FT_UINT8, BASE_DEC, VALS(vals_dcd_burst_tcs), 0, NULL, HFILL} + }, +#endif + { + &hf_ucd_bw_req_size, + { + "Bandwidth Request Opportunity Size", "wmx.ucd.bw_req_size", + FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &wimax_units_ps, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_172_cqich_band_amc_transition_delay, + { + "CQICH Band AMC-Transition Delay", "wmx.ucd.cqich_band_amc_transition_delay", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_frame_frames, 0, NULL, HFILL + } + }, + { + &hf_ucd_freq, + { + "Frequency", "wmx.ucd.frequency", + FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_khz, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_194_handover_ranging_codes, + { + "Handover Ranging Codes", "wmx.ucd.handover_ranging_codes", + FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_171_harq_ack_delay_dl_burst, + { + "HARQ ACK Delay for DL Burst", "wmx.ucd.harq_ack_delay_dl_burst", + FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_frame_offset, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_150_initial_ranging_codes, + { + "Initial Ranging Codes", "wmx.ucd.initial_ranging_codes", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_195_initial_ranging_interval, + { + "Number of Frames Between Initial Ranging Interval Allocation", "wmx.ucd.initial_ranging_interval", + FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_invalid_tlv, + { + "Invalid TLV", "wmx.ucd.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_187_lower_bound_aas_preamble, + { + "Lower Bound AAS Preamble (in units of 0.25 dB)", "wmx.ucd.lower_bound_aas_preamble", + FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_192_min_level_power_offset_adjustment, + { + "Minimum Level of Power Offset Adjustment (in units of 0.1 dB)", "wmx.ucd.min_level_power_offset_adjustment", + FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_193_max_level_power_offset_adjustment, + { + "Maximum Level of Power Offset Adjustment (in units of 0.1 dB)", "wmx.ucd.max_level_power_offset_adjustment", + FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_174_maximum_retransmission, + { + "Maximum Number of Retransmission in UL-HARQ", "wmx.ucd.max_number_of_retransmission_in_ul_harq", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_191_ms_specific_down_power_addjustment_step, + { + "MS-specific Down Power Offset Adjustment Step (in units of 0.01 dB)", "wmx.ucd.ms_specific_down_power_offset_adjustment_step", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_190_ms_specific_up_power_addjustment_step, + { + "MS-specific Up Power Offset Adjustment Step (in units of 0.01 dB)", "wmx.ucd.ms_specific_up_power_offset_adjustment_step", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, +#if 0 + { + &hf_ucd_tlv_t_197_normalized_cn_channel_sounding, + { + "Normalized C/N for Channel Sounding", "wmx.ucd.normalized_cn.channel_sounding", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, +#endif + { + &hf_ucd_tlv_t_177_normalized_cn_override2, + { + "Normalized C/N Override 2", "wmx.ucd.normalized_cn.override_2", + FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_177_normalized_cn_override2_first_line, + { + "Normalized C/N Value", "wmx.ucd.normalized_cn.override_first_line", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_177_normalized_cn_override2_list, + { + "Normalized C/N Value List", "wmx.ucd.normalized_cn.override_list", + FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_158_optional_permutation_ul_allocated_subchannels_bitmap, + { + "Optional permutation UL allocated subchannels bitmap", "wmx.ucd.optional_permutation_ul_allocated_subchannels_bitmap", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_151_periodic_ranging_codes, + { + "Periodic Ranging Codes", "wmx.ucd.periodic_ranging_codes", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_156_permutation_base, + { + "Permutation Base", "wmx.ucd.permutation_base", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_ranging_req_size, + { + "Ranging Request Opportunity Size", "wmx.ucd.ranging_req_size", + FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &wimax_units_db, 0, NULL, HFILL + } + }, + { + &hf_ucd_res_timeout, + { + "Contention-based Reservation Timeout", "wmx.ucd.res_timeout", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_170_safety_channel_retry_timer, + { + "Safety Channel Release Timer", "wmx.ucd.safety_channel_release_timer", + FT_UINT8, BASE_HEX|BASE_UNIT_STRING, &wimax_units_frame_frames, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_176_size_of_cqich_id_field, + { + "Size of CQICH_ID Field", "wmx.ucd.size_of_cqich_id_field", + FT_UINT8, BASE_DEC, VALS(vals_ucd_cqich_size), 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_155_start_of_ranging_codes_group, + { + "Start of Ranging Codes Group", "wmx.ucd.start_of_ranging_codes_group", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_ul_allocated_subchannles_bitmap, + { + "UL Allocated Subchannels Bitmap", "wmx.ucd.subchan.bitmap", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, +#if 0 + { + &hf_ucd_subchan_codes, + { + "Periodic Ranging Codes", "wmx.ucd.subchan.codes", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_subchan_params_num_chan, + { + "Number of Subchannels", "wmx.ucd.subchan.num_chan", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_subchan_params_num_sym, + { + "Number of OFDMA Symbols", "wmx.ucd.subchan.num_sym", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, +#endif + { + &hf_ucd_tlv_t_196_tx_power_report, + { + "Tx Power Report", "wmx.ucd.tx_power_report", + FT_UINT24, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_196_tx_power_report_a_p_avg, + { + "A p_avg (in multiples of 1/16)", "wmx.ucd.tx_power_report.a_p_avg", + FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_196_tx_power_report_a_p_avg_icqch, + { + "A p_avg (in multiples of 1/16) when ICQCH is allocated", "wmx.ucd.tx_power_report.a_p_avg_icqch", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_196_tx_power_report_interval, + { + "Interval (expressed as power of 2)", "wmx.ucd.tx_power_report.interval", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_196_tx_power_report_interval_icqch, + { + "Interval When ICQCH is Allocated (expressed as power of 2)", "wmx.ucd.tx_power_report.interval_icqch", + FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_196_tx_power_report_threshold, + { + "Threshold", "wmx.ucd.tx_power_report.threshold", + FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_196_tx_power_report_threshold_icqch, + { + "Threshold When ICQCH is Allocated to SS (in dB)", "wmx.ucd.tx_power_report.threshold_icqch", + FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL + } + }, +#if 0 + { + &hf_ucd_unknown_type, + { + "Unknown UCD Type", "wmx.ucd.unknown_tlv_type", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, +#endif + { + &hf_ucd_tlv_t_202_uplink_burst_profile_for_multiple_fec_types, + { + "Uplink Burst Profile for Multiple FEC Types", "wmx.ucd.uplink_burst_profile.multiple_fec_types", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_203_ul_pusc_subchannel_rotation, + { + "Uplink PUSC Subchannel Rotation", "wmx.ucd.uplink_burst_profile.ul_pusc_subchannel_rotation", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_205_relative_power_offset_ul_harq_burst, + { + "Relative Power Offset UL HARQ Burst", "wmx.ucd.uplink_burst_profile.relative_power_offset_ul_harq_burst", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_206_relative_power_offset_ul_burst_containing_mac_mgmt_msg, + { + "Relative Power Offset UL Burst Containing MAC Mgmt Msg", "wmx.ucd.uplink_burst_profile.relative_power_offset_ul_burst_mac_mgmt_msg", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_207_ul_initial_transmit_timing, + { + "UL Initial Transmit Timing", "wmx.ucd.uplink_burst_profile.ul_initial_transmit_timing", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_210_fast_feedback_region, + { + "Fast Feedback Region", "wmx.ucd.uplink_burst_profile.fast_feedback_region", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_211_harq_ack_region, + { + "HARQ ACK Region", "wmx.ucd.uplink_burst_profile.harq_ack_region", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_212_ranging_region, + { + "Ranging Region", "wmx.ucd.uplink_burst_profile.ranging_region", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_213_sounding_region, + { + "Sounding Region", "wmx.ucd.uplink_burst_profile.sounding_region", + FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_186_upper_bound_aas_preamble, + { + "Upper Bound AAS Preamble (in units of 0.25 dB)", "wmx.ucd.upper_bound_aas_preamble", + FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_tlv_t_189_use_cqich_indication_flag, + { + "Use CQICH Indication Flag", "wmx.ucd.use_cqich_indication_flag", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_ho_ranging_start, + { + "Initial Backoff Window Size for MS Performing Initial During Handover Process", "wmx.ucd.ho_ranging_start", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_ho_ranging_end, + { + "Final Backoff Window Size for MS Performing Initial During Handover Process", "wmx.ucd.ho_ranging_end", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_initial_range_backoff_start, + { + "Initial Ranging Backoff Start", "wmx.ucd.initial_range_backoff_start", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_initial_range_backoff_end, + { + "Initial Ranging Backoff End", "wmx.ucd.initial_range_backoff_end", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_bandwidth_backoff_start, + { + "Bandwidth Request Backoff Start", "wmx.ucd.bandwidth_backoff_start", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_bandwidth_backoff_end, + { + "Bandwidth Request Backoff End", "wmx.ucd.bandwidth_backoff_end", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_periodic_ranging_backoff_start, + { + "Periodic Ranging Backoff Start", "wmx.ucd.periodic_ranging_backoff_start", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_periodic_ranging_backoff_end, + { + "Periodic Ranging Backoff End", "wmx.ucd.periodic_ranging_backoff_end", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_config_change_count, + { + "Configuration Change Count", "wmx.ucd.config_change_count", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_ranging_backoff_start, + { + "Ranging Backoff Start", "wmx.ucd.ranging_backoff_start", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_ranging_backoff_end, + { + "Ranging Backoff End", "wmx.ucd.ranging_backoff_end", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_request_backoff_start, + { + "Request Backoff Start", "wmx.ucd.request_backoff_start", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + { + &hf_ucd_request_backoff_end, + { + "Request Backoff End", "wmx.ucd.request_backoff_end", + FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL + } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_mac_mgmt_msg_ucd_decoder, + }; + + proto_mac_mgmt_msg_ucd_decoder = proto_register_protocol ( + "WiMax UCD Messages", /* name */ + "WiMax UCD", /* short name */ + "wmx.ucd" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_ucd_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + ucd_handle = register_dissector("mac_mgmt_msg_ucd_handler", dissect_mac_mgmt_msg_ucd_decoder, proto_mac_mgmt_msg_ucd_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_ucd(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_UCD, ucd_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: + */ diff --git a/plugins/epan/wimax/msg_ulmap.c b/plugins/epan/wimax/msg_ulmap.c new file mode 100644 index 00000000..b4909cc5 --- /dev/null +++ b/plugins/epan/wimax/msg_ulmap.c @@ -0,0 +1,2942 @@ +/* msg_ulmap.c + * WiMax MAC Management UL-MAP Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Mike Harvey + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include +#include "wimax_mac.h" +#include "wimax_bits.h" +#include "wimax_utils.h" + +extern gboolean include_cor2_changes; + +static dissector_handle_t ulmap_handle; + +void proto_register_mac_mgmt_msg_ulmap(void); +void proto_reg_handoff_mac_mgmt_msg_ulmap(void); + +#define MAC_MGMT_MSG_ULMAP 3 + +#define XBIT_HF(bits, hf) \ + proto_tree_add_bits_item(tree, hf, tvb, bit, bits, ENC_BIG_ENDIAN); bit += bits; + +#define XBIT_HF_VALUE(var, bits, hf) \ + do { \ + var = TVB_BIT_BITS(bit, tvb, bits); \ + proto_tree_add_bits_item(tree, hf, tvb, bit, bits, ENC_BIG_ENDIAN); \ + bit += bits; \ + } while(0) + +#define VNIB(var, nibs, hf) \ + do { \ + var = TVB_NIB_NIBS(nib, tvb, nibs); \ + proto_tree_add_uint(tree, hf, tvb, NIBHI(nib, nibs), var); \ + nib += nibs; \ + } while(0) + +/* from msg_ucd.c */ +extern guint cqich_id_size; /* Set for CQICH_Alloc_IE */ + +/* from msg_dlmap.c */ +extern gint harq; +extern gint ir_type; +extern gint N_layer; +extern gint RCID_Type; + +static gint proto_mac_mgmt_msg_ulmap_decoder = -1; + +static gint ett_ulmap = -1; +static gint ett_ulmap_ie = -1; +static gint ett_ulmap_ffb = -1; +/* static gint ett_ulmap_c = -1; */ +/* static gint ett_ulmap_c_ie = -1; */ +/* static gint ett_ulmap_s = -1; */ +/* static gint ett_ulmap_s_ie = -1; */ +static gint ett_287_1 = -1; +static gint ett_287_2 = -1; +static gint ett_289 = -1; +static gint ett_290 = -1; +static gint ett_290b = -1; +static gint ett_291 = -1; +static gint ett_292 = -1; +static gint ett_293 = -1; +static gint ett_294 = -1; +static gint ett_295 = -1; +static gint ett_299 = -1; +static gint ett_300 = -1; +static gint ett_302 = -1; +static gint ett_302a = -1; +static gint ett_302b = -1; +static gint ett_302c = -1; +static gint ett_302d = -1; +static gint ett_302e = -1; +static gint ett_302f = -1; +static gint ett_302g = -1; +static gint ett_302h = -1; +static gint ett_302i = -1; +static gint ett_302j = -1; +static gint ett_302k = -1; +static gint ett_302l = -1; +static gint ett_302m = -1; +static gint ett_302n = -1; +static gint ett_302o = -1; +static gint ett_302p = -1; +static gint ett_302q = -1; +static gint ett_302r = -1; +static gint ett_302s = -1; +static gint ett_302t = -1; +static gint ett_302u = -1; +static gint ett_302v = -1; +static gint ett_306 = -1; +static gint ett_306_ul = -1; +static gint ett_308b = -1; +static gint ett_315d = -1; + +#define DCD_DOWNLINK_BURST_PROFILE 1 +#define DCD_BS_EIRP 2 +#define DCD_FRAME_DURATION 3 +#define DCD_PHY_TYPE 4 +#define DCD_POWER_ADJUSTMENT 5 +#define DCD_CHANNEL_NR 6 +#define DCD_TTG 7 +#define DCD_RTG 8 +#define DCD_RSS 9 +#define DCD_CHANNEL_SWITCH_FRAME_NR 10 +#define DCD_FREQUENCY 12 +#define DCD_BS_ID 13 +#define DCD_FRAME_DURATION_CODE 14 +#define DCD_FRAME_NR 15 +#define DCD_SIZE_CQICH_ID 16 +#define DCD_H_ARQ_ACK_DELAY 17 +#define DCD_MAC_VERSION 148 +#define DCD_RESTART_COUNT 154 + +#define DCD_BURST_FREQUENCY 1 +#define DCD_BURST_FEC_CODE_TYPE 150 +#define DCD_BURST_DIUC_EXIT_THRESHOLD 151 +#define DCD_BURST_DIUC_ENTRY_THRESHOLD 152 +#define DCD_BURST_TCS_ENABLE 153 + +#define DCD_TLV_T_541_TYPE_FUNCTION_ACTION 1 +#define DCD_TLV_T542_TRIGGER_VALUE 2 +#define DCD_TLV_T_543_TRIGGER_AVERAGING_DURATION 3 +#define DCD_TLV_T_19_PERMUTATION_TYPE_FOR_BROADCAST_REGION_IN_HARQ_ZONE 19 +#define DCD_TLV_T_20_MAXIMUM_RETRANSMISSION 20 +#define DCD_TLV_T_21_DEFAULT_RSSI_AND_CINR_AVERAGING_PARAMETER 21 +#define DCD_TLV_T_22_DL_AMC_ALLOCATED_PHYSICAL_BANDS_BITMAP 22 +#define DCD_TLV_T_31_H_ADD_THRESHOLD 31 +#define DCD_TLV_T_32_H_DELETE_THRESHOLD 32 +#define DCD_TLV_T_33_ASR 33 +#define DCD_TLV_T_34_DL_REGION_DEFINITION 34 +#define DCD_TLV_T_35_PAGING_GROUP_ID 35 +#define DCD_TLV_T_36_TUSC1_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP 36 +#define DCD_TLV_T_37_TUSC2_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP 37 +#define DCD_TLV_T_45_PAGING_INTERVAL_LENGTH 45 +#define DCD_TLV_T_50_HO_TYPE_SUPPORT 50 +#define DCD_TLV_T_51_HYSTERSIS_MARGIN 51 +#define DCD_TLV_T_52_TIME_TO_TRIGGER_DURATION 52 +#define DCD_TLV_T_54_TRIGGER 54 +#define DCD_TLV_T_153_DOWNLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES 153 + +#define UL_MAP_NCT_PMP 0 +#define UL_MAP_NCT_DM 1 +#define UL_MAP_NCT_PTP 2 + +#if 0 +/* NCT messages */ +static const value_string nct_msgs[] = +{ + { UL_MAP_NCT_PMP, "PMP" }, + { UL_MAP_NCT_PMP, "DM" }, + { UL_MAP_NCT_PMP, "PTP" }, + { 0, NULL } +}; +#endif + +#if 0 +/* Repetition Coding Indications */ +static const value_string rep_msgs[] = +{ + { 0, "No Repetition Coding" }, + { 1, "Repetition Coding of 2 Used" }, + { 2, "Repetition Coding of 4 Used" }, + { 3, "Repetition Coding of 6 Used" }, + { 0, NULL } +}; +#endif + +#if 0 +/* DL Frame Prefix Coding Indications */ +static const value_string boost_msgs[] = +{ + { 0, "Normal (not boosted)" }, + { 1, "+6dB" }, + { 2, "-6dB" }, + { 3, "+9dB" }, + { 4, "+3dB" }, + { 5, "-3dB" }, + { 6, "-9dB" }, + { 7, "-12dB" }, + { 0, NULL } +}; +#endif + +/* ul-map fields */ +static gint hf_ulmap_reserved = -1; +static gint hf_ulmap_ucd_count = -1; +static gint hf_ulmap_alloc_start_time = -1; +static gint hf_ulmap_ofdma_sym = -1; +static gint hf_ulmap_ie_diuc_ext = -1; +static gint hf_ulmap_ie_diuc_ext2 = -1; +static gint hf_ulmap_ie_length = -1; +static gint hf_ulmap_ie_reserved_extended2_duic = -1; +static gint hf_ulmap_ie_reserved_extended_duic = -1; +/* static gint hf_ulmap_fch_expected = -1; */ + +/* static gint hf_ulmap_ie = -1; */ + +static gint hf_ulmap_ie_cid = -1; +static gint hf_ulmap_ie_uiuc = -1; +static gint hf_ulmap_uiuc12_symofs = -1; +static gint hf_ulmap_uiuc12_subofs = -1; +static gint hf_ulmap_uiuc12_numsym = -1; +static gint hf_ulmap_uiuc12_numsub = -1; +static gint hf_ulmap_uiuc12_method = -1; +static gint hf_ulmap_uiuc12_dri = -1; +static gint hf_ulmap_uiuc10_dur = -1; +static gint hf_ulmap_uiuc10_rep = -1; +static gint hf_ulmap_uiuc10_slot_offset = -1; + +static gint hf_ulmap_uiuc14_dur = -1; +static gint hf_ulmap_uiuc14_uiuc = -1; +static gint hf_ulmap_uiuc14_rep = -1; +static gint hf_ulmap_uiuc14_idx = -1; +static gint hf_ulmap_uiuc14_code = -1; +static gint hf_ulmap_uiuc14_sym = -1; +static gint hf_ulmap_uiuc14_sub = -1; +static gint hf_ulmap_uiuc14_bwr = -1; + +/* static gint hf_ulmap_uiuc11_ext = -1; */ +/* static gint hf_ulmap_uiuc11_len = -1; */ +/* static gint hf_ulmap_uiuc11_data = -1; */ +/* static gint hf_ulmap_uiuc15_ext = -1; */ +/* static gint hf_ulmap_uiuc15_len = -1; */ +/* static gint hf_ulmap_uiuc15_data = -1; */ + +static gint hf_ulmap_uiuc0_symofs = -1; +static gint hf_ulmap_uiuc0_subofs = -1; +static gint hf_ulmap_uiuc0_numsym = -1; +static gint hf_ulmap_uiuc0_numsub = -1; +static gint hf_ulmap_uiuc0_rsv = -1; + +static gint hf_ulmap_uiuc13_symofs = -1; +static gint hf_ulmap_uiuc13_subofs = -1; +static gint hf_ulmap_uiuc13_numsym = -1; +static gint hf_ulmap_uiuc13_numsub = -1; +static gint hf_ulmap_uiuc13_papr = -1; +static gint hf_ulmap_uiuc13_zone = -1; +static gint hf_ulmap_uiuc13_rsv = -1; +/* static gint hf_ulmap_crc16 = -1; */ +/* static gint hf_ulmap_crc16_status = -1; */ +static gint hf_ulmap_padding = -1; + +/* Generated via "one time" script to help create filterable fields */ +static int hf_ulmap_dedicated_ul_control_length = -1; +static int hf_ulmap_dedicated_ul_control_control_header = -1; +static int hf_ulmap_dedicated_ul_control_num_sdma_layers = -1; +static int hf_ulmap_dedicated_ul_control_pilot_pattern = -1; +static int hf_ulmap_dedicated_mimo_ul_control_matrix = -1; +static int hf_ulmap_dedicated_mimo_ul_control_n_layer = -1; +static int hf_ulmap_harq_chase_dedicated_ul_control_indicator = -1; +static int hf_ulmap_harq_chase_uiuc = -1; +static int hf_ulmap_harq_chase_repetition_coding_indication = -1; +static int hf_ulmap_harq_chase_duration = -1; +static int hf_ulmap_harq_chase_acid = -1; +static int hf_ulmap_harq_chase_ai_sn = -1; +static int hf_ulmap_harq_chase_ack_disable = -1; +static int hf_ulmap_reserved_uint = -1; +static int hf_ulmap_harq_ir_ctc_dedicated_ul_control_indicator = -1; +static int hf_ulmap_harq_ir_ctc_nep = -1; +static int hf_ulmap_harq_ir_ctc_nsch = -1; +static int hf_ulmap_harq_ir_ctc_spid = -1; +static int hf_ulmap_harq_ir_ctc_acin = -1; +static int hf_ulmap_harq_ir_ctc_ai_sn = -1; +static int hf_ulmap_harq_ir_ctc_ack_disable = -1; +static int hf_ulmap_harq_ir_cc_dedicated_ul_control_indicator = -1; +static int hf_ulmap_harq_ir_cc_uiuc = -1; +static int hf_ulmap_harq_ir_cc_repetition_coding_indication = -1; +static int hf_ulmap_harq_ir_cc_duration = -1; +static int hf_ulmap_harq_ir_cc_spid = -1; +static int hf_ulmap_harq_ir_cc_acid = -1; +static int hf_ulmap_harq_ir_cc_ai_sn = -1; +static int hf_ulmap_harq_ir_cc_ack_disable = -1; +static int hf_ulmap_mimo_ul_chase_harq_mu_indicator = -1; +static int hf_ulmap_mimo_ul_chase_harq_dedicated_mimo_ulcontrol_indicator = -1; +static int hf_ulmap_mimo_ul_chase_harq_ack_disable = -1; +static int hf_ulmap_mimo_ul_chase_harq_matrix = -1; +static int hf_ulmap_mimo_ul_chase_harq_duration = -1; +static int hf_ulmap_mimo_ul_chase_harq_uiuc = -1; +static int hf_ulmap_mimo_ul_chase_harq_repetition_coding_indication = -1; +static int hf_ulmap_mimo_ul_chase_harq_acid = -1; +static int hf_ulmap_mimo_ul_chase_harq_ai_sn = -1; +static int hf_ulmap_mimo_ul_ir_harq_mu_indicator = -1; +static int hf_ulmap_mimo_ul_ir_harq_dedicated_mimo_ul_control_indicator = -1; +static int hf_ulmap_mimo_ul_ir_harq_ack_disable = -1; +static int hf_ulmap_mimo_ul_ir_harq_matrix = -1; +static int hf_ulmap_mimo_ul_ir_harq_nsch = -1; +static int hf_ulmap_mimo_ul_ir_harq_nep = -1; +static int hf_ulmap_mimo_ul_ir_harq_spid = -1; +static int hf_ulmap_mimo_ul_ir_harq_acid = -1; +static int hf_ulmap_mimo_ul_ir_harq_ai_sn = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_mu_indicator = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_dedicated_mimo_ul_control_indicator = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_ack_disable = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_matrix = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_duration = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_uiuc = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_repetition_coding_indication = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_acid = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_ai_sn = -1; +static int hf_ulmap_mimo_ul_ir_harq_cc_spid = -1; +static int hf_ulmap_mimo_ul_stc_harq_tx_count = -1; +static int hf_ulmap_mimo_ul_stc_harq_duration = -1; +static int hf_ulmap_mimo_ul_stc_harq_sub_burst_offset_indication = -1; +static int hf_ulmap_mimo_ul_stc_harq_sub_burst_offset = -1; +static int hf_ulmap_mimo_ul_stc_harq_ack_disable = -1; +static int hf_ulmap_mimo_ul_stc_harq_uiuc = -1; +static int hf_ulmap_mimo_ul_stc_harq_repetition_coding_indication = -1; +static int hf_ulmap_mimo_ul_stc_harq_acid = -1; +static int hf_ulmap_power_control = -1; +static int hf_ulmap_power_measurement_frame = -1; +static int hf_ulmap_mini_subcha_alloc_extended_2_uiuc = -1; +static int hf_ulmap_mini_subcha_alloc_length = -1; +static int hf_ulmap_mini_subcha_alloc_ctype = -1; +static int hf_ulmap_mini_subcha_alloc_duration = -1; +static int hf_ulmap_mini_subcha_alloc_cid = -1; +static int hf_ulmap_mini_subcha_alloc_uiuc = -1; +static int hf_ulmap_mini_subcha_alloc_repetition = -1; +static int hf_ulmap_mini_subcha_alloc_padding = -1; +static int hf_ulmap_aas_ul_extended_uiuc = -1; +static int hf_ulmap_aas_ul_length = -1; +static int hf_ulmap_aas_ul_permutation = -1; +static int hf_ulmap_aas_ul_ul_permbase = -1; +static int hf_ulmap_aas_ul_ofdma_symbol_offset = -1; +static int hf_ulmap_aas_ul_aas_zone_length = -1; +static int hf_ulmap_aas_ul_uplink_preamble_config = -1; +static int hf_ulmap_aas_ul_preamble_type = -1; +static int hf_ulmap_cqich_alloc_extended_uiuc = -1; +static int hf_ulmap_cqich_alloc_length = -1; +static int hf_ulmap_cqich_alloc_cqich_id = -1; +static int hf_ulmap_cqich_alloc_allocation_offset = -1; +static int hf_ulmap_cqich_alloc_period = -1; +static int hf_ulmap_cqich_alloc_frame_offset = -1; +static int hf_ulmap_cqich_alloc_duration = -1; +static int hf_ulmap_cqich_alloc_report_configuration_included = -1; +static int hf_ulmap_cqich_alloc_feedback_type = -1; +static int hf_ulmap_cqich_alloc_report_type = -1; +static int hf_ulmap_cqich_alloc_cinr_preamble_report_type = -1; +static int hf_ulmap_cqich_alloc_zone_permutation = -1; +static int hf_ulmap_cqich_alloc_zone_type = -1; +static int hf_ulmap_cqich_alloc_zone_prbs_id = -1; +static int hf_ulmap_cqich_alloc_major_group_indication = -1; +static int hf_ulmap_cqich_alloc_pusc_major_group_bitmap = -1; +static int hf_ulmap_cqich_alloc_cinr_zone_measurement_type = -1; +static int hf_ulmap_cqich_alloc_averaging_parameter_included = -1; +static int hf_ulmap_cqich_alloc_averaging_parameter = -1; +static int hf_ulmap_cqich_alloc_mimo_permutation_feedback_cycle = -1; +static int hf_ulmap_zone_extended_uiuc = -1; +static int hf_ulmap_zone_length = -1; +static int hf_ulmap_zone_ofdma_symbol_offset = -1; +static int hf_ulmap_zone_permutation = -1; +static int hf_ulmap_zone_ul_permbase = -1; +static int hf_ulmap_zone_amc_type = -1; +static int hf_ulmap_zone_use_all_sc_indicator = -1; +static int hf_ulmap_zone_disable_subchannel_rotation = -1; +static int hf_ulmap_phymod_ul_extended_uiuc = -1; +static int hf_ulmap_phymod_ul_length = -1; +static int hf_ulmap_phymod_ul_preamble_modifier_type = -1; +static int hf_ulmap_phymod_ul_preamble_frequency_shift_index = -1; +static int hf_ulmap_phymod_ul_preamble_time_shift_index = -1; +static int hf_ulmap_phymod_ul_pilot_pattern_modifier = -1; +static int hf_ulmap_phymod_ul_pilot_pattern_index = -1; +static int hf_ulmap_fast_tracking_extended_uiuc = -1; +static int hf_ulmap_fast_tracking_length = -1; +static int hf_ulmap_fast_tracking_map_index = -1; +static int hf_ulmap_fast_tracking_power_correction = -1; +static int hf_ulmap_fast_tracking_frequency_correction = -1; +static int hf_ulmap_fast_tracking_time_correction = -1; +static int hf_ulmap_pusc_burst_allocation_extended_uiuc = -1; +static int hf_ulmap_pusc_burst_allocation_length = -1; +static int hf_ulmap_pusc_burst_allocation_uiuc = -1; +static int hf_ulmap_pusc_burst_allocation_segment = -1; +static int hf_ulmap_pusc_burst_allocation_ul_permbase = -1; +static int hf_ulmap_pusc_burst_allocation_ofdma_symbol_offset = -1; +static int hf_ulmap_pusc_burst_allocation_subchannel_offset = -1; +static int hf_ulmap_pusc_burst_allocation_duration = -1; +static int hf_ulmap_pusc_burst_allocation_repetition_coding_indication = -1; +static int hf_ulmap_fast_ranging_extended_uiuc = -1; +static int hf_ulmap_fast_ranging_length = -1; +static int hf_ulmap_fast_ranging_ho_id_indicator = -1; +static int hf_ulmap_fast_ranging_ho_id = -1; +static int hf_ulmap_fast_ranging_mac_address = -1; +static int hf_ulmap_fast_ranging_uiuc = -1; +static int hf_ulmap_fast_ranging_duration = -1; +static int hf_ulmap_fast_ranging_repetition_coding_indication = -1; +static int hf_ulmap_allocation_start_extended_uiuc = -1; +static int hf_ulmap_allocation_start_length = -1; +static int hf_ulmap_allocation_start_ofdma_symbol_offset = -1; +static int hf_ulmap_allocation_start_subchannel_offset = -1; +static int hf_ulmap_cqich_enhanced_alloc_extended_2_uiuc = -1; +static int hf_ulmap_cqich_enhanced_alloc_length = -1; +static int hf_ulmap_cqich_enhanced_alloc_cqich_id = -1; +static int hf_ulmap_cqich_enhanced_alloc_period = -1; +static int hf_ulmap_cqich_enhanced_alloc_frame_offset = -1; +static int hf_ulmap_cqich_enhanced_alloc_duration = -1; +static int hf_ulmap_cqich_enhanced_alloc_cqich_num = -1; +static int hf_ulmap_cqich_enhanced_alloc_feedback_type = -1; +static int hf_ulmap_cqich_enhanced_alloc_allocation_index = -1; +static int hf_ulmap_cqich_enhanced_alloc_cqich_type = -1; +static int hf_ulmap_cqich_enhanced_alloc_sttd_indication = -1; +static int hf_ulmap_cqich_enhanced_alloc_band_amc_precoding_mode = -1; +static int hf_ulmap_cqich_enhanced_alloc_nr_precoders_feedback = -1; +static int hf_ulmap_anchor_bs_switch_extended_2_uiuc = -1; +static int hf_ulmap_anchor_bs_switch_length = -1; +static int hf_ulmap_anchor_bs_switch_n_anchor_bs_switch = -1; +static int hf_ulmap_anchor_bs_switch_reduced_cid = -1; +static int hf_ulmap_anchor_bs_switch_action_code = -1; +static int hf_ulmap_anchor_bs_switch_action_time = -1; +static int hf_ulmap_anchor_bs_switch_temp_bs_id = -1; +static int hf_ulmap_anchor_bs_switch_ak_change_indicator = -1; +static int hf_ulmap_anchor_bs_switch_cqich_allocation_indicator = -1; +static int hf_ulmap_anchor_bs_switch_cqich_id = -1; +static int hf_ulmap_anchor_bs_switch_feedback_channel_offset = -1; +static int hf_ulmap_anchor_bs_switch_period = -1; +static int hf_ulmap_anchor_bs_switch_frame_offset = -1; +static int hf_ulmap_anchor_bs_switch_duration = -1; +static int hf_ulmap_anchor_bs_switch_mimo_permutation_feedback_code = -1; +static int hf_ulmap_sounding_command_extended_2_uiuc = -1; +static int hf_ulmap_sounding_command_length = -1; +static int hf_ulmap_sounding_command_type = -1; +static int hf_ulmap_sounding_command_send_sounding_report_flag = -1; +static int hf_ulmap_sounding_command_relevance_flag = -1; +static int hf_ulmap_sounding_command_relevance = -1; +static int hf_ulmap_sounding_command_include_additional_feedback = -1; +static int hf_ulmap_sounding_command_num_sounding_symbols = -1; +static int hf_ulmap_sounding_command_separability_type = -1; +static int hf_ulmap_sounding_command_max_cyclic_shift_index_p = -1; +static int hf_ulmap_sounding_command_decimation_value = -1; +static int hf_ulmap_sounding_command_decimation_offset_randomization = -1; +static int hf_ulmap_sounding_command_symbol_index = -1; +static int hf_ulmap_sounding_command_number_of_cids = -1; +static int hf_ulmap_sounding_command_shorted_basic_cid = -1; +static int hf_ulmap_sounding_command_power_assignment_method = -1; +static int hf_ulmap_sounding_command_power_boost = -1; +static int hf_ulmap_sounding_command_multi_antenna_flag = -1; +static int hf_ulmap_sounding_command_allocation_mode = -1; +static int hf_ulmap_sounding_command_band_bit_map = -1; +static int hf_ulmap_sounding_command_starting_frequency_band = -1; +static int hf_ulmap_sounding_command_number_of_frequency_bands = -1; +static int hf_ulmap_sounding_command_cyclic_time_shift_index = -1; +static int hf_ulmap_sounding_command_decimation_offset = -1; +static int hf_ulmap_sounding_command_use_same_symbol_for_additional_feedback = -1; +static int hf_ulmap_sounding_command_periodicity = -1; +static int hf_ulmap_sounding_command_permutation = -1; +static int hf_ulmap_sounding_command_dl_permbase = -1; +static int hf_ulmap_sounding_command_shortened_basic_cid = -1; +static int hf_ulmap_sounding_command_subchannel_offset = -1; +static int hf_ulmap_sounding_command_number_of_subchannels = -1; +static int hf_ulmap_harq_ulmap_extended_2_uiuc = -1; +static int hf_ulmap_harq_ulmap_length = -1; +static int hf_ulmap_harq_ulmap_rcid_type = -1; +static int hf_ulmap_harq_ulmap_mode = -1; +static int hf_ulmap_harq_ulmap_allocation_start_indication = -1; +static int hf_ulmap_harq_ulmap_ofdma_symbol_offset = -1; +static int hf_ulmap_harq_ulmap_subchannel_offset = -1; +static int hf_ulmap_harq_ulmap_n_sub_burst = -1; +static int hf_ulmap_harq_ackch_region_alloc_extended_2_uiuc = -1; +static int hf_ulmap_harq_ackch_region_alloc_length = -1; +static int hf_ulmap_harq_ackch_region_alloc_ofdma_symbol_offset = -1; +static int hf_ulmap_harq_ackch_region_alloc_subchannel_offset = -1; +static int hf_ulmap_harq_ackch_region_alloc_num_ofdma_symbols = -1; +static int hf_ulmap_harq_ackch_region_alloc_num_subchannels = -1; +static int hf_ulmap_aas_sdma_extended_2_uiuc = -1; +static int hf_ulmap_aas_sdma_length = -1; +static int hf_ulmap_aas_sdma_rcid_type = -1; +static int hf_ulmap_aas_sdma_num_burst_region = -1; +static int hf_ulmap_aas_sdma_slot_offset = -1; +static int hf_ulmap_aas_sdma_slot_duration = -1; +static int hf_ulmap_aas_sdma_number_of_users = -1; +static int hf_ulmap_aas_sdma_encoding_mode = -1; +static int hf_ulmap_aas_sdma_power_adjust = -1; +static int hf_ulmap_aas_sdma_pilot_pattern_modifier = -1; +static int hf_ulmap_aas_sdma_preamble_modifier_index = -1; +static int hf_ulmap_aas_sdma_pilot_pattern = -1; +static int hf_ulmap_aas_sdma_diuc = -1; +static int hf_ulmap_aas_sdma_repetition_coding_indication = -1; +static int hf_ulmap_aas_sdma_acid = -1; +static int hf_ulmap_aas_sdma_ai_sn = -1; +static int hf_ulmap_aas_sdma_nep = -1; +static int hf_ulmap_aas_sdma_nsch = -1; +static int hf_ulmap_aas_sdma_spid = -1; +static int hf_ulmap_aas_sdma_power_adjustment = -1; +static int hf_ulmap_feedback_polling_extended_2_uiuc = -1; +static int hf_ulmap_feedback_polling_length = -1; +static int hf_ulmap_feedback_polling_num_allocation = -1; +static int hf_ulmap_feedback_polling_dedicated_ul_allocation_included = -1; +static int hf_ulmap_feedback_polling_basic_cid = -1; +static int hf_ulmap_feedback_polling_allocation_duration = -1; +static int hf_ulmap_feedback_polling_type = -1; +static int hf_ulmap_feedback_polling_frame_offset = -1; +static int hf_ulmap_feedback_polling_period = -1; +static int hf_ulmap_feedback_polling_uiuc = -1; +static int hf_ulmap_feedback_polling_ofdma_symbol_offset = -1; +static int hf_ulmap_feedback_polling_subchannel_offset = -1; +static int hf_ulmap_feedback_polling_duration = -1; +static int hf_ulmap_feedback_polling_repetition_coding_indication = -1; +static int hf_ulmap_reduced_aas_aas_zone_configuration_included = -1; +static int hf_ulmap_reduced_aas_aas_zone_position_included = -1; +static int hf_ulmap_reduced_aas_ul_map_information_included = -1; +static int hf_ulmap_reduced_aas_phy_modification_included = -1; +static int hf_ulmap_reduced_aas_power_control_included = -1; +static int hf_ulmap_reduced_aas_include_feedback_header = -1; +static int hf_ulmap_reduced_aas_encoding_mode = -1; +static int hf_ulmap_reduced_aas_permutation = -1; +static int hf_ulmap_reduced_aas_ul_permbase = -1; +static int hf_ulmap_reduced_aas_preamble_indication = -1; +static int hf_ulmap_reduced_aas_padding = -1; +static int hf_ulmap_reduced_aas_zone_symbol_offset = -1; +static int hf_ulmap_reduced_aas_zone_length = -1; +static int hf_ulmap_reduced_aas_ucd_count = -1; +static int hf_ulmap_reduced_aas_private_map_alloc_start_time = -1; +static int hf_ulmap_reduced_aas_pilot_pattern_index = -1; +static int hf_ulmap_reduced_aas_preamble_select = -1; +static int hf_ulmap_reduced_aas_preamble_shift_index = -1; +static int hf_ulmap_reduced_aas_pilot_pattern_modifier = -1; +static int hf_ulmap_reduced_aas_power_control = -1; +static int hf_ulmap_reduced_aas_ul_frame_offset = -1; +static int hf_ulmap_reduced_aas_slot_offset = -1; +static int hf_ulmap_reduced_aas_slot_duration = -1; +static int hf_ulmap_reduced_aas_uiuc_nep = -1; +static int hf_ulmap_reduced_aas_acid = -1; +static int hf_ulmap_reduced_aas_ai_sn = -1; +static int hf_ulmap_reduced_aas_nsch = -1; +static int hf_ulmap_reduced_aas_spid = -1; +static int hf_ulmap_reduced_aas_repetition_coding_indication = -1; + +static expert_field ei_ulmap_not_implemented = EI_INIT; + +/* This gets called each time a capture file is loaded. */ +void init_wimax_globals(void) +{ + cqich_id_size = 0; + harq = 0; + ir_type = 0; + N_layer = 0; + RCID_Type = 0; +} + +/******************************************************************** + * UL-MAP HARQ Sub-Burst IEs + * 8.4.5.4.24 table 302j + * these functions take offset/length in bits + *******************************************************************/ + +static gint Dedicated_UL_Control_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24.1 Dedicated_UL_Control_IE -- table 302r */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + gint sdma; + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302r, NULL, "Dedicated_UL_Control_IE"); + + XBIT_HF(4, hf_ulmap_dedicated_ul_control_length); + XBIT_HF_VALUE(sdma, 4, hf_ulmap_dedicated_ul_control_control_header); + if ((sdma & 1) == 1) { + XBIT_HF(2, hf_ulmap_dedicated_ul_control_num_sdma_layers); + XBIT_HF(2, hf_ulmap_dedicated_ul_control_pilot_pattern); + } + return (bit - offset); /* length in bits */ +} + +static gint Dedicated_MIMO_UL_Control_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24.2 Dedicated_MIMO_UL_Control_IE -- table 302s */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302s, NULL, "Dedicated_MIMO_UL_Control_IE"); + + XBIT_HF(2, hf_ulmap_dedicated_mimo_ul_control_matrix); + XBIT_HF_VALUE(N_layer, 2, hf_ulmap_dedicated_mimo_ul_control_n_layer); + + return (bit - offset); /* length in bits */ +} + +/* begin Sub-Burst IEs */ + +static gint UL_HARQ_Chase_Sub_Burst_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24 UL_HARQ_Chase_sub_burst_IE -- table 302k */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + /*proto_item *generic_item = NULL;*/ + gint duci; + /*guint16 calculated_crc;*/ + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, BITHI(offset,length), ett_302k, NULL, "UL_HARQ_Chase_Sub_Burst_IE"); + + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + XBIT_HF_VALUE(duci, 1, hf_ulmap_harq_chase_dedicated_ul_control_indicator); + if (duci == 1) { + bit += Dedicated_UL_Control_IE(tree, bit, length, tvb); + } + XBIT_HF(4, hf_ulmap_harq_chase_uiuc); + XBIT_HF(2, hf_ulmap_harq_chase_repetition_coding_indication); + XBIT_HF(10, hf_ulmap_harq_chase_duration); + XBIT_HF(4, hf_ulmap_harq_chase_acid); + XBIT_HF(1, hf_ulmap_harq_chase_ai_sn); + XBIT_HF(1, hf_ulmap_harq_chase_ack_disable); + XBIT_HF(1, hf_ulmap_reserved_uint); + +#if 0 + if (include_cor2_changes) + { + calculated_crc = wimax_mac_calc_crc16((guint8 *)tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BITHI(bit,16), hf_ulmap_crc16, hf_ulmap_crc16_status, &ei_ulmap_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + } +#endif + + return (bit - offset); /* length in bits */ +} + +static gint UL_HARQ_IR_CTC_Sub_Burst_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24 UL_HARQ_IR_CTC_sub_burst_IE -- table 302l */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + /*proto_item *generic_item = NULL;*/ + gint duci; + /*guint16 calculated_crc;*/ + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302l, NULL, "UL_HARQ_IR_CTC_Sub_Burst_IE"); + + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + XBIT_HF_VALUE(duci, 1, hf_ulmap_harq_ir_ctc_dedicated_ul_control_indicator); + if (duci == 1) { + bit += Dedicated_UL_Control_IE(tree, bit, length, tvb); + } + XBIT_HF(4, hf_ulmap_harq_ir_ctc_nep); + XBIT_HF(4, hf_ulmap_harq_ir_ctc_nsch); + XBIT_HF(2, hf_ulmap_harq_ir_ctc_spid); + XBIT_HF(4, hf_ulmap_harq_ir_ctc_acin); + XBIT_HF(1, hf_ulmap_harq_ir_ctc_ai_sn); + XBIT_HF(1, hf_ulmap_harq_ir_ctc_ack_disable); + XBIT_HF(3, hf_ulmap_reserved_uint); + +#if 0 + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16((guint8 *)tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BITHI(bit,16), hf_ulmap_crc16, hf_ulmap_crc16_status, &ei_ulmap_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + bit += 16; + } +#endif + + return (bit - offset); /* length in bits */ +} + +static gint UL_HARQ_IR_CC_Sub_Burst_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24 UL_HARQ_IR_CC_sub_burst_IE -- table 302m */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + /*proto_item *generic_item = NULL;*/ + gint duci; + /*guint16 calculated_crc;*/ + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302m, NULL, "UL_HARQ_IR_CC_Sub_Burst_IE"); + + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + XBIT_HF_VALUE(duci, 1, hf_ulmap_harq_ir_cc_dedicated_ul_control_indicator); + if (duci == 1) { + bit += Dedicated_UL_Control_IE(tree, bit, length, tvb); + } + XBIT_HF(4, hf_ulmap_harq_ir_cc_uiuc); + XBIT_HF(2, hf_ulmap_harq_ir_cc_repetition_coding_indication); + XBIT_HF(10, hf_ulmap_harq_ir_cc_duration); + XBIT_HF(2, hf_ulmap_harq_ir_cc_spid); + XBIT_HF(4, hf_ulmap_harq_ir_cc_acid); + XBIT_HF(1, hf_ulmap_harq_ir_cc_ai_sn); + XBIT_HF(1, hf_ulmap_harq_ir_cc_ack_disable); + XBIT_HF(3, hf_ulmap_reserved_uint); + +#if 0 + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16((guint8 *)tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BITHI(bit,16), hf_ulmap_crc16, hf_ulmap_crc16_status, &ei_ulmap_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + + bit += 16; + } +#endif + + return (bit - offset); /* length in bits */ +} + +static gint MIMO_UL_Chase_HARQ_Sub_Burst_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24 MIMO_UL_Chase_HARQ_Sub_Burst_IE -- table 302n */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + /*proto_item *generic_item = NULL;*/ + gint muin,dmci,ackd,i; + /*guint16 calculated_crc;*/ + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302n, NULL, "MIMO_UL_Chase_HARQ_Sub_Burst_IE"); + + XBIT_HF_VALUE(muin, 1, hf_ulmap_mimo_ul_chase_harq_mu_indicator); + XBIT_HF_VALUE(dmci, 1, hf_ulmap_mimo_ul_chase_harq_dedicated_mimo_ulcontrol_indicator); + XBIT_HF_VALUE(ackd, 1, hf_ulmap_mimo_ul_chase_harq_ack_disable); + if (muin == 0) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + if (dmci) { + bit += Dedicated_MIMO_UL_Control_IE(tree, bit, length, tvb); + } + } else { + XBIT_HF(1, hf_ulmap_mimo_ul_chase_harq_matrix); + } + XBIT_HF(10, hf_ulmap_mimo_ul_chase_harq_duration); + for (i = 0; i < N_layer; i++) { + if (muin == 1) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + XBIT_HF(4, hf_ulmap_mimo_ul_chase_harq_uiuc); + XBIT_HF(2, hf_ulmap_mimo_ul_chase_harq_repetition_coding_indication); + if (ackd == 0) { + XBIT_HF(4, hf_ulmap_mimo_ul_chase_harq_acid); + XBIT_HF(1, hf_ulmap_mimo_ul_chase_harq_ai_sn); + } + } + +#if 0 + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16((guint8 *)tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BITHI(bit,16), hf_ulmap_crc16, hf_ulmap_crc16_status, &ei_ulmap_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + + bit += 16; + } +#endif + + return (bit - offset); /* length in bits */ +} + +static gint MIMO_UL_IR_HARQ__Sub_Burst_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24 MIMO_UL_IR_HARQ__Sub_Burst_IE -- table 302o */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + /*proto_item *generic_item = NULL;*/ + gint muin,dmci,ackd,i; + /*guint16 calculated_crc;*/ + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302o, NULL, "MIMO_UL_IR_HARQ__Sub_Burst_IE"); + + XBIT_HF_VALUE(muin, 1, hf_ulmap_mimo_ul_ir_harq_mu_indicator); + XBIT_HF_VALUE(dmci, 1, hf_ulmap_mimo_ul_ir_harq_dedicated_mimo_ul_control_indicator); + XBIT_HF_VALUE(ackd, 1, hf_ulmap_mimo_ul_ir_harq_ack_disable); + if (muin == 0) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + if (dmci) { + bit += Dedicated_MIMO_UL_Control_IE(tree, bit, length, tvb); + } + } else { + XBIT_HF(1, hf_ulmap_mimo_ul_ir_harq_matrix); + } + XBIT_HF(4, hf_ulmap_mimo_ul_ir_harq_nsch); + for (i = 0; i < N_layer; i++) { + if (muin == 1) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + XBIT_HF(4, hf_ulmap_mimo_ul_ir_harq_nep); + if (ackd == 0) { + XBIT_HF(2, hf_ulmap_mimo_ul_ir_harq_spid); + XBIT_HF(4, hf_ulmap_mimo_ul_ir_harq_acid); + XBIT_HF(1, hf_ulmap_mimo_ul_ir_harq_ai_sn); + } + } + +#if 0 + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16((guint8 *)tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BITHI(bit,16), hf_ulmap_crc16, hf_ulmap_crc16_status, &ei_ulmap_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + + bit += 16; + } +#endif + + return (bit - offset); /* length in bits */ +} + +static gint MIMO_UL_IR_HARQ_for_CC_Sub_Burst_UIE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24 MIMO_UL_IR_HARQ_for_CC_Sub_Burst_UIE -- table 302p */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + /*proto_item *generic_item = NULL;*/ + gint muin,dmci,ackd,i; + /*guint16 calculated_crc;*/ + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302p, NULL, "MIMO_UL_IR_HARQ_for_CC_Sub_Burst_UIE"); + + XBIT_HF_VALUE(muin, 1, hf_ulmap_mimo_ul_ir_harq_cc_mu_indicator); + XBIT_HF_VALUE(dmci, 1, hf_ulmap_mimo_ul_ir_harq_cc_dedicated_mimo_ul_control_indicator); + XBIT_HF_VALUE(ackd, 1, hf_ulmap_mimo_ul_ir_harq_cc_ack_disable); + if (muin == 0) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + if (dmci) { + bit += Dedicated_MIMO_UL_Control_IE(tree, bit, length, tvb); + } + } else { + XBIT_HF(1, hf_ulmap_mimo_ul_ir_harq_cc_matrix); + } + XBIT_HF(10, hf_ulmap_mimo_ul_ir_harq_cc_duration); + for (i = 0; i < N_layer; i++) { + if (muin == 1) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + } + XBIT_HF(4, hf_ulmap_mimo_ul_ir_harq_cc_uiuc); + XBIT_HF(2, hf_ulmap_mimo_ul_ir_harq_cc_repetition_coding_indication); + if (ackd == 0) { + XBIT_HF(4, hf_ulmap_mimo_ul_ir_harq_cc_acid); + XBIT_HF(1, hf_ulmap_mimo_ul_ir_harq_cc_ai_sn); + XBIT_HF(2, hf_ulmap_mimo_ul_ir_harq_cc_spid); + } + } + +#if 0 + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16((guint8 *)tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BITHI(bit,16), hf_ulmap_crc16, hf_ulmap_crc16_status, &ei_ulmap_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + + bit += 16; + } +#endif + + return (bit - offset); /* length in bits */ +} + +static gint MIMO_UL_STC_HARQ_Sub_Burst_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.4.24 MIMO_UL_STC_HARQ_Sub_Burst_IE -- table 302q */ + /* UL-MAP HARQ Sub-Burst IE * offset/length are in bits */ + gint bit; + proto_item *tree; + /*proto_item *generic_item = NULL;*/ + gint ackd,txct,sboi; + /*guint16 calculated_crc;*/ + + bit = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302q, NULL, "MIMO_UL_STC_HARQ_Sub_Burst_IE"); + + XBIT_HF_VALUE(txct, 2, hf_ulmap_mimo_ul_stc_harq_tx_count); + XBIT_HF(10, hf_ulmap_mimo_ul_stc_harq_duration); + XBIT_HF_VALUE(sboi, 1, hf_ulmap_mimo_ul_stc_harq_sub_burst_offset_indication); + /*XBIT_HF_VALUE(muin, 1, hf_ulmap_reserved_uint);*/ + if (sboi == 1) { + XBIT_HF(8, hf_ulmap_mimo_ul_stc_harq_sub_burst_offset); + } + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + XBIT_HF_VALUE(ackd, 1, hf_ulmap_mimo_ul_stc_harq_ack_disable); + if (txct == 0) { + XBIT_HF(4, hf_ulmap_mimo_ul_stc_harq_uiuc); + XBIT_HF(2, hf_ulmap_mimo_ul_stc_harq_repetition_coding_indication); + } + if (ackd == 0) { + XBIT_HF(4, hf_ulmap_mimo_ul_stc_harq_acid); + } + +#if 0 + if (include_cor2_changes) + { + /* CRC-16 is always appended */ + calculated_crc = wimax_mac_calc_crc16((guint8 *)tvb_get_ptr(tvb, 0, BIT_TO_BYTE(bit)), BIT_TO_BYTE(bit)); + proto_tree_add_checksum(tree, tvb, BITHI(bit,16), hf_ulmap_crc16, hf_ulmap_crc16_status, &ei_ulmap_crc16, pinfo, calculated_crc, + ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + + bit += 16; + } +#endif + + return (bit - offset); /* length in bits */ +} + +/******************************************************************** + * UL-MAP Extended IEs + * table 290a + *******************************************************************/ + +static gint Power_Control_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 0 */ + /* 8.4.5.4.5 Power_Control_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_item *tree; + + nib = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_292, NULL, "Power_Control_IE"); + + VNIB(data, 1, hf_ulmap_ie_diuc_ext); + VNIB(data, 1, hf_ulmap_ie_length); + + VNIB(data, 2, hf_ulmap_power_control); + VNIB(data, 2, hf_ulmap_power_measurement_frame); + return nib; +} + +static gint Mini_Subchannel_allocation_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 1 */ + /* 8.4.5.4.8 [2] Mini-Subchannel_allocation_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + guint idx; + proto_item *tree; + gint j, M; + const gint m_table[4] = { 2, 2, 3, 6 }; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_295, NULL, "Mini_subchannel_allocation_IE"); + + XBIT_HF(4, hf_ulmap_mini_subcha_alloc_extended_2_uiuc); + XBIT_HF(8, hf_ulmap_mini_subcha_alloc_length); + + XBIT_HF_VALUE(idx, 2, hf_ulmap_mini_subcha_alloc_ctype); + M = m_table[idx]; + XBIT_HF(6, hf_ulmap_mini_subcha_alloc_duration); + + for (j = 0; j < M; j++) { + data = TVB_BIT_BITS(bit, tvb, 16); + proto_tree_add_uint_format(tree, hf_ulmap_mini_subcha_alloc_cid, tvb, BITHI(bit, 16), data, "CID(%d): %d", j, data); + bit += 16; + data = TVB_BIT_BITS(bit, tvb, 4); + proto_tree_add_uint_format(tree, hf_ulmap_mini_subcha_alloc_uiuc, tvb, BITHI(bit, 4), data, "UIUC(%d): %d", j, data); + bit += 4; + data = TVB_BIT_BITS(bit, tvb, 2); + proto_tree_add_uint_format(tree, hf_ulmap_mini_subcha_alloc_repetition, tvb, BITHI(bit, 2), data, "Repetition(%d): %d", j, data); + bit += 2; + } + if (M == 3) { + XBIT_HF(4, hf_ulmap_mini_subcha_alloc_padding); + } + return BIT_TO_NIB(bit); +} + +static gint AAS_UL_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 2 */ + /* 8.4.5.4.6 [2] AAS_UL_IE*/ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_293, NULL, "AAS_UL_IE"); + + XBIT_HF(4, hf_ulmap_aas_ul_extended_uiuc); + XBIT_HF(4, hf_ulmap_aas_ul_length); + + XBIT_HF(2, hf_ulmap_aas_ul_permutation); + XBIT_HF(7, hf_ulmap_aas_ul_ul_permbase); + XBIT_HF(8, hf_ulmap_aas_ul_ofdma_symbol_offset); + XBIT_HF(8, hf_ulmap_aas_ul_aas_zone_length); + XBIT_HF(2, hf_ulmap_aas_ul_uplink_preamble_config); + XBIT_HF(1, hf_ulmap_aas_ul_preamble_type); + XBIT_HF(4, hf_ulmap_reserved_uint); + return BIT_TO_NIB(bit); +} + +static gint CQICH_Alloc_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 3 */ + /* 8.4.5.4.12 [2] CQICH_Alloc_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + gint target; + proto_item *tree; + gint rci, rtype, ftype, zperm, mgi, api, pad; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_300, NULL, "CQICH_Alloc_IE"); + + XBIT_HF(4, hf_ulmap_cqich_alloc_extended_uiuc); + XBIT_HF_VALUE(data, 4, hf_ulmap_cqich_alloc_length); + target = bit + BYTE_TO_BIT(data); + + if (cqich_id_size == 0) { + proto_tree_add_uint_format_value(tree, hf_ulmap_cqich_alloc_cqich_id, tvb, BITHI(bit, 1), cqich_id_size, "n/a (size == 0 bits)"); + } else { + /* variable from 0-9 bits */ + data = TVB_BIT_BITS16(bit, tvb, cqich_id_size); + proto_tree_add_uint_format_value(tree, hf_ulmap_cqich_alloc_cqich_id, tvb, BITHI(bit, cqich_id_size), data, "%d (%d bits)", data, cqich_id_size); + bit += cqich_id_size; + } + + XBIT_HF(6, hf_ulmap_cqich_alloc_allocation_offset); + XBIT_HF(2, hf_ulmap_cqich_alloc_period); + XBIT_HF(3, hf_ulmap_cqich_alloc_frame_offset); + XBIT_HF(3, hf_ulmap_cqich_alloc_duration); + XBIT_HF_VALUE(rci, 1, hf_ulmap_cqich_alloc_report_configuration_included); + if (rci) + { + XBIT_HF_VALUE(ftype, 2, hf_ulmap_cqich_alloc_feedback_type); + XBIT_HF_VALUE(rtype, 1, hf_ulmap_cqich_alloc_report_type); + if (rtype == 0) { + XBIT_HF(1, hf_ulmap_cqich_alloc_cinr_preamble_report_type); + } + else { + XBIT_HF_VALUE(zperm, 3, hf_ulmap_cqich_alloc_zone_permutation); + XBIT_HF(2, hf_ulmap_cqich_alloc_zone_type); + XBIT_HF(2, hf_ulmap_cqich_alloc_zone_prbs_id); + if (zperm == 0 || zperm == 1) { + XBIT_HF_VALUE(mgi, 1, hf_ulmap_cqich_alloc_major_group_indication); + if (mgi == 1) { + /* PUSC major group bitmap*/ + XBIT_HF(6, hf_ulmap_cqich_alloc_pusc_major_group_bitmap); + } + } + XBIT_HF(1, hf_ulmap_cqich_alloc_cinr_zone_measurement_type); + } + if (ftype == 0) { + XBIT_HF_VALUE(api, 1, hf_ulmap_cqich_alloc_averaging_parameter_included); + if (api == 1) { + XBIT_HF(4, hf_ulmap_cqich_alloc_averaging_parameter); + } + } + } + XBIT_HF(2, hf_ulmap_cqich_alloc_mimo_permutation_feedback_cycle); + + pad = target - bit; + if (pad) { + proto_tree_add_bytes_format_value(tree, hf_ulmap_padding, tvb, BITHI(bit, pad), NULL, "%d bits", pad); + bit += pad; + } + return BIT_TO_NIB(bit); /* Return position in nibbles. */ +} + +static gint UL_Zone_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 4 */ + /* 8.4.5.4.7 [2] UL_Zone_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_294, NULL, "UL_Zone_IE"); + + XBIT_HF(4, hf_ulmap_zone_extended_uiuc); + XBIT_HF(4, hf_ulmap_zone_length); + + XBIT_HF(7, hf_ulmap_zone_ofdma_symbol_offset); + XBIT_HF(2, hf_ulmap_zone_permutation); + XBIT_HF(7, hf_ulmap_zone_ul_permbase); + XBIT_HF(2, hf_ulmap_zone_amc_type); + XBIT_HF(1, hf_ulmap_zone_use_all_sc_indicator); + XBIT_HF(1, hf_ulmap_zone_disable_subchannel_rotation); + XBIT_HF(4, hf_ulmap_reserved_uint); + return BIT_TO_NIB(bit); +} + +static gint PHYMOD_UL_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 5 */ + /* 8.4.5.4.14 [2] PHYMOD_UL_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + gint pmt; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302, NULL, "PHYMOD_UL_IE"); + + XBIT_HF(4, hf_ulmap_phymod_ul_extended_uiuc); + XBIT_HF(4, hf_ulmap_phymod_ul_length); + + XBIT_HF_VALUE(pmt, 1, hf_ulmap_phymod_ul_preamble_modifier_type); + if (pmt == 0) { + XBIT_HF(4, hf_ulmap_phymod_ul_preamble_frequency_shift_index); + } else { + XBIT_HF(4, hf_ulmap_phymod_ul_preamble_time_shift_index); + } + XBIT_HF(1, hf_ulmap_phymod_ul_pilot_pattern_modifier); + XBIT_HF(2, hf_ulmap_phymod_ul_pilot_pattern_index); + return BIT_TO_NIB(bit); +} + +static gint MIMO_UL_IE(proto_tree *uiuc_tree, packet_info* pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 6 */ + /* 8.4.5.4.11 MIMO_UL_Basic_IE (not implemented) */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_item *tree; + + nib = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_299, NULL, "MIMO_UL_Basic_IE"); + + VNIB(data, 1, hf_ulmap_ie_diuc_ext); + VNIB(data, 1, hf_ulmap_ie_length); + proto_tree_add_expert(tree, pinfo, &ei_ulmap_not_implemented, tvb, NIBHI(nib,length-2)); + return nib; +} + +static gint ULMAP_Fast_Tracking_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 7 */ + /* 8.4.5.4.22 [2] ULMAP_Fast_Tracking_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302h, NULL, "Fast_Tracking_IE"); + + length = NIB_TO_BIT(length); + + XBIT_HF(4, hf_ulmap_fast_tracking_extended_uiuc); + XBIT_HF(4, hf_ulmap_fast_tracking_length); + + XBIT_HF(2, hf_ulmap_fast_tracking_map_index); + XBIT_HF(6, hf_ulmap_reserved_uint); + while (bit < (length-7)) { + XBIT_HF(3, hf_ulmap_fast_tracking_power_correction); + XBIT_HF(3, hf_ulmap_fast_tracking_frequency_correction); + XBIT_HF(2, hf_ulmap_fast_tracking_time_correction); + } + return BIT_TO_NIB(bit); +} + +static gint UL_PUSC_Burst_Allocation_in_other_segment_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 8 */ + /* 8.4.5.4.17 [2] UL_PUSC_Burst_Allocation_in_other_segment_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302c, NULL, "UL_PUSC_Burst_Allocation_in_Other_Segment_IE"); + + XBIT_HF(4, hf_ulmap_pusc_burst_allocation_extended_uiuc); + XBIT_HF(4, hf_ulmap_pusc_burst_allocation_length); + + XBIT_HF(4, hf_ulmap_pusc_burst_allocation_uiuc); + XBIT_HF(2, hf_ulmap_pusc_burst_allocation_segment); + XBIT_HF(7, hf_ulmap_pusc_burst_allocation_ul_permbase); + XBIT_HF(8, hf_ulmap_pusc_burst_allocation_ofdma_symbol_offset); + XBIT_HF(6, hf_ulmap_pusc_burst_allocation_subchannel_offset); + XBIT_HF(10, hf_ulmap_pusc_burst_allocation_duration); + XBIT_HF(2, hf_ulmap_pusc_burst_allocation_repetition_coding_indication); + XBIT_HF(1, hf_ulmap_reserved_uint); + return BIT_TO_NIB(bit); +} + +static gint Fast_Ranging_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 9 */ + /* 8.4.5.4.21 [2] Fast_Ranging_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + gint hidi; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302g, NULL, "Fast_Ranging_IE"); + + XBIT_HF(4, hf_ulmap_fast_ranging_extended_uiuc); + XBIT_HF(4, hf_ulmap_fast_ranging_length); + + XBIT_HF_VALUE(hidi, 1, hf_ulmap_fast_ranging_ho_id_indicator); + XBIT_HF(7, hf_ulmap_reserved_uint); + if (hidi == 1) { + XBIT_HF(8, hf_ulmap_fast_ranging_ho_id); + /* XBIT_HF(40, hf_ulmap_reserved_uint); TODO */ + } else { + proto_tree_add_item(tree, hf_ulmap_fast_ranging_mac_address, tvb, BITHI(bit, 48), ENC_NA); + bit += 48; + } + XBIT_HF(4, hf_ulmap_fast_ranging_uiuc); + XBIT_HF(10, hf_ulmap_fast_ranging_duration); + XBIT_HF(2, hf_ulmap_fast_ranging_repetition_coding_indication); + return BIT_TO_NIB(bit); +} + +static gint UL_Allocation_Start_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended IE = 0xA */ + /* 8.4.5.4.15 [2] UL_Allocation_Start_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302a, NULL, "UL_Allocation_start_IE"); + + XBIT_HF(4, hf_ulmap_allocation_start_extended_uiuc); + XBIT_HF(4, hf_ulmap_allocation_start_length); + + XBIT_HF(8, hf_ulmap_allocation_start_ofdma_symbol_offset); + XBIT_HF(7, hf_ulmap_allocation_start_subchannel_offset); + XBIT_HF(1, hf_ulmap_reserved_uint); + return BIT_TO_NIB(bit); +} + + +/******************************************************************** + * UL-MAP Extended-2 IEs + * table 290c + *******************************************************************/ + +static gint CQICH_Enhanced_Allocation_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 0 */ + /* 8.4.5.4.16 [2] CQICH_Enhanced_Allocation_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_item *tree; + gint i, cnum, bapm; + guint pad; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302b, NULL, "CQICH_Enhanced_Alloc_IE"); + + XBIT_HF(4, hf_ulmap_cqich_enhanced_alloc_extended_2_uiuc); + XBIT_HF(8, hf_ulmap_cqich_enhanced_alloc_length); + + if (cqich_id_size == 0) { + proto_tree_add_uint_format_value(tree, hf_ulmap_cqich_enhanced_alloc_cqich_id, tvb, BITHI(bit, 1), cqich_id_size, "n/a (size == 0 bits)"); + } else { + /* variable from 0-9 bits */ + data = TVB_BIT_BITS16(bit, tvb, cqich_id_size); + proto_tree_add_uint_format_value(tree, hf_ulmap_cqich_enhanced_alloc_cqich_id, tvb, BITHI(bit, cqich_id_size), data, "%d (%d bits)", data, cqich_id_size); + bit += cqich_id_size; + } + + XBIT_HF(3, hf_ulmap_cqich_enhanced_alloc_period); + XBIT_HF(3, hf_ulmap_cqich_enhanced_alloc_frame_offset); + XBIT_HF(3, hf_ulmap_cqich_enhanced_alloc_duration); + XBIT_HF_VALUE(cnum, 4, hf_ulmap_cqich_enhanced_alloc_cqich_num); + cnum += 1; + for (i = 0; i < cnum; i++) { + XBIT_HF(3, hf_ulmap_cqich_enhanced_alloc_feedback_type); + XBIT_HF(6, hf_ulmap_cqich_enhanced_alloc_allocation_index); + XBIT_HF(3, hf_ulmap_cqich_enhanced_alloc_cqich_type); + XBIT_HF(1, hf_ulmap_cqich_enhanced_alloc_sttd_indication); + } + XBIT_HF_VALUE(bapm, 1, hf_ulmap_cqich_enhanced_alloc_band_amc_precoding_mode); + if (bapm == 1) { + XBIT_HF(3, hf_ulmap_cqich_enhanced_alloc_nr_precoders_feedback); + } + + pad = BIT_PADDING(bit,8); + if (pad) { + proto_tree_add_bytes_format_value(tree, hf_ulmap_padding, tvb, BITHI(bit, pad), NULL, "%d bits", pad); + bit += pad; + } + return BIT_TO_NIB(bit); +} + +static gint HO_Anchor_Active_UL_MAP_IE(proto_tree *uiuc_tree, packet_info* pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 1 */ + /* 8.4.5.4.18 [2] HO_Anchor_Active_UL_MAP_IE (not implemented) */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_item *tree; + + nib = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302d, NULL, "HO_Anchor_Active_UL_MAP_IE"); + + VNIB(data, 1, hf_ulmap_ie_diuc_ext2); + VNIB(data, 2, hf_ulmap_ie_length); + proto_tree_add_expert(tree, pinfo, &ei_ulmap_not_implemented, tvb, NIBHI(nib,length-3)); + return nib; +} + +static gint HO_Active_Anchor_UL_MAP_IE(proto_tree *uiuc_tree, packet_info* pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 2 */ + /* 8.4.5.4.19 [2] HO_Active_Anchor_UL_MAP_IE (not implemented) */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_item *tree; + + nib = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302e, NULL, "HO_Active_Anchor_UL_MAP_IE"); + + VNIB(data, 1, hf_ulmap_ie_diuc_ext2); + VNIB(data, 2, hf_ulmap_ie_length); + proto_tree_add_expert(tree, pinfo, &ei_ulmap_not_implemented, tvb, NIBHI(nib,length-3)); + return nib; +} + +static gint Anchor_BS_switch_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 3 */ + /* 8.4.5.4.23 [2] Anchor_BS_switch_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + gint data; + proto_item *tree; + gint nbss, acod, cqai, pad; + gint i; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302i, NULL, "Anchor_BS_switch_IE"); + + XBIT_HF(4, hf_ulmap_anchor_bs_switch_extended_2_uiuc); + XBIT_HF(8, hf_ulmap_anchor_bs_switch_length); + + XBIT_HF_VALUE(nbss, 4, hf_ulmap_anchor_bs_switch_n_anchor_bs_switch); + for (i = 0; i < nbss; i++) { + XBIT_HF(12, hf_ulmap_anchor_bs_switch_reduced_cid); + XBIT_HF_VALUE(acod, 2, hf_ulmap_anchor_bs_switch_action_code); + if (acod == 1) { + XBIT_HF(3, hf_ulmap_anchor_bs_switch_action_time); + XBIT_HF(3, hf_ulmap_anchor_bs_switch_temp_bs_id); + XBIT_HF(2, hf_ulmap_reserved_uint); + } + if (acod == 0 || acod == 1) { + XBIT_HF(1, hf_ulmap_anchor_bs_switch_ak_change_indicator); + XBIT_HF_VALUE(cqai, 1, hf_ulmap_anchor_bs_switch_cqich_allocation_indicator); + if (cqai == 1) { + /* variable bits from 0-9 */ + if (cqich_id_size == 0) { + proto_tree_add_uint_format_value(tree, hf_ulmap_anchor_bs_switch_cqich_id, tvb, BITHI(bit, 1), cqich_id_size, "n/a (size == 0 bits)"); + } else { + data = TVB_BIT_BITS16(bit, tvb, cqich_id_size); + proto_tree_add_uint_format_value(tree, hf_ulmap_anchor_bs_switch_cqich_id, tvb, BITHI(bit, cqich_id_size), + data, "%d (%d bits)", data, cqich_id_size); + bit += cqich_id_size; + } + XBIT_HF(6, hf_ulmap_anchor_bs_switch_feedback_channel_offset); + XBIT_HF(2, hf_ulmap_anchor_bs_switch_period); + XBIT_HF(3, hf_ulmap_anchor_bs_switch_frame_offset); + XBIT_HF(3, hf_ulmap_anchor_bs_switch_duration); + XBIT_HF(2, hf_ulmap_anchor_bs_switch_mimo_permutation_feedback_code); + pad = BIT_PADDING(bit,8); + if (pad) { + proto_tree_add_uint_format_value(tree, hf_ulmap_reserved, tvb, BITHI(bit,pad), 0, "%d bits", pad); + } + } + } else { + XBIT_HF(2, hf_ulmap_reserved_uint); + } + } + XBIT_HF(4, hf_ulmap_reserved_uint); + return BIT_TO_NIB(bit); +} + +static gint UL_sounding_command_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 4 */ + /* 8.4.5.4.26 [2] UL_sounding_command_IE */ + /* see 8.4.6.2.7.1 */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + gint stype, srlf, iafb, pad, sept, nssym, ncid, amod; + gint i, j; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_315d, NULL, "UL_Sounding_Command_IE"); + + XBIT_HF(4, hf_ulmap_sounding_command_extended_2_uiuc); + XBIT_HF(8, hf_ulmap_sounding_command_length); + + XBIT_HF_VALUE(stype, 1, hf_ulmap_sounding_command_type); + XBIT_HF(1, hf_ulmap_sounding_command_send_sounding_report_flag); + XBIT_HF_VALUE(srlf, 1, hf_ulmap_sounding_command_relevance_flag); + if (srlf == 0) { + XBIT_HF(1, hf_ulmap_sounding_command_relevance); + XBIT_HF(2, hf_ulmap_reserved_uint); + } else { + XBIT_HF(3, hf_ulmap_reserved_uint); + } + XBIT_HF_VALUE(iafb, 2, hf_ulmap_sounding_command_include_additional_feedback); + if (stype == 0) { + XBIT_HF_VALUE(nssym, 3, hf_ulmap_sounding_command_num_sounding_symbols); + XBIT_HF(1, hf_ulmap_reserved_uint); + for (i = 0; i < nssym; i++) { + XBIT_HF_VALUE(sept, 1, hf_ulmap_sounding_command_separability_type); + if (sept == 0) { + XBIT_HF(3, hf_ulmap_sounding_command_max_cyclic_shift_index_p); + XBIT_HF(1, hf_ulmap_reserved_uint); + } else { + XBIT_HF(3, hf_ulmap_sounding_command_decimation_value); + XBIT_HF(1, hf_ulmap_sounding_command_decimation_offset_randomization); + } + XBIT_HF(3, hf_ulmap_sounding_command_symbol_index); + XBIT_HF_VALUE(ncid, 7, hf_ulmap_sounding_command_number_of_cids); + XBIT_HF(1, hf_ulmap_reserved_uint); + for (j = 0; j < ncid; j++) { + XBIT_HF(12, hf_ulmap_sounding_command_shorted_basic_cid); + XBIT_HF(2, hf_ulmap_sounding_command_power_assignment_method); + XBIT_HF(1, hf_ulmap_sounding_command_power_boost); + XBIT_HF(1, hf_ulmap_sounding_command_multi_antenna_flag); + XBIT_HF_VALUE(amod, 1, hf_ulmap_sounding_command_allocation_mode); + if (amod == 1) { + XBIT_HF(12, hf_ulmap_sounding_command_band_bit_map); + XBIT_HF(2, hf_ulmap_reserved_uint); + } else { + XBIT_HF(7, hf_ulmap_sounding_command_starting_frequency_band); + XBIT_HF(7, hf_ulmap_sounding_command_number_of_frequency_bands); + } + if (srlf == 1) { + XBIT_HF(1, hf_ulmap_sounding_command_relevance); + } else { + XBIT_HF(1, hf_ulmap_reserved_uint); + } + if (sept == 0) { + XBIT_HF(5, hf_ulmap_sounding_command_cyclic_time_shift_index); + } else { + XBIT_HF(6, hf_ulmap_sounding_command_decimation_offset); + if (iafb == 1) { + XBIT_HF(1, hf_ulmap_sounding_command_use_same_symbol_for_additional_feedback); + XBIT_HF(2, hf_ulmap_reserved_uint); + } else { + XBIT_HF(3, hf_ulmap_reserved_uint); + } + } + XBIT_HF(3, hf_ulmap_sounding_command_periodicity); + } + } + } else { + XBIT_HF(3, hf_ulmap_sounding_command_permutation); + XBIT_HF(6, hf_ulmap_sounding_command_dl_permbase); + XBIT_HF_VALUE(nssym, 3, hf_ulmap_sounding_command_num_sounding_symbols); + for (i = 0; i < nssym; i++) { + XBIT_HF_VALUE(ncid, 7, hf_ulmap_sounding_command_number_of_cids); + XBIT_HF(1, hf_ulmap_reserved_uint); + for (j = 0; j < ncid; j++) { + XBIT_HF(12, hf_ulmap_sounding_command_shortened_basic_cid); + if (srlf) { + XBIT_HF(1, hf_ulmap_sounding_command_relevance); + XBIT_HF(3, hf_ulmap_reserved_uint); + } + XBIT_HF(7, hf_ulmap_sounding_command_subchannel_offset); + XBIT_HF(1, hf_ulmap_sounding_command_power_boost); + XBIT_HF(3, hf_ulmap_sounding_command_number_of_subchannels); + XBIT_HF(3, hf_ulmap_sounding_command_periodicity); + XBIT_HF(2, hf_ulmap_sounding_command_power_assignment_method); + } + } + } + pad = BIT_PADDING(bit,8); + if (pad) { + proto_tree_add_bytes_format_value(tree, hf_ulmap_padding, tvb, BITHI(bit, pad), NULL, "%d bits", pad); + bit += pad; + } + return BIT_TO_NIB(bit); +} + +static gint MIMO_UL_Enhanced_IE(proto_tree *uiuc_tree, packet_info* pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 6 */ + /* 8.4.5.4.20 [2] MIMO_UL_Enhanced_IE (not implemented) */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint nib; + gint data; + proto_item *tree; + + nib = offset; + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302f, NULL, "MIMO_UL_Enhanced_IE"); + + VNIB(data, 1, hf_ulmap_ie_diuc_ext2); + VNIB(data, 2, hf_ulmap_ie_length); + proto_tree_add_expert(tree, pinfo, &ei_ulmap_not_implemented, tvb, NIBHI(nib,length-3)); + return nib; +} + +static gint HARQ_ULMAP_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 7 */ + /* 8.4.5.4.24 HARQ_ULMAP_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + gint bitlength; + gint lastbit; + gint pad, mode, alsi, nsub; + gint i; + + bit = NIB_TO_BIT(offset); + bitlength = NIB_TO_BIT(length); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302j, NULL, "HARQ_ULMAP_IE"); + + XBIT_HF(4, hf_ulmap_harq_ulmap_extended_2_uiuc); + XBIT_HF(8, hf_ulmap_harq_ulmap_length); + + XBIT_HF_VALUE(RCID_Type, 2, hf_ulmap_harq_ulmap_rcid_type); + XBIT_HF(2, hf_ulmap_reserved_uint); + lastbit = bit + bitlength -16 - 4; + while (bit < lastbit) { + XBIT_HF_VALUE(mode, 3, hf_ulmap_harq_ulmap_mode); + XBIT_HF_VALUE(alsi, 1, hf_ulmap_harq_ulmap_allocation_start_indication); + if (alsi == 1) { + XBIT_HF(8, hf_ulmap_harq_ulmap_ofdma_symbol_offset); + XBIT_HF(7, hf_ulmap_harq_ulmap_subchannel_offset); + XBIT_HF(1, hf_ulmap_reserved_uint); + } + XBIT_HF_VALUE(nsub, 4, hf_ulmap_harq_ulmap_n_sub_burst); + nsub++; + for (i = 0; i < nsub; i++) { + if (mode == 0) { + bit += UL_HARQ_Chase_Sub_Burst_IE(tree, bit, bitlength, tvb); + } else if (mode == 1) { + bit += UL_HARQ_IR_CTC_Sub_Burst_IE(tree, bit, bitlength, tvb); + } else if (mode == 2) { + bit += UL_HARQ_IR_CC_Sub_Burst_IE(tree, bit, bitlength, tvb); + } else if (mode == 3) { + bit += MIMO_UL_Chase_HARQ_Sub_Burst_IE(tree, bit, bitlength, tvb); + } else if (mode == 4) { + bit += MIMO_UL_IR_HARQ__Sub_Burst_IE(tree, bit, bitlength, tvb); + } else if (mode == 5) { + bit += MIMO_UL_IR_HARQ_for_CC_Sub_Burst_UIE(tree, bit, bitlength, tvb); + } else if (mode == 6) { + bit += MIMO_UL_STC_HARQ_Sub_Burst_IE(tree, bit, bitlength, tvb); + } + } + } + + pad = NIB_TO_BIT(offset) + bitlength - bit; + if (pad) { + proto_tree_add_bytes_format_value(tree, hf_ulmap_padding, tvb, BITHI(bit, pad), NULL, "%d bits", pad); + bit += pad; + } + return BIT_TO_NIB(bit); +} + +static gint HARQ_ACKCH_Region_Allocation_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 8 */ + /* 8.4.5.4.25 [2] HARQ_ACKCH_Region_Allocation_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302t, NULL, "HARQ_ACKCH_Region_IE"); + + XBIT_HF(4, hf_ulmap_harq_ackch_region_alloc_extended_2_uiuc); + XBIT_HF(8, hf_ulmap_harq_ackch_region_alloc_length); + + XBIT_HF(8, hf_ulmap_harq_ackch_region_alloc_ofdma_symbol_offset); + XBIT_HF(7, hf_ulmap_harq_ackch_region_alloc_subchannel_offset); + XBIT_HF(5, hf_ulmap_harq_ackch_region_alloc_num_ofdma_symbols); + XBIT_HF(4, hf_ulmap_harq_ackch_region_alloc_num_subchannels); + return BIT_TO_NIB(bit); +} + +static gint AAS_SDMA_UL_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 0xE */ + /* 8.4.5.4.27 [2] AAS_SDMA_UL_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + gint nreg, pad, user, encm, ppmd, padj; + gint aasp = 0; /* TODO AAS UL preamble used */ + gint ii, jj; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302u, NULL, "AAS_SDMA_UL_IE"); + + XBIT_HF(4, hf_ulmap_aas_sdma_extended_2_uiuc); + XBIT_HF(8, hf_ulmap_aas_sdma_length); + + XBIT_HF_VALUE(RCID_Type, 2, hf_ulmap_aas_sdma_rcid_type); + XBIT_HF_VALUE(nreg, 4, hf_ulmap_aas_sdma_num_burst_region); + XBIT_HF(2, hf_ulmap_reserved_uint); + for (ii = 0; ii < nreg; ii++) { + XBIT_HF(12, hf_ulmap_aas_sdma_slot_offset); + XBIT_HF(10, hf_ulmap_aas_sdma_slot_duration); + XBIT_HF_VALUE(user, 3, hf_ulmap_aas_sdma_number_of_users); + XBIT_HF(3, hf_ulmap_reserved_uint); + for (jj = 0; jj < user; jj++) { + bit += RCID_IE(tree, bit, length, tvb, RCID_Type); + XBIT_HF_VALUE(encm, 2, hf_ulmap_aas_sdma_encoding_mode); + XBIT_HF_VALUE(padj, 1, hf_ulmap_aas_sdma_power_adjust); + XBIT_HF_VALUE(ppmd, 1, hf_ulmap_aas_sdma_pilot_pattern_modifier); + if (aasp) { + XBIT_HF(4, hf_ulmap_aas_sdma_preamble_modifier_index); + } + if (ppmd) { + XBIT_HF(2, hf_ulmap_aas_sdma_pilot_pattern); + XBIT_HF(2, hf_ulmap_reserved_uint); + } + if (encm == 0) { + XBIT_HF(4, hf_ulmap_aas_sdma_diuc); + XBIT_HF(2, hf_ulmap_aas_sdma_repetition_coding_indication); + XBIT_HF(2, hf_ulmap_reserved_uint); + } + if (encm == 1) { + XBIT_HF(4, hf_ulmap_aas_sdma_diuc); + XBIT_HF(2, hf_ulmap_aas_sdma_repetition_coding_indication); + XBIT_HF(4, hf_ulmap_aas_sdma_acid); + XBIT_HF(1, hf_ulmap_aas_sdma_ai_sn); + XBIT_HF(1, hf_ulmap_reserved_uint); + } + if (encm == 2) { + XBIT_HF(4, hf_ulmap_aas_sdma_nep); + XBIT_HF(4, hf_ulmap_aas_sdma_nsch); + XBIT_HF(2, hf_ulmap_aas_sdma_spid); + XBIT_HF(4, hf_ulmap_aas_sdma_acid); + XBIT_HF(1, hf_ulmap_aas_sdma_ai_sn); + XBIT_HF(1, hf_ulmap_reserved_uint); + } + if (encm == 3) { + XBIT_HF(4, hf_ulmap_aas_sdma_diuc); + XBIT_HF(2, hf_ulmap_aas_sdma_repetition_coding_indication); + XBIT_HF(2, hf_ulmap_aas_sdma_spid); + XBIT_HF(4, hf_ulmap_aas_sdma_acid); + XBIT_HF(1, hf_ulmap_aas_sdma_ai_sn); + XBIT_HF(3, hf_ulmap_reserved_uint); + } + if (padj) { + XBIT_HF(8, hf_ulmap_aas_sdma_power_adjustment); + + } + } + } + + pad = BIT_PADDING(bit,8); + if (pad) { + proto_tree_add_bytes_format_value(tree, hf_ulmap_padding, tvb, BITHI(bit, pad), NULL, "%d bits", pad); + bit += pad; + } + return BIT_TO_NIB(bit); +} + +static gint Feedback_Polling_IE(proto_tree *uiuc_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* UL-MAP Extended-2 IE = 0xF */ + /* 8.4.5.4.28 [2] Feedback_Polling_IE */ + /* offset of TLV in nibbles, length of TLV in nibbles */ + gint bit; + proto_item *tree; + gint nalloc, dula, pad, adur; + gint i; + + bit = NIB_TO_BIT(offset); + + tree = proto_tree_add_subtree(uiuc_tree, tvb, NIBHI(offset, length), ett_302v, NULL, "Feedback_Polling_IE"); + + XBIT_HF(4, hf_ulmap_feedback_polling_extended_2_uiuc); + XBIT_HF(8, hf_ulmap_feedback_polling_length); + + XBIT_HF_VALUE(nalloc, 4, hf_ulmap_feedback_polling_num_allocation); + XBIT_HF_VALUE(dula, 1, hf_ulmap_feedback_polling_dedicated_ul_allocation_included); + XBIT_HF(3, hf_ulmap_reserved_uint); + for (i = 0; i < nalloc; i++) { + XBIT_HF(16, hf_ulmap_feedback_polling_basic_cid); + XBIT_HF_VALUE(adur, 3, hf_ulmap_feedback_polling_allocation_duration); + if (adur != 0) { + XBIT_HF(4, hf_ulmap_feedback_polling_type); + XBIT_HF(3, hf_ulmap_feedback_polling_frame_offset); + XBIT_HF(2, hf_ulmap_feedback_polling_period); + if (dula == 1) { + XBIT_HF(4, hf_ulmap_feedback_polling_uiuc); + XBIT_HF(8, hf_ulmap_feedback_polling_ofdma_symbol_offset); + XBIT_HF(7, hf_ulmap_feedback_polling_subchannel_offset); + XBIT_HF(3, hf_ulmap_feedback_polling_duration); + XBIT_HF(2, hf_ulmap_feedback_polling_repetition_coding_indication); + } + } + } + pad = BIT_PADDING(bit,8); + if (pad) { + proto_tree_add_bytes_format_value(tree, hf_ulmap_padding, tvb, BITHI(bit, pad), NULL, "%d bits", pad); + bit += pad; + } + return BIT_TO_NIB(bit); +} + + +/******************************************************************** + * UL-MAP Miscellany + *******************************************************************/ + +gint dissect_ulmap_ie( proto_tree *ie_tree, packet_info* pinfo, gint offset, gint length _U_, tvbuff_t *tvb) +{ + /* decode a single UL-MAP IE and return the + * length of the IE in nibbles + * offset = start of IE (nibbles) + * length = total length of tvb (nibbles) */ + proto_item *ti; + proto_tree *tree; + gint nibble; + gint uiuc, ext_uiuc, ext2_uiuc, len, aas_or_amc; + guint cid; + guint data; + guint32 data32; + + nibble = offset; + + /* 8.4.5.4 UL-MAP IE format - table 287 */ + cid = TVB_NIB_WORD(nibble, tvb); + uiuc = TVB_NIB_NIBBLE(nibble + 4, tvb); + + if (uiuc == 0) + { + /* 8.4.5.4.9 FAST-FEEDBACK channel */ + tree = proto_tree_add_subtree(ie_tree, tvb, NIBHI(nibble, 5+8), ett_ulmap_ffb, NULL, "FAST FEEDBACK Allocation IE"); + + proto_tree_add_uint(tree, hf_ulmap_ie_cid, tvb, NIBHI(nibble, 4), cid); + nibble += 4; + proto_tree_add_uint(tree, hf_ulmap_ie_uiuc, tvb, NIBHI(nibble, 1), uiuc); + nibble += 1; + + data = TVB_NIB_LONG(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc0_symofs, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc0_subofs, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc0_numsym, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc0_numsub, tvb, NIBHI(nibble, 8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc0_rsv, tvb, NIBHI(nibble, 8), data); + nibble += 8; + } + else if (uiuc == 11) + { + /* 8.4.5.4.4.2 [2] extended-2 UIUC IE table 290b */ + ext2_uiuc = TVB_NIB_NIBBLE(5+nibble, tvb); + len = TVB_NIB_BYTE(5+nibble+1, tvb); + + tree = proto_tree_add_subtree_format(ie_tree, tvb, NIBHI(nibble, 5+3+len*2), ett_290b, NULL, "UIUC: %d (Extended-2 IE)", uiuc); + + proto_tree_add_uint(tree, hf_ulmap_ie_cid, tvb, NIBHI(nibble, 4), cid); + nibble += 4; + proto_tree_add_uint(tree, hf_ulmap_ie_uiuc, tvb, NIBHI(nibble, 1), uiuc); + nibble += 1; + +#if 0 + proto_tree_add_uint(tree, hf_ulmap_uiuc11_ext, tvb, NIBHI(nibble, 1), ext2_uiuc); + nibble += 1; + proto_tree_add_uint(tree, hf_ulmap_uiuc11_len, tvb, NIBHI(nibble, 2), len); + nibble += 2; +#endif + + len = 3 + BYTE_TO_NIB(len); /* length in nibbles */ + + /* data table 290c 8.4.5.4.4.2 */ + switch (ext2_uiuc) { + case 0x00: + /* 8.4.5.4.16 CQICH_Enhanced_Allocation_IE */ + nibble = CQICH_Enhanced_Allocation_IE(tree, nibble, len, tvb); + break; + case 0x01: + /* 8.4.5.4.18 HO_Anchor_Active_UL_MAP_IE */ + nibble = HO_Anchor_Active_UL_MAP_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x02: + /* 8.4.5.4.19 HO_Active_Anchor_UL_MAP_IE */ + nibble = HO_Active_Anchor_UL_MAP_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x03: + /* 8.4.5.4.23 Anchor_BS_switch_IE */ + nibble = Anchor_BS_switch_IE(tree, nibble, len, tvb); + break; + case 0x04: + /* 8.4.5.4.26 UL_sounding_command_IE */ + nibble = UL_sounding_command_IE(tree, nibble, len, tvb); + break; + case 0x06: + /* 8.4.5.4.20 MIMO_UL_Enhanced_IE */ + nibble = MIMO_UL_Enhanced_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x07: + /* 8.4.5.4.24 HARQ_ULMAP_IE */ + nibble = HARQ_ULMAP_IE(tree, nibble, len, tvb); + break; + case 0x08: + /* 8.4.5.4.25 HARQ_ACKCH_Region_Allocation_IE */ + nibble = HARQ_ACKCH_Region_Allocation_IE(tree, nibble, len, tvb); + break; + case 0x0e: + /* 8.4.5.4.27 AAS_SDMA_UL_IE */ + nibble = AAS_SDMA_UL_IE(tree, nibble, len, tvb); + break; + case 0x0f: + /* 8.4.5.4.28 Feedback_Polling_IE */ + nibble = Feedback_Polling_IE(tree, nibble, len, tvb); + break; + + default: + proto_tree_add_bytes_format(tree, hf_ulmap_ie_reserved_extended2_duic, tvb, NIBHI(nibble, len), NULL, "(reserved Extended-2 UIUC: %d)", ext2_uiuc); + nibble += len; + break; + + } + } + else if (uiuc == 12) + { + /* 8.4.5.4 [2] CDMA bandwidth request, CDMA ranging */ + tree = proto_tree_add_subtree(ie_tree, tvb, NIBHI(nibble, 5+8), ett_287_1, NULL, "CDMA Bandwidth/Ranging Request IE"); + + proto_tree_add_uint(tree, hf_ulmap_ie_cid, tvb, NIBHI(nibble, 4), cid); + nibble += 4; + proto_tree_add_uint(tree, hf_ulmap_ie_uiuc, tvb, NIBHI(nibble, 1), uiuc); + nibble += 1; + + data32 = TVB_NIB_LONG(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc12_symofs, tvb, NIBHI(nibble,8), data32); + proto_tree_add_uint(tree, hf_ulmap_uiuc12_subofs, tvb, NIBHI(nibble,8), data32); + proto_tree_add_uint(tree, hf_ulmap_uiuc12_numsym, tvb, NIBHI(nibble,8), data32); + proto_tree_add_uint(tree, hf_ulmap_uiuc12_numsub, tvb, NIBHI(nibble,8), data32); + proto_tree_add_uint(tree, hf_ulmap_uiuc12_method, tvb, NIBHI(nibble,8), data32); + proto_tree_add_uint(tree, hf_ulmap_uiuc12_dri, tvb, NIBHI(nibble,8), data32); + nibble += 8; + } + else if (uiuc == 13) + { + /* 8.4.5.4.2 [2] PAPR reduction allocation, safety zone - table 289 */ + tree = proto_tree_add_subtree(ie_tree, tvb, NIBHI(nibble,5+8), ett_289, NULL, "PAPR/Safety/Sounding Zone IE"); + + + proto_tree_add_uint(tree, hf_ulmap_ie_cid, tvb, NIBHI(nibble, 4), cid); + nibble += 4; + proto_tree_add_uint(tree, hf_ulmap_ie_uiuc, tvb, NIBHI(nibble, 1), uiuc); + nibble += 1; + + data = TVB_NIB_LONG(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc13_symofs, tvb, NIBHI(nibble,8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc13_subofs, tvb, NIBHI(nibble,8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc13_numsym, tvb, NIBHI(nibble,8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc13_numsub, tvb, NIBHI(nibble,8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc13_papr, tvb, NIBHI(nibble,8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc13_zone, tvb, NIBHI(nibble,8), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc13_rsv, tvb, NIBHI(nibble,8), data); + nibble += 8; + } + else if (uiuc == 14) + { + /* 8.4.5.4.3 [2] CDMA allocation IE */ + tree = proto_tree_add_subtree(ie_tree, tvb, NIBHI(nibble,5+10), ett_290, &ti, "CDMA allocation IE"); + + proto_tree_add_uint(tree, hf_ulmap_ie_cid, tvb, NIBHI(nibble, 4), cid); + nibble += 4; + proto_tree_add_uint(tree, hf_ulmap_ie_uiuc, tvb, NIBHI(nibble, 1), uiuc); + nibble += 1; + + data = TVB_NIB_WORD(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc14_dur, tvb, NIBHI(nibble,2), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc14_uiuc, tvb, NIBHI(nibble+1,2), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc14_rep, tvb, NIBHI(nibble+2,1), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc14_idx, tvb, NIBHI(nibble+3,1), data); + nibble += 4; + + data = TVB_NIB_BYTE(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc14_code, tvb, NIBHI(nibble,2), data); + proto_item_append_text(ti, " (0x%02x)", data); + nibble += 2; + + data = TVB_NIB_BYTE(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc14_sym, tvb, NIBHI(nibble,2), data); + proto_item_append_text(ti, " (0x%02x)", data); + nibble += 2; + + data = TVB_NIB_BYTE(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc14_sub, tvb, NIBHI(nibble,2), data); + proto_item_append_text(ti, " (0x%02x)", data >> 1); + proto_tree_add_uint(tree, hf_ulmap_uiuc14_bwr, tvb, NIBHI(nibble+1,1), data); + nibble += 2; + } + else if (uiuc == 15) + { + /* 8.4.5.4.4 [1] Extended UIUC dependent IE table 291 */ + ext_uiuc = TVB_NIB_NIBBLE(5+nibble, tvb); + len = TVB_NIB_NIBBLE(5+nibble+1, tvb); + + tree = proto_tree_add_subtree_format(ie_tree, tvb, NIBHI(nibble, 5+2+len*2), ett_291, NULL, "UIUC: %d (Extended IE)", uiuc); + + proto_tree_add_uint(tree, hf_ulmap_ie_cid, tvb, NIBHI(nibble,4), cid); + nibble += 4; + proto_tree_add_uint(tree, hf_ulmap_ie_uiuc, tvb, NIBHI(nibble,1), uiuc); + nibble += 1; + +#if 0 + ti = proto_tree_add_uint(tree, hf_ulmap_uiuc11_ext, tvb, NIBHI(nibble,1), ext_uiuc); + nibble += 1; + proto_tree_add_uint(tree, hf_ulmap_uiuc11_len, tvb, NIBHI(nibble,1), len); + nibble += 1; +#endif + + len = 2 + BYTE_TO_NIB(len); /* length in nibbles */ + + /* data table 290a 8.4.5.4.4.1 */ + switch (ext_uiuc) { + case 0x00: + /* 8.4.5.4.5 Power_Control_IE */ + nibble = Power_Control_IE(tree, nibble, len, tvb); + break; + case 0x01: + /* 8.4.5.4.8 Mini-Subchannel_allocation_IE*/ + nibble = Mini_Subchannel_allocation_IE(tree, nibble, len, tvb); + break; + case 0x02: + /* 8.4.5.4.6 AAS_UL_IE*/ + nibble = AAS_UL_IE(tree, nibble, len, tvb); + break; + case 0x03: + /* 8.4.5.4.12 CQICH_Alloc_IE */ + nibble = CQICH_Alloc_IE(tree, nibble, len, tvb); + break; + case 0x04: + /* 8.4.5.4.7 UL_Zone_IE */ + nibble = UL_Zone_IE(tree, nibble, len, tvb); + break; + case 0x05: + /* 8.4.5.4.14 PHYMOD_UL_IE */ + nibble = PHYMOD_UL_IE(tree, nibble, len, tvb); + break; + case 0x06: + /* 8.4.5.4.11 MIMO_UL_IE */ + nibble = MIMO_UL_IE(tree, pinfo, nibble, len, tvb); + break; + case 0x07: + /* 8.4.5.4.22 ULMAP_Fast_Tracking_IE */ + nibble = ULMAP_Fast_Tracking_IE(tree, nibble, len, tvb); + break; + case 0x08: + /* 8.4.5.4.17 UL_PUSC_Burst_Allocation_in_other_segment_IE */ + nibble = UL_PUSC_Burst_Allocation_in_other_segment_IE(tree, nibble, len, tvb); + break; + case 0x09: + /* 8.4.5.4.21 Fast_Ranging_IE */ + nibble = Fast_Ranging_IE(tree, nibble, len, tvb); + break; + case 0x0a: + /* 8.4.5.4.15 UL_Allocation_Start_IE */ + nibble = UL_Allocation_Start_IE(tree, nibble, len, tvb); + break; + default: + proto_tree_add_bytes_format_value(tree, hf_ulmap_ie_reserved_extended_duic, tvb, NIBHI(nibble,len), NULL, "(reserved Extended UIUC: %d)", ext_uiuc); + nibble += len; + break; + } + } + else + { + /* 8.4.5.4 [2] regular IE 1-10, data grant burst type */ + aas_or_amc = 0; /* TODO */ + len = 3; + + if (aas_or_amc) len += 3; + + tree = proto_tree_add_subtree(ie_tree, tvb, NIBHI(nibble, 5+len), ett_287_2, NULL, "Data Grant Burst Profile"); + + proto_tree_add_uint(tree, hf_ulmap_ie_cid, tvb, NIBHI(nibble, 4), cid); + nibble += 4; + proto_tree_add_uint(tree, hf_ulmap_ie_uiuc, tvb, NIBHI(nibble, 1), uiuc); + nibble += 1; + + data = TVB_NIB_WORD(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc10_dur, tvb, NIBHI(nibble,3), data); + proto_tree_add_uint(tree, hf_ulmap_uiuc10_rep, tvb, NIBHI(nibble+2,1), data); + nibble += 3; + + if (aas_or_amc) { + data = TVB_NIB_BITS12(nibble, tvb); + proto_tree_add_uint(tree, hf_ulmap_uiuc10_slot_offset, tvb, NIBHI(nibble,3), data); + nibble += 3; + } + } + + /* length in nibbles */ + return (nibble - offset); +} + +static int dissect_mac_mgmt_msg_ulmap_decoder(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void* data _U_) +{ + /* 6.3.2.3.4 [2] UL-MAP table 18 */ + guint offset = 0; + guint length; + guint nib, pad; + proto_item *ti = NULL; + proto_tree *ulmap_tree = NULL; + proto_tree *ie_tree = NULL; + guint tvb_len; + + tvb_len = tvb_reported_length(tvb); + + /* display MAC UL-MAP */ + ti = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_ulmap_decoder, tvb, offset, -1, "UL-MAP"); + ulmap_tree = proto_item_add_subtree(ti, ett_ulmap); + + proto_tree_add_item(ulmap_tree, hf_ulmap_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + proto_tree_add_item(ulmap_tree, hf_ulmap_ucd_count, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + proto_tree_add_item(ulmap_tree, hf_ulmap_alloc_start_time, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(ulmap_tree, hf_ulmap_ofdma_sym, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + /* UL-MAP IEs */ + length = tvb_len - offset; /* remaining length in bytes */ + ie_tree = proto_tree_add_subtree_format(ulmap_tree, tvb, offset, length, ett_ulmap_ie, NULL, "UL-MAP IEs (%u bytes)", length); + + /* length = BYTE_TO_NIB(length); */ /* convert length to nibbles */ + nib = BYTE_TO_NIB(offset); + while (nib < ((tvb_len*2)-1)) { + nib += dissect_ulmap_ie(ie_tree, pinfo, nib, tvb_len*2, tvb); + } + pad = NIB_PADDING(nib); + if (pad) { + proto_tree_add_bytes_format(ulmap_tree, hf_ulmap_padding, tvb, NIBHI(nib,1), NULL, "Padding nibble"); + nib++; + } + return tvb_captured_length(tvb); +} + +/*gint wimax_decode_ulmapc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)*/ +gint wimax_decode_ulmapc(proto_tree *base_tree, packet_info* pinfo, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.6.2 [2] Compressed UL-MAP */ + /* returns length in nibbles */ + gint nib; + guint data; + proto_item *ti = NULL; + proto_tree *tree = NULL; + proto_tree *ie_tree = NULL; + + nib = offset; + + /* display MAC UL-MAP */ + ti = proto_tree_add_protocol_format(base_tree, proto_mac_mgmt_msg_ulmap_decoder, tvb, NIBHI(offset,length-offset), "Compressed UL-MAP (%u bytes)", NIB_ADDR(length-offset)); + tree = proto_item_add_subtree(ti, ett_306); + + /* Decode and display the UL-MAP */ + data = TVB_NIB_BYTE(nib, tvb); + proto_tree_add_uint(tree, hf_ulmap_ucd_count, tvb, NIBHI(nib,2), data); + nib += 2; + data = TVB_NIB_LONG(nib, tvb); + proto_tree_add_uint(tree, hf_ulmap_alloc_start_time, tvb, NIBHI(nib,8), data); + nib += 8; + data = TVB_NIB_BYTE(nib, tvb); + proto_tree_add_uint(tree, hf_ulmap_ofdma_sym, tvb, NIBHI(nib,2), data); /* added 2005 */ + nib += 2; + + ie_tree = proto_tree_add_subtree_format(tree, tvb, NIBHI(nib,length-nib), ett_306_ul, NULL, "UL-MAP IEs (%u bytes)", NIB_ADDR(length-nib)); + while (nib < length-1) { + nib += dissect_ulmap_ie(ie_tree, pinfo, nib, length-nib, tvb); + } + + /* padding */ + if (nib & 1) { + proto_tree_add_bytes_format(tree, hf_ulmap_padding, tvb, NIBHI(nib,1), NULL, "Padding nibble"); + nib++; + } + + + return length; +} + + +gint wimax_decode_ulmap_reduced_aas(proto_tree *base_tree, gint offset, gint length, tvbuff_t *tvb) +{ + /* 8.4.5.8.2 Reduced AAS private UL-MAP */ + /* offset and length are in bits since this is called from within + * the Reduced AAS private DL-MAP + * return length in bits */ + gint bit; + guint data; + proto_tree *tree; + gint azci, azpi, umii, phmi, powi; + + bit = offset; + + tree = proto_tree_add_subtree(base_tree, tvb, BITHI(bit,length), ett_308b, NULL, "Reduced_AAS_Private_UL_MAP"); + + /* Decode and display the Reduced AAS private UL-MAP */ + XBIT_HF_VALUE(azci, 1, hf_ulmap_reduced_aas_aas_zone_configuration_included); + XBIT_HF_VALUE(azpi, 1, hf_ulmap_reduced_aas_aas_zone_position_included); + XBIT_HF_VALUE(umii, 1, hf_ulmap_reduced_aas_ul_map_information_included); + XBIT_HF_VALUE(phmi, 1, hf_ulmap_reduced_aas_phy_modification_included); + XBIT_HF_VALUE(powi, 1, hf_ulmap_reduced_aas_power_control_included); + XBIT_HF(2, hf_ulmap_reduced_aas_include_feedback_header); + XBIT_HF(2, hf_ulmap_reduced_aas_encoding_mode); + + if (azci) { + XBIT_HF(2, hf_ulmap_reduced_aas_permutation); + XBIT_HF(7, hf_ulmap_reduced_aas_ul_permbase); + XBIT_HF(2, hf_ulmap_reduced_aas_preamble_indication); + XBIT_HF(5, hf_ulmap_reduced_aas_padding); + } + if (azpi) { + XBIT_HF(8, hf_ulmap_reduced_aas_zone_symbol_offset); + XBIT_HF(8, hf_ulmap_reduced_aas_zone_length); + } + if (umii) { + XBIT_HF(8, hf_ulmap_reduced_aas_ucd_count); + data = TVB_BIT_BITS64(bit,tvb,32); + proto_tree_add_uint64(tree, hf_ulmap_reduced_aas_private_map_alloc_start_time, tvb, BITHI(bit,32), data); + bit += 32; + } + if (phmi) { + XBIT_HF(1, hf_ulmap_reduced_aas_preamble_select); + XBIT_HF(4, hf_ulmap_reduced_aas_preamble_shift_index); + XBIT_HF(1, hf_ulmap_reduced_aas_pilot_pattern_modifier); + data = TVB_BIT_BITS32(bit,tvb,22); + proto_tree_add_uint64(tree, hf_ulmap_reduced_aas_pilot_pattern_index, tvb, BITHI(bit,22), data); + bit += 22; + } + if (powi) { + XBIT_HF(8, hf_ulmap_reduced_aas_power_control); + } + XBIT_HF(3, hf_ulmap_reduced_aas_ul_frame_offset); + XBIT_HF(12, hf_ulmap_reduced_aas_slot_offset); + XBIT_HF(10, hf_ulmap_reduced_aas_slot_duration); + XBIT_HF(4, hf_ulmap_reduced_aas_uiuc_nep); + if (harq) { + XBIT_HF(4, hf_ulmap_reduced_aas_acid); + XBIT_HF(1, hf_ulmap_reduced_aas_ai_sn); + XBIT_HF(3, hf_ulmap_reserved_uint); + if (ir_type) { + XBIT_HF(4, hf_ulmap_reduced_aas_nsch); + XBIT_HF(2, hf_ulmap_reduced_aas_spid); + XBIT_HF(2, hf_ulmap_reserved_uint); + } + } + XBIT_HF(2, hf_ulmap_reduced_aas_repetition_coding_indication); + + return (bit - offset); /* length in bits */ +} + + +/* Register Wimax Mac Payload Protocol and Dissector */ +void proto_register_mac_mgmt_msg_ulmap(void) +{ + /* UL-MAP fields display */ + static hf_register_info hf[] = + { +#if 0 + { + &hf_ulmap_fch_expected, + { + "FCH Expected", "wmx.ulmap.fch.expected", + FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#endif +#if 0 + { + &hf_ulmap_ie, + { + "UL-MAP IE", "wmx.ulmap.ie", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#endif + { + &hf_ulmap_ie_cid, + { + "CID", "wmx.ulmap.ie.cid", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_ie_uiuc, + { + "UIUC", "wmx.ulmap.ie.uiuc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_ofdma_sym, + { + "Num OFDMA Symbols", "wmx.ulmap.ofdma.sym", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_ie_diuc_ext, + { + "Extended DIUC", "wmx.ulmap.ie.ext_diuc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_ie_diuc_ext2, + { + "Extended-2 DIUC", "wmx.ulmap.ie.ext2_diuc", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_ie_length, + { + "Length", "wmx.ilmap.ie.length", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_ie_reserved_extended2_duic, + { + "Reserved Extended-2 DIUC", "wmx.ulmap.ie.ext2_diuc_reserved", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_ie_reserved_extended_duic, + { + "Reserved Extended DIUC", "wmx.ulmap.ie.ext_diuc_reserved", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_reserved, + { + "Reserved", "wmx.ulmap.rsv", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_alloc_start_time, + { + "Uplink Channel ID", "wmx.ulmap.start", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_ucd_count, + { + "UCD Count", "wmx.ulmap.ucd", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc0_numsub, + { + "No. subchannels", "wmx.ulmap.uiuc0.numsub", + FT_UINT32, BASE_DEC, NULL, 0x000003f8, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc0_numsym, + { + "No. OFDMA symbols", "wmx.ulmap.uiuc0.numsym", + FT_UINT32, BASE_DEC, NULL, 0x0001fc00, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc0_rsv, + { + "Reserved", "wmx.ulmap.uiuc0.rsv", + FT_UINT32, BASE_DEC, NULL, 0x00000007, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc0_subofs, + { + "Subchannel offset", "wmx.ulmap.uiuc0.subofs", + FT_UINT32, BASE_DEC, NULL, 0x00fe0000, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc0_symofs, + { + "OFDMA symbol offset", "wmx.ulmap.uiuc0.symofs", + FT_UINT32, BASE_DEC, NULL, 0xff000000, NULL, HFILL + } + }, +#if 0 + { + &hf_ulmap_uiuc11_data, + { + "Data", "wmx.ulmap.uiuc11.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc11_ext, + { + "Extended 2 UIUC", "wmx.ulmap.uiuc11.ext", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc11_len, + { + "Length", "wmx.ulmap.uiuc11.len", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#endif + { + &hf_ulmap_uiuc12_dri, + { + "Dedicated ranging indicator", "wmx.ulmap.uiuc12.dri", + FT_UINT32, BASE_DEC, NULL, 0x00000001, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc10_dur, + { + "Duration", "wmx.ulmap.uiuc12.dur", + FT_UINT16, BASE_DEC, NULL, 0xFFc0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc12_method, + { + "Ranging Method", "wmx.ulmap.uiuc12.method", + FT_UINT32, BASE_DEC, NULL, 0x00000006, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc12_numsub, + { + "No. Subchannels", "wmx.ulmap.uiuc12.numsub", + FT_UINT32, BASE_DEC, NULL, 0x000003F8, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc12_numsym, + { + "No. OFDMA Symbols", "wmx.ulmap.uiuc12.numsym", + FT_UINT32, BASE_DEC, NULL, 0x0001Fc00, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc10_rep, + { + "Repetition Coding indication", "wmx.ulmap.uiuc10.rep", + FT_UINT16, BASE_DEC, NULL, 0x0030, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc10_slot_offset, + { + "Slot offset", "wmx.ulmap.uiuc10.slot_offset", + FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc12_subofs, + { + "Subchannel Offset", "wmx.ulmap.uiuc12.subofs", + FT_UINT32, BASE_DEC, NULL, 0x00Fe0000, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc12_symofs, + { + "OFDMA Symbol Offset", "wmx.ulmap.uiuc12.symofs", + FT_UINT32, BASE_DEC, NULL, 0xFF000000, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc13_numsub, + { + "No. Subchannels/SZ Shift Value", "wmx.ulmap.uiuc13.numsub", + FT_UINT32, BASE_DEC, NULL, 0x000003f8, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc13_numsym, + { + "No. OFDMA symbols", "wmx.ulmap.uiuc13.numsym", + FT_UINT32, BASE_DEC, NULL, 0x0001fc00, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc13_papr, + { + "PAPR Reduction/Safety Zone", "wmx.ulmap.uiuc13.papr", + FT_UINT32, BASE_DEC, NULL, 0x00000004, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc13_rsv, + { + "Reserved", "wmx.ulmap.uiuc13.rsv", + FT_UINT32, BASE_DEC, NULL, 0x00000001, NULL, HFILL + } + }, +#if 0 + { + &hf_ulmap_crc16, + { + "CRC-16", "wmx.ulmap.crc16", + FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_crc16_status, + { + "CRC-16 Status", "wmx.ulmap.crc16.status", + FT_UINT8, BASE_NONE, VALS(plugin_proto_checksum_vals), 0x0, NULL, HFILL + } + }, +#endif + { + &hf_ulmap_padding, + { + "Padding", "wmx.ulmap.padding", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc13_subofs, + { + "Subchannel offset", "wmx.ulmap.uiuc13.subofs", + FT_UINT32, BASE_DEC, NULL, 0x00fe0000, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc13_symofs, + { + "OFDMA symbol offset", "wmx.ulmap.uiuc13.symofs", + FT_UINT32, BASE_DEC, NULL, 0xff000000, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc13_zone, + { + "Sounding Zone", "wmx.ulmap.uiuc13.zone", + FT_UINT32, BASE_DEC, NULL, 0x00000002, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc14_bwr, + { + "BW request mandatory", "wmx.ulmap.uiuc14.bwr", + FT_UINT8, BASE_DEC, NULL, 0x01, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc14_code, + { + "Ranging code", "wmx.ulmap.uiuc14.code", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc14_dur, + { + "Duration", "wmx.ulmap.uiuc14.dur", + FT_UINT16, BASE_DEC, NULL, 0xfc00, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc14_idx, + { + "Frame Number Index", "wmx.ulmap.uiuc14.idx", + FT_UINT16, BASE_DEC, NULL, 0x000F, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc14_rep, + { + "Repetition Coding Indication", "wmx.ulmap.uiuc14.rep", + FT_UINT16, BASE_DEC, NULL, 0x0030, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc14_sub, + { + "Ranging subchannel", "wmx.ulmap.uiuc14.sub", + FT_UINT8, BASE_DEC, NULL, 0xfe, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc14_sym, + { + "Ranging symbol", "wmx.ulmap.uiuc14.sym", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc14_uiuc, + { + "UIUC", "wmx.ulmap.uiuc14.uiuc", + FT_UINT16, BASE_DEC, NULL, 0x03c0, NULL, HFILL + } + }, +#if 0 + { + &hf_ulmap_uiuc15_data, + { + "Data", "wmx.ulmap.uiuc15.data", + FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc15_ext, + { + "Extended UIUC", "wmx.ulmap.uiuc15.ext", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, + { + &hf_ulmap_uiuc15_len, + { + "Length", "wmx.ulmap.uiuc15.len", + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL + } + }, +#endif + /* Generated via "one time" script to help create filterable fields */ + { &hf_ulmap_dedicated_ul_control_length, { "Length", "wmx.ulmap.dedicated_ul_control.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_dedicated_ul_control_control_header, { "Control Header", "wmx.ulmap.dedicated_ul_control.control_header", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_dedicated_ul_control_num_sdma_layers, { "Num SDMA layers", "wmx.ulmap.dedicated_ul_control.num_sdma_layers", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_dedicated_ul_control_pilot_pattern, { "Pilot Pattern", "wmx.ulmap.dedicated_ul_control.pilot_pattern", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_dedicated_mimo_ul_control_matrix, { "Matrix", "wmx.ulmap.dedicated_mimo_ul_control.matrix", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_dedicated_mimo_ul_control_n_layer, { "N_layer", "wmx.ulmap.dedicated_mimo_ul_control.n_layer", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_chase_dedicated_ul_control_indicator, { "Dedicated UL Control Indicator", "wmx.ulmap.harq_chase.dedicated_ul_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_chase_uiuc, { "UIUC", "wmx.ulmap.harq_chase.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_chase_repetition_coding_indication, { "Repetition Coding Indication", "wmx.ulmap.harq_chase.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_chase_duration, { "Duration", "wmx.ulmap.harq_chase.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_chase_acid, { "ACID", "wmx.ulmap.harq_chase.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_chase_ai_sn, { "AI_SN", "wmx.ulmap.harq_chase.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_chase_ack_disable, { "ACK_disable", "wmx.ulmap.harq_chase.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reserved_uint, { "Reserved", "wmx.ulmap.reserved.uint", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_ctc_dedicated_ul_control_indicator, { "Dedicated UL Control Indicator", "wmx.ulmap.harq_ir_ctc.dedicated_ul_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_ctc_nep, { "N(EP)", "wmx.ulmap.harq_ir_ctc.nep", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_ctc_nsch, { "N(SCH)", "wmx.ulmap.harq_ir_ctc.nsch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_ctc_spid, { "SPID", "wmx.ulmap.harq_ir_ctc.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_ctc_acin, { "ACIN", "wmx.ulmap.harq_ir_ctc.acin", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_ctc_ai_sn, { "AI_SN", "wmx.ulmap.harq_ir_ctc.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_ctc_ack_disable, { "ACK_disable", "wmx.ulmap.harq_ir_ctc.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_cc_dedicated_ul_control_indicator, { "Dedicated UL Control Indicator", "wmx.ulmap.harq_ir_cc.dedicated_ul_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_cc_uiuc, { "UIUC", "wmx.ulmap.harq_ir_cc.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_cc_repetition_coding_indication, { "Repetition Coding Indication", "wmx.ulmap.harq_ir_cc.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_cc_duration, { "Duration", "wmx.ulmap.harq_ir_cc.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_cc_spid, { "SPID", "wmx.ulmap.harq_ir_cc.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_cc_acid, { "ACID", "wmx.ulmap.harq_ir_cc.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_cc_ai_sn, { "AI_SN", "wmx.ulmap.harq_ir_cc.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ir_cc_ack_disable, { "ACK_disable", "wmx.ulmap.harq_ir_cc.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_mu_indicator, { "MU indicator", "wmx.ulmap.mimo_ul_chase_harq.mu_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_dedicated_mimo_ulcontrol_indicator, { "Dedicated MIMO ULControl Indicator", "wmx.ulmap.mimo_ul_chase_harq.dedicated_mimo_ulcontrol_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_ack_disable, { "ACK Disable", "wmx.ulmap.mimo_ul_chase_harq.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_matrix, { "Matrix", "wmx.ulmap.mimo_ul_chase_harq.matrix", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_duration, { "Duration", "wmx.ulmap.mimo_ul_chase_harq.duration", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_uiuc, { "UIUC", "wmx.ulmap.mimo_ul_chase_harq.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_repetition_coding_indication, { "Repetition Coding Indication", "wmx.ulmap.mimo_ul_chase_harq.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_acid, { "ACID", "wmx.ulmap.mimo_ul_chase_harq.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_chase_harq_ai_sn, { "AI_SN", "wmx.ulmap.mimo_ul_chase_harq.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_mu_indicator, { "MU indicator", "wmx.ulmap.mimo_ul_ir_harq.mu_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_dedicated_mimo_ul_control_indicator, { "Dedicated MIMO UL Control Indicator", "wmx.ulmap.mimo_ul_ir_harq.dedicated_mimo_ul_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_ack_disable, { "ACK Disable", "wmx.ulmap.mimo_ul_ir_harq.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_matrix, { "Matrix", "wmx.ulmap.mimo_ul_ir_harq.matrix", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_nsch, { "N(SCH)", "wmx.ulmap.mimo_ul_ir_harq.nsch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_nep, { "N(EP)", "wmx.ulmap.mimo_ul_ir_harq.nep", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_spid, { "SPID", "wmx.ulmap.mimo_ul_ir_harq.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_acid, { "ACID", "wmx.ulmap.mimo_ul_ir_harq.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_ai_sn, { "AI_SN", "wmx.ulmap.mimo_ul_ir_harq.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_mu_indicator, { "MU indicator", "wmx.ulmap.mimo_ul_ir_harq_cc.mu_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_dedicated_mimo_ul_control_indicator, { "Dedicated MIMO UL Control Indicator", "wmx.ulmap.mimo_ul_ir_harq_cc.dedicated_mimo_ul_control_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_ack_disable, { "ACK Disable", "wmx.ulmap.mimo_ul_ir_harq_cc.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_matrix, { "Matrix", "wmx.ulmap.mimo_ul_ir_harq_cc.matrix", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_duration, { "Duration", "wmx.ulmap.mimo_ul_ir_harq_cc.duration", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_uiuc, { "UIUC", "wmx.ulmap.mimo_ul_ir_harq_cc.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_repetition_coding_indication, { "Repetition Coding Indication", "wmx.ulmap.mimo_ul_ir_harq_cc.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_acid, { "ACID", "wmx.ulmap.mimo_ul_ir_harq_cc.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_ai_sn, { "AI_SN", "wmx.ulmap.mimo_ul_ir_harq_cc.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_ir_harq_cc_spid, { "SPID", "wmx.ulmap.mimo_ul_ir_harq_cc.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_stc_harq_tx_count, { "Tx count", "wmx.ulmap.mimo_ul_stc_harq.tx_count", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_stc_harq_duration, { "Duration", "wmx.ulmap.mimo_ul_stc_harq.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_stc_harq_sub_burst_offset_indication, { "Sub-burst offset indication", "wmx.ulmap.mimo_ul_stc_harq.sub_burst_offset_indication", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_stc_harq_sub_burst_offset, { "Sub-burst offset", "wmx.ulmap.mimo_ul_stc_harq.sub_burst_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_stc_harq_ack_disable, { "ACK Disable", "wmx.ulmap.mimo_ul_stc_harq.ack_disable", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_stc_harq_uiuc, { "UIUC", "wmx.ulmap.mimo_ul_stc_harq.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_stc_harq_repetition_coding_indication, { "Repetition Coding Indication", "wmx.ulmap.mimo_ul_stc_harq.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mimo_ul_stc_harq_acid, { "ACID", "wmx.ulmap.mimo_ul_stc_harq.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_power_control, { "Power Control", "wmx.ulmap.power_control", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_power_measurement_frame, { "Power measurement frame", "wmx.ulmap.power_measurement_frame", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mini_subcha_alloc_extended_2_uiuc, { "Extended-2 UIUC", "wmx.ulmap.mini_subcha_alloc.extended_2_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mini_subcha_alloc_length, { "Length", "wmx.ulmap.mini_subcha_alloc.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mini_subcha_alloc_ctype, { "Ctype", "wmx.ulmap.mini_subcha_alloc.ctype", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mini_subcha_alloc_duration, { "Duration", "wmx.ulmap.mini_subcha_alloc.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mini_subcha_alloc_cid, { "CID", "wmx.ulmap.mini_subcha_alloc.cid", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mini_subcha_alloc_uiuc, { "UIUC", "wmx.ulmap.mini_subcha_alloc.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mini_subcha_alloc_repetition, { "Repetition", "wmx.ulmap.mini_subcha_alloc.repetition", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_mini_subcha_alloc_padding, { "Padding", "wmx.ulmap.mini_subcha_alloc.padding", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_ul_extended_uiuc, { "Extended UIUC", "wmx.ulmap.aas_ul.extended_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_ul_length, { "Length", "wmx.ulmap.aas_ul.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_ul_permutation, { "Permutation", "wmx.ulmap.aas_ul.permutation", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_ul_ul_permbase, { "UL_PermBase", "wmx.ulmap.aas_ul.ul_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_ul_ofdma_symbol_offset, { "OFDMA symbol offset", "wmx.ulmap.aas_ul.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_ul_aas_zone_length, { "AAS zone length", "wmx.ulmap.aas_ul.aas_zone_length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_ul_uplink_preamble_config, { "Uplink preamble config", "wmx.ulmap.aas_ul.uplink_preamble_config", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_ul_preamble_type, { "Preamble type", "wmx.ulmap.aas_ul.preamble_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_extended_uiuc, { "Extended UIUC", "wmx.ulmap.cqich_alloc.extended_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_length, { "Length", "wmx.ulmap.cqich_alloc.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_cqich_id, { "CQICH_ID", "wmx.ulmap.cqich_alloc.cqich_id", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_allocation_offset, { "Allocation offset", "wmx.ulmap.cqich_alloc.allocation_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_period, { "Period (p)", "wmx.ulmap.cqich_alloc.period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_frame_offset, { "Frame offset", "wmx.ulmap.cqich_alloc.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_duration, { "Duration (d)", "wmx.ulmap.cqich_alloc.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_report_configuration_included, { "Report configuration included", "wmx.ulmap.cqich_alloc.report_configuration_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_feedback_type, { "Feedback Type", "wmx.ulmap.cqich_alloc.feedback_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_report_type, { "Report type", "wmx.ulmap.cqich_alloc.report_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_cinr_preamble_report_type, { "CINR preamble report type", "wmx.ulmap.cqich_alloc.cinr_preamble_report_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_zone_permutation, { "Zone permutation", "wmx.ulmap.cqich_alloc.zone_permutation", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_zone_type, { "Zone type", "wmx.ulmap.cqich_alloc.zone_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_zone_prbs_id, { "Zone PRBS_ID", "wmx.ulmap.cqich_alloc.zone_prbs_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_major_group_indication, { "Major group indication", "wmx.ulmap.cqich_alloc.major_group_indication", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_pusc_major_group_bitmap, { "PUSC Major group bitmap", "wmx.ulmap.cqich_alloc.pusc_major_group_bitmap", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_cinr_zone_measurement_type, { "CINR zone measurement type", "wmx.ulmap.cqich_alloc.cinr_zone_measurement_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_averaging_parameter_included, { "Averaging parameter included", "wmx.ulmap.cqich_alloc.averaging_parameter_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_averaging_parameter, { "Averaging parameter", "wmx.ulmap.cqich_alloc.averaging_parameter", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_alloc_mimo_permutation_feedback_cycle, { "MIMO_permutation_feedback_cycle", "wmx.ulmap.cqich_alloc.mimo_permutation_feedback_cycle", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_zone_extended_uiuc, { "Extended UIUC", "wmx.ulmap.zone.extended_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_zone_length, { "Length", "wmx.ulmap.zone.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_zone_ofdma_symbol_offset, { "OFDMA symbol offset", "wmx.ulmap.zone.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_zone_permutation, { "Permutation", "wmx.ulmap.zone.permutation", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_zone_ul_permbase, { "UL_PermBase", "wmx.ulmap.zone.ul_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_zone_amc_type, { "AMC type", "wmx.ulmap.zone.amc_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_zone_use_all_sc_indicator, { "Use All SC indicator", "wmx.ulmap.zone.use_all_sc_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_zone_disable_subchannel_rotation, { "Disable subchannel rotation", "wmx.ulmap.zone.disable_subchannel_rotation", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_phymod_ul_extended_uiuc, { "Extended UIUC", "wmx.ulmap.phymod_ul.extended_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_phymod_ul_length, { "Length", "wmx.ulmap.phymod_ul.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_phymod_ul_preamble_modifier_type, { "Preamble Modifier Type", "wmx.ulmap.phymod_ul.preamble_modifier_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_phymod_ul_preamble_frequency_shift_index, { "Preamble frequency shift index", "wmx.ulmap.phymod_ul.preamble_frequency_shift_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_phymod_ul_preamble_time_shift_index, { "Preamble Time Shift index", "wmx.ulmap.phymod_ul.preamble_time_shift_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_phymod_ul_pilot_pattern_modifier, { "Pilot Pattern Modifier", "wmx.ulmap.phymod_ul.pilot_pattern_modifier", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_phymod_ul_pilot_pattern_index, { "Pilot Pattern Index", "wmx.ulmap.phymod_ul.pilot_pattern_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_tracking_extended_uiuc, { "Extended UIUC", "wmx.ulmap.fast_tracking.extended_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_tracking_length, { "Length", "wmx.ulmap.fast_tracking.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_tracking_map_index, { "Map Index", "wmx.ulmap.fast_tracking.map_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_tracking_power_correction, { "Power correction", "wmx.ulmap.fast_tracking.power_correction", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_tracking_frequency_correction, { "Frequency correction", "wmx.ulmap.fast_tracking.frequency_correction", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_tracking_time_correction, { "Time correction", "wmx.ulmap.fast_tracking.time_correction", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_extended_uiuc, { "Extended UIUC", "wmx.ulmap.pusc_burst_allocation.extended_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_length, { "Length", "wmx.ulmap.pusc_burst_allocation.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_uiuc, { "UIUC", "wmx.ulmap.pusc_burst_allocation.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_segment, { "Segment", "wmx.ulmap.pusc_burst_allocation.segment", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_ul_permbase, { "UL_PermBase", "wmx.ulmap.pusc_burst_allocation.ul_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_ofdma_symbol_offset, { "OFDMA symbol offset", "wmx.ulmap.pusc_burst_allocation.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_subchannel_offset, { "Subchannel offset", "wmx.ulmap.pusc_burst_allocation.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_duration, { "Duration", "wmx.ulmap.pusc_burst_allocation.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_pusc_burst_allocation_repetition_coding_indication, { "Repetition coding indication", "wmx.ulmap.pusc_burst_allocation.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_ranging_extended_uiuc, { "Extended UIUC", "wmx.ulmap.fast_ranging.extended_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_ranging_length, { "Length", "wmx.ulmap.fast_ranging.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_ranging_ho_id_indicator, { "HO_ID indicator", "wmx.ulmap.fast_ranging.ho_id_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_ranging_ho_id, { "HO_ID", "wmx.ulmap.fast_ranging.ho_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_ranging_mac_address, { "MAC address", "wmx.ulmap.fast_ranging.mac_address", FT_ETHER, BASE_NONE, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_ranging_uiuc, { "UIUC", "wmx.ulmap.fast_ranging.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_ranging_duration, { "Duration", "wmx.ulmap.fast_ranging.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_fast_ranging_repetition_coding_indication, { "Repetition coding indication", "wmx.ulmap.fast_ranging.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_allocation_start_extended_uiuc, { "Extended UIUC", "wmx.ulmap.allocation_start.extended_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_allocation_start_length, { "Length", "wmx.ulmap.allocation_start.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_allocation_start_ofdma_symbol_offset, { "OFDMA symbol offset", "wmx.ulmap.allocation_start.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_allocation_start_subchannel_offset, { "Subchannel offset", "wmx.ulmap.allocation_start.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_extended_2_uiuc, { "Extended-2 UIUC", "wmx.ulmap.cqich_enhanced_alloc.extended_2_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_length, { "Length", "wmx.ulmap.cqich_enhanced_alloc.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_cqich_id, { "CQICH_ID", "wmx.ulmap.cqich_enhanced_alloc.cqich_id", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_period, { "Period (p)", "wmx.ulmap.cqich_enhanced_alloc.period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_frame_offset, { "Frame offset", "wmx.ulmap.cqich_enhanced_alloc.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_duration, { "Duration (d)", "wmx.ulmap.cqich_enhanced_alloc.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_cqich_num, { "CQICH_Num", "wmx.ulmap.cqich_enhanced_alloc.cqich_num", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_feedback_type, { "Feedback Type", "wmx.ulmap.cqich_enhanced_alloc.feedback_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_allocation_index, { "Allocation Index", "wmx.ulmap.cqich_enhanced_alloc.allocation_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_cqich_type, { "CQICH Type", "wmx.ulmap.cqich_enhanced_alloc.cqich_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_sttd_indication, { "STTD indication", "wmx.ulmap.cqich_enhanced_alloc.sttd_indication", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_band_amc_precoding_mode, { "Band_AMC_Precoding_Mode", "wmx.ulmap.cqich_enhanced_alloc.band_amc_precoding_mode", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_cqich_enhanced_alloc_nr_precoders_feedback, { "Nr_Precoders_Feedback (=N)", "wmx.ulmap.cqich_enhanced_alloc.nr_precoders_feedback", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_extended_2_uiuc, { "Extended-2 UIUC", "wmx.ulmap.anchor_bs_switch.extended_2_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_length, { "Length", "wmx.ulmap.anchor_bs_switch.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_n_anchor_bs_switch, { "N_Anchor_BS_switch", "wmx.ulmap.anchor_bs_switch.n_anchor_bs_switch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_reduced_cid, { "Reduced CID", "wmx.ulmap.anchor_bs_switch.reduced_cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_action_code, { "Action Code", "wmx.ulmap.anchor_bs_switch.action_code", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_action_time, { "Action Time (A)", "wmx.ulmap.anchor_bs_switch.action_time", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_temp_bs_id, { "TEMP_BS_ID", "wmx.ulmap.anchor_bs_switch.temp_bs_id", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_ak_change_indicator, { "AK Change Indicator", "wmx.ulmap.anchor_bs_switch.ak_change_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_cqich_allocation_indicator, { "CQICH Allocation Indicator", "wmx.ulmap.anchor_bs_switch.cqich_allocation_indicator", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_feedback_channel_offset, { "Feedback channel offset", "wmx.ulmap.anchor_bs_switch.feedback_channel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_cqich_id, { "CQICH_ID", "wmx.ulmap.anchor_bs_switch.cqich_id", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_period, { "Period (=p)", "wmx.ulmap.anchor_bs_switch.period", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_frame_offset, { "Frame offset", "wmx.ulmap.anchor_bs_switch.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_duration, { "Duration (=d)", "wmx.ulmap.anchor_bs_switch.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_anchor_bs_switch_mimo_permutation_feedback_code, { "MIMO_permutation_feedback_code", "wmx.ulmap.anchor_bs_switch.mimo_permutation_feedback_code", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_extended_2_uiuc, { "Extended-2 UIUC", "wmx.ulmap.sounding_command.extended_2_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_length, { "Length", "wmx.ulmap.sounding_command.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_type, { "Sounding_Type", "wmx.ulmap.sounding_command.sounding_command.type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_send_sounding_report_flag, { "Send Sounding Report Flag", "wmx.ulmap.sounding_command.send_sounding_report_flag", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_relevance_flag, { "Sounding Relevance Flag", "wmx.ulmap.sounding_command.relevance_flag", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_relevance, { "Sounding_Relevance", "wmx.ulmap.sounding_command.sounding_relevance", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_include_additional_feedback, { "Include additional feedback", "wmx.ulmap.sounding_command.include_additional_feedback", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_num_sounding_symbols, { "Num_Sounding_Symbols", "wmx.ulmap.sounding_command.num_sounding_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_separability_type, { "Separability Type", "wmx.ulmap.sounding_command.separability_type", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_max_cyclic_shift_index_p, { "Max Cyclic Shift Index P", "wmx.ulmap.sounding_command.max_cyclic_shift_index_p", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_decimation_value, { "Decimation Value D", "wmx.ulmap.sounding_command.decimation_value", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_decimation_offset_randomization, { "Decimation offset randomization", "wmx.ulmap.sounding_command.decimation_offset_randomization", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_symbol_index, { "Sounding symbol index", "wmx.ulmap.sounding_command.sounding_command.symbol_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_number_of_cids, { "Number of CIDs", "wmx.ulmap.sounding_command.number_of_cids", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_shorted_basic_cid, { "Shorted Basic CID", "wmx.ulmap.sounding_command.shorted_basic_cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_power_assignment_method, { "Power Assignment Method", "wmx.ulmap.sounding_command.power_assignment_method", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_power_boost, { "Power boost", "wmx.ulmap.sounding_command.power_boost", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_multi_antenna_flag, { "Multi-Antenna Flag", "wmx.ulmap.sounding_command.multi_antenna_flag", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_allocation_mode, { "Allocation Mode", "wmx.ulmap.sounding_command.allocation_mode", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_band_bit_map, { "Band bit map", "wmx.ulmap.sounding_command.band_bit_map", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_starting_frequency_band, { "Starting frequency band", "wmx.ulmap.sounding_command.starting_frequency_band", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_number_of_frequency_bands, { "Number of frequency bands", "wmx.ulmap.sounding_command.number_of_frequency_bands", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_cyclic_time_shift_index, { "Cyclic time shift index m", "wmx.ulmap.sounding_command.cyclic_time_shift_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_decimation_offset, { "Decimation offset d", "wmx.ulmap.sounding_command.decimation_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_use_same_symbol_for_additional_feedback, { "Use same symbol for additional feedback", "wmx.ulmap.sounding_command.use_same_symbol_for_additional_feedback", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_periodicity, { "Periodicity", "wmx.ulmap.sounding_command.periodicity", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_permutation, { "Permutation", "wmx.ulmap.sounding_command.permutation", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_dl_permbase, { "DL_PermBase", "wmx.ulmap.sounding_command.dl_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_shortened_basic_cid, { "Shortened basic CID", "wmx.ulmap.sounding_command.shortened_basic_cid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_subchannel_offset, { "Subchannel offset", "wmx.ulmap.sounding_command.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_sounding_command_number_of_subchannels, { "Number of subchannels", "wmx.ulmap.sounding_command.number_of_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ulmap_extended_2_uiuc, { "Extended-2 UIUC", "wmx.ulmap.harq_ulmap.extended_2_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ulmap_length, { "Length", "wmx.ulmap.harq_ulmap.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ulmap_rcid_type, { "RCID_Type", "wmx.ulmap.harq_ulmap.rcid_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ulmap_mode, { "Mode", "wmx.ulmap.harq_ulmap.mode", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ulmap_allocation_start_indication, { "Allocation Start Indication", "wmx.ulmap.harq_ulmap.allocation_start_indication", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ulmap_ofdma_symbol_offset, { "OFDMA Symbol offset", "wmx.ulmap.harq_ulmap.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ulmap_subchannel_offset, { "Subchannel offset", "wmx.ulmap.harq_ulmap.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ulmap_n_sub_burst, { "N sub Burst", "wmx.ulmap.harq_ulmap.n_sub_burst", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ackch_region_alloc_extended_2_uiuc, { "Extended-2 UIUC", "wmx.ulmap.harq_ackch_region_alloc.extended_2_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ackch_region_alloc_length, { "Length", "wmx.ulmap.harq_ackch_region_alloc.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ackch_region_alloc_ofdma_symbol_offset, { "OFDMA Symbol Offset", "wmx.ulmap.harq_ackch_region_alloc.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ackch_region_alloc_subchannel_offset, { "Subchannel Offset", "wmx.ulmap.harq_ackch_region_alloc.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ackch_region_alloc_num_ofdma_symbols, { "No. OFDMA Symbols", "wmx.ulmap.harq_ackch_region_alloc.num_ofdma_symbols", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_harq_ackch_region_alloc_num_subchannels, { "No. Subchannels", "wmx.ulmap.harq_ackch_region_alloc.num_subchannels", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_extended_2_uiuc, { "Extended-2 UIUC", "wmx.ulmap.aas_sdma.extended_2_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_length, { "Length", "wmx.ulmap.aas_sdma.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_rcid_type, { "RCID_Type", "wmx.ulmap.aas_sdma.rcid_type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_num_burst_region, { "Num Burst Region", "wmx.ulmap.aas_sdma.num_burst_region", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_slot_offset, { "Slot offset", "wmx.ulmap.aas_sdma.slot_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_slot_duration, { "Slot duration", "wmx.ulmap.aas_sdma.slot_duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_number_of_users, { "Number of users", "wmx.ulmap.aas_sdma.number_of_users", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_encoding_mode, { "Encoding Mode", "wmx.ulmap.aas_sdma.encoding_mode", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_power_adjust, { "Power Adjust", "wmx.ulmap.aas_sdma.power_adjust", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_pilot_pattern_modifier, { "Pilot Pattern Modifier", "wmx.ulmap.aas_sdma.pilot_pattern_modifier", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_preamble_modifier_index, { "Preamble Modifier Index", "wmx.ulmap.aas_sdma.preamble_modifier_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_pilot_pattern, { "Pilot Pattern", "wmx.ulmap.aas_sdma.pilot_pattern", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_diuc, { "DIUC", "wmx.ulmap.aas_sdma.diuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_repetition_coding_indication, { "Repetition Coding Indication", "wmx.ulmap.aas_sdma.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_acid, { "ACID", "wmx.ulmap.aas_sdma.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_ai_sn, { "AI_SN", "wmx.ulmap.aas_sdma.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_nep, { "N(EP)", "wmx.ulmap.aas_sdma.nep", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_nsch, { "N(SCH)", "wmx.ulmap.aas_sdma.nsch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_spid, { "SPID", "wmx.ulmap.aas_sdma.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_aas_sdma_power_adjustment, { "Power Adjustment", "wmx.ulmap.aas_sdma.power_adjustment", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_extended_2_uiuc, { "Extended-2 UIUC", "wmx.ulmap.feedback_polling.extended_2_uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_length, { "Length", "wmx.ulmap.feedback_polling.length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_num_allocation, { "Num_Allocation", "wmx.ulmap.feedback_polling.num_allocation", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_dedicated_ul_allocation_included, { "Dedicated UL Allocation included", "wmx.ulmap.feedback_polling.dedicated_ul_allocation_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_basic_cid, { "Basic CID", "wmx.ulmap.feedback_polling.basic_cid", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_allocation_duration, { "Allocation Duration (d)", "wmx.ulmap.feedback_polling.allocation_duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_type, { "Feedback type", "wmx.ulmap.feedback_polling.feedback_polling.type", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_frame_offset, { "Frame Offset", "wmx.ulmap.feedback_polling.frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_period, { "Period (p)", "wmx.ulmap.feedback_polling.perio", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_uiuc, { "UIUC", "wmx.ulmap.feedback_polling.uiuc", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_ofdma_symbol_offset, { "OFDMA Symbol Offset", "wmx.ulmap.feedback_polling.ofdma_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_subchannel_offset, { "Subchannel offset", "wmx.ulmap.feedback_polling.subchannel_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_duration, { "Duration", "wmx.ulmap.feedback_polling.duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_feedback_polling_repetition_coding_indication, { "Repetition coding indication", "wmx.ulmap.feedback_polling.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_aas_zone_configuration_included, { "AAS zone configuration included", "wmx.ulmap.reduced_aas.aas_zone_configuration_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_aas_zone_position_included, { "AAS zone position included", "wmx.ulmap.reduced_aas.aas_zone_position_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_ul_map_information_included, { "UL-MAP information included", "wmx.ulmap.reduced_aas.ul_map_information_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_phy_modification_included, { "PHY modification included", "wmx.ulmap.reduced_aas.phy_modification_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_power_control_included, { "Power Control included", "wmx.ulmap.reduced_aas.power_control_included", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_include_feedback_header, { "Include Feedback Header", "wmx.ulmap.reduced_aas.include_feedback_header", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_encoding_mode, { "Encoding Mode", "wmx.ulmap.reduced_aas.encoding_mode", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_permutation, { "Permutation", "wmx.ulmap.reduced_aas.permutation", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_ul_permbase, { "UL_PermBase", "wmx.ulmap.reduced_aas.ul_permbase", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_preamble_indication, { "Preamble Indication", "wmx.ulmap.reduced_aas.preamble_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_padding, { "Padding", "wmx.ulmap.reduced_aas.padding", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_zone_symbol_offset, { "Zone Symbol Offset", "wmx.ulmap.reduced_aas.zone_symbol_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_zone_length, { "Zone Length", "wmx.ulmap.reduced_aas.zone_length", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_ucd_count, { "UCD Count", "wmx.ulmap.reduced_aas.ucd_count", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_private_map_alloc_start_time, { "Private Map Allocation Start Time", "wmx.ulmap.reduced_aas.private_map_alloc_start_time", FT_UINT64, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_pilot_pattern_index, { "Pilot Pattern Index", "wmx.ulmap.reduced_aas.pilot_pattern_index", FT_UINT64, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_preamble_select, { "Preamble Select", "wmx.ulmap.reduced_aas.preamble_select", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_preamble_shift_index, { "Preamble Shift Index", "wmx.ulmap.reduced_aas.preamble_shift_index", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_pilot_pattern_modifier, { "Pilot Pattern Modifier", "wmx.ulmap.reduced_aas.pilot_pattern_modifier", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_power_control, { "Power Control", "wmx.ulmap.reduced_aas.power_control", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_ul_frame_offset, { "UL Frame Offset", "wmx.ulmap.reduced_aas.ul_frame_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_slot_offset, { "Slot Offset", "wmx.ulmap.reduced_aas.slot_offset", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_slot_duration, { "Slot Duration", "wmx.ulmap.reduced_aas.slot_duration", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_uiuc_nep, { "UIUC / N(EP)", "wmx.ulmap.reduced_aas.uiuc_nep", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_acid, { "ACID", "wmx.ulmap.reduced_aas.acid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_ai_sn, { "AI_SN", "wmx.ulmap.reduced_aas.ai_sn", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_nsch, { "N(SCH)", "wmx.ulmap.reduced_aas.nsch", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_spid, { "SPID", "wmx.ulmap.reduced_aas.spid", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + { &hf_ulmap_reduced_aas_repetition_coding_indication, { "Repetition Coding Indication", "wmx.ulmap.reduced_aas.repetition_coding_indication", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL }}, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_ulmap, + &ett_ulmap_ie, + &ett_ulmap_ffb, + /* &ett_ulmap_c, */ + /* &ett_ulmap_c_ie, */ + /* &ett_ulmap_s, */ + /* &ett_ulmap_s_ie, */ + &ett_287_1, + &ett_287_2, + &ett_289, + &ett_290, + &ett_290b, + &ett_291, + &ett_292, + &ett_293, + &ett_294, + &ett_295, + &ett_299, + &ett_300, + &ett_302, + &ett_302a, + &ett_302b, + &ett_302c, + &ett_302d, + &ett_302e, + &ett_302f, + &ett_302h, + &ett_302g, + &ett_302i, + &ett_302j, + &ett_302k, + &ett_302l, + &ett_302m, + &ett_302n, + &ett_302o, + &ett_302p, + &ett_302q, + &ett_302r, + &ett_302s, + &ett_302t, + &ett_302u, + &ett_302v, + &ett_306, + &ett_306_ul, + &ett_308b, + &ett_315d, + }; + + static ei_register_info ei[] = { + { &ei_ulmap_not_implemented, { "wmx.ulmap.not_implemented", PI_UNDECODED, PI_WARN, "Not implemented", EXPFILL }}, + }; + + expert_module_t* expert_mac_mgmt_msg_ulmap; + + proto_mac_mgmt_msg_ulmap_decoder = proto_register_protocol ( + "WiMax ULMAP Messages", /* name */ + "WiMax ULMAP", /* short name */ + "wmx.ulmap" /* abbrev */ + ); + + proto_register_field_array(proto_mac_mgmt_msg_ulmap_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_mac_mgmt_msg_ulmap = expert_register_protocol(proto_mac_mgmt_msg_ulmap_decoder); + expert_register_field_array(expert_mac_mgmt_msg_ulmap, ei, array_length(ei)); + ulmap_handle = register_dissector("mac_mgmt_msg_ulmap_handler", dissect_mac_mgmt_msg_ulmap_decoder, proto_mac_mgmt_msg_ulmap_decoder); +} + +void proto_reg_handoff_mac_mgmt_msg_ulmap(void) +{ + dissector_add_uint("wmx.mgmtmsg", MAC_MGMT_MSG_UL_MAP, ulmap_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: + */ diff --git a/plugins/epan/wimax/packet-m2m.c b/plugins/epan/wimax/packet-m2m.c new file mode 100644 index 00000000..bd08ebb1 --- /dev/null +++ b/plugins/epan/wimax/packet-m2m.c @@ -0,0 +1,809 @@ +/* packet-m2m.c + * Routines for WiMax MAC to MAC TLV packet disassembly + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include +#include +#include +#include "wimax_tlv.h" + +/* forward reference */ +void proto_reg_handoff_m2m(void); +void proto_register_m2m(void); +static void fch_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo); +static void cdma_code_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo); +static void pdu_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo, gint burst_number, gint frag_type, gint frag_number); +static void fast_feedback_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo); +static void harq_ack_bursts_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo); +static void physical_attributes_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo); +static void extended_tlv_decoder(packet_info *pinfo); +void proto_tree_add_tlv(tlv_info_t *self, tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, gint hf, guint encoding); + +/* Global variables */ +static dissector_handle_t m2m_handle; +static dissector_handle_t wimax_cdma_code_burst_handle; +static dissector_handle_t wimax_ffb_burst_handle; +static dissector_handle_t wimax_fch_burst_handle; +static dissector_handle_t wimax_hack_burst_handle; +static dissector_handle_t wimax_pdu_burst_handle; +static dissector_handle_t wimax_phy_attributes_burst_handle; + +static reassembly_table pdu_reassembly_table; + +static gint proto_m2m = -1; + +static gint ett_m2m = -1; +static gint ett_m2m_tlv = -1; +static gint ett_m2m_fch = -1; +static gint ett_m2m_cdma = -1; +static gint ett_m2m_ffb = -1; + +/* TLV types (rev:0.2) */ +#define TLV_PROTO_VER 1 +#define TLV_FRAME_NUM 2 +#define TLV_BURST_NUM 3 +#define TLV_FRAG_TYPE 4 +#define TLV_FRAG_NUM 5 +#define TLV_CDMA_CODE 7 +#define TLV_FCH_BURST 8 +#define TLV_PDU_BURST 9 +#define TLV_FAST_FB 10 +#define TLV_CRC16_STATUS 11 +#define TLV_BURST_POWER 12 +#define TLV_BURST_CINR 13 +#define TLV_PREAMBLE 14 +#define TLV_HARQ_ACK_BURST 15 +#define TLV_PHY_ATTRIBUTES 16 +#define TLV_EXTENDED_TLV 255 + +/* TLV names */ +static const value_string tlv_name[] = +{ + { TLV_PROTO_VER, "Protocol Version" }, + { TLV_FRAME_NUM, "Frame Number" }, + { TLV_BURST_NUM, "Burst Number" }, + { TLV_FRAG_TYPE, "Fragment Type" }, + { TLV_FRAG_NUM, "Fragment Number" }, + { TLV_CDMA_CODE, "CDMA Attribute" }, + { TLV_FCH_BURST, "FCH Burst" }, + { TLV_PDU_BURST, "PDU Burst" }, + { TLV_FAST_FB, "Fast Feedback Burst" }, + { TLV_CRC16_STATUS, "CRC16 Status" }, + { TLV_BURST_POWER, " Burst Power" }, + { TLV_BURST_CINR, "Burst CINR" }, + { TLV_PREAMBLE, "Preamble" }, + { TLV_HARQ_ACK_BURST, "HARQ ACK Bursts" }, + { TLV_PHY_ATTRIBUTES, "PDU Burst Physical Attributes" }, + { TLV_EXTENDED_TLV, "Extended TLV" }, + { 0, NULL } +}; + +/* TLV Fragment types */ +#define TLV_NO_FRAG 0 +#define TLV_FIRST_FRAG 1 +#define TLV_MIDDLE_FRAG 2 +#define TLV_LAST_FRAG 3 + +/* TLV Fragment Type names */ +static const value_string tlv_frag_type_name[] = +{ + { TLV_NO_FRAG, "No TLV Fragment" }, + { TLV_FIRST_FRAG, "First TLV Fragment" }, + { TLV_MIDDLE_FRAG, "Middle TLV Fragment" }, + { TLV_LAST_FRAG, "Last TLV Fragment" }, + { 0, NULL } +}; + +/* TLV CRC16 Status */ +static const value_string tlv_crc16_status[] = +{ + { 0, "No CRC-16 in burst" }, + { 1, "Good CRC-16 in burst" }, + { 2, "Bad CRC-16 in burst" }, + { 0, NULL } +}; + +static gint hf_m2m_sequence_number = -1; +static gint hf_m2m_frame_number = -1; +static gint hf_m2m_tlv_count = -1; + +static gint hf_m2m_type = -1; +static gint hf_m2m_len = -1; +static gint hf_m2m_len_size = -1; +/* static gint hf_m2m_value_bytes = -1; */ +static gint hf_wimax_invalid_tlv = -1; +static gint hf_m2m_value_protocol_vers_uint8 = -1; +static gint hf_m2m_value_burst_num_uint8 = -1; +static gint hf_m2m_value_frag_type_uint8 = -1; +static gint hf_m2m_value_frag_num_uint8 = -1; +static gint hf_m2m_value_pdu_burst = -1; +static gint hf_m2m_value_fast_fb = -1; +static gint hf_m2m_value_fch_burst_uint24 = -1; +static gint hf_m2m_value_cdma_code_uint24 = -1; +static gint hf_m2m_value_crc16_status_uint8 = -1; +static gint hf_m2m_value_burst_power_uint16 = -1; +static gint hf_m2m_value_burst_cinr_uint16 = -1; +static gint hf_m2m_value_preamble_uint16 = -1; +static gint hf_m2m_value_harq_ack_burst_bytes = -1; +static gint hf_m2m_phy_attributes = -1; + +static expert_field ei_m2m_unexpected_length = EI_INIT; + + +/* WiMax MAC to MAC protocol dissector */ +static int dissect_m2m(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_item *ti = NULL; + proto_item *m2m_item = NULL; + proto_tree *m2m_tree = NULL; + proto_tree *tlv_tree = NULL; + gint burst_number = 0; + gint length, offset = 0; + gint tlv_count; + gint tlv_type, tlv_len, tlv_offset, tlv_value; + gint tlv_frag_type = 0; + gint tlv_frag_number = 0; + tlv_info_t m2m_tlv_info; + gint hf; + guint encoding; + guint frame_number; + int expected_len; + + /* display the M2M protocol name */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "WiMax"); + + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo, COL_INFO); + + + { /* we are being asked for details */ + m2m_item = proto_tree_add_item(tree, proto_m2m, tvb, 0, -1, ENC_NA); + m2m_tree = proto_item_add_subtree(m2m_item, ett_m2m); + /* get the tvb reported length */ + length = tvb_reported_length(tvb); + /* add the size info */ + /* + proto_item_append_text(m2m_item, " (%u bytes) - Packet Sequence Number,Number of TLVs", length); + */ + proto_item_append_text(m2m_item, " (%u bytes)", length); + /* display the sequence number */ + proto_tree_add_item(m2m_tree, hf_m2m_sequence_number, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + /* display the TLV count */ + proto_tree_add_item(m2m_tree, hf_m2m_tlv_count, tvb, offset, 2, ENC_BIG_ENDIAN); + tlv_count = tvb_get_ntohs(tvb, offset); + offset += 2; + /* parses the TLVs within current packet */ + while ( tlv_count > 0) + { /* init MAC to MAC TLV information */ + init_tlv_info(&m2m_tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&m2m_tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&m2m_tlv_info); + if(tlv_type == -1 || tlv_len > 64000 || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "M2M TLV error"); + /* display the invalid TLV in HEX */ + proto_tree_add_item(m2m_tree, hf_wimax_invalid_tlv, tvb, offset, (length - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_offset = get_tlv_value_offset(&m2m_tlv_info); + /* display TLV type */ + ti = proto_tree_add_protocol_format(m2m_tree, proto_m2m, tvb, offset, (tlv_len + tlv_offset), "%s", + val_to_str_const(tlv_type, tlv_name, "Unknown TLV")); + /* add TLV subtree */ + tlv_tree = proto_item_add_subtree(ti, ett_m2m_tlv); + /* update the offset */ + offset += tlv_offset; + /* add the size info */ + /* decode TLV content (TLV value) */ + expected_len = 0; + hf = 0; + encoding = ENC_NA; + switch (tlv_type) + { + case TLV_PROTO_VER: + /* get the protocol version */ + tlv_value = tvb_get_guint8( tvb, offset ); + /* add the description */ + proto_item_append_text(ti, ": %d", tlv_value); + hf = hf_m2m_value_protocol_vers_uint8; + encoding = ENC_BIG_ENDIAN; + expected_len = 1; + break; + + case TLV_BURST_NUM: + /* get the burst number */ + burst_number = tvb_get_guint8( tvb, offset ); + /* add the description */ + proto_item_append_text(ti, ": %d", burst_number); + hf = hf_m2m_value_burst_num_uint8; + encoding = ENC_BIG_ENDIAN; + expected_len = 1; + break; + + case TLV_FRAG_TYPE: + /* add the description */ + tlv_frag_type = tvb_get_guint8( tvb, offset ); + proto_item_append_text(ti, ": %s", val_to_str_const(tlv_frag_type, tlv_frag_type_name, "Unknown")); + hf = hf_m2m_value_frag_type_uint8; + encoding = ENC_BIG_ENDIAN; + expected_len = 1; + break; + + case TLV_FRAG_NUM: + /* get the fragment number */ + tlv_frag_number = tvb_get_guint8( tvb, offset ); + /* add the description */ + proto_item_append_text(ti, ": %d", tlv_frag_number); + hf = hf_m2m_value_frag_num_uint8; + encoding = ENC_BIG_ENDIAN; + expected_len = 1; + break; + + case TLV_PDU_BURST: + /* display PDU Burst length info */ + proto_item_append_text(ti, " (%u bytes)", tlv_len); + /* decode and display the PDU Burst */ + pdu_burst_decoder(tree, tvb, offset, tlv_len, pinfo, burst_number, tlv_frag_type, tlv_frag_number); + hf = hf_m2m_value_pdu_burst; + encoding = ENC_NA; + break; + + case TLV_FAST_FB: + /* display the Fast Feedback Burst length info */ + proto_item_append_text(ti, " (%u bytes)", tlv_len); + /* decode and display the Fast Feedback Burst */ + fast_feedback_burst_decoder(tree, tvb, offset, tlv_len, pinfo); + hf = hf_m2m_value_fast_fb; + encoding = ENC_NA; + break; + + case TLV_FRAME_NUM: + /* get the frame number */ + frame_number = tvb_get_ntoh24( tvb, offset ); + /* add the description */ + proto_tree_add_item(tlv_tree, hf_m2m_frame_number, tvb, offset, 3, ENC_BIG_ENDIAN); + proto_item_append_text(ti, ": %d", frame_number); + break; + + case TLV_FCH_BURST: + /* add the description */ + tlv_value = tvb_get_ntoh24( tvb, offset ); + proto_item_append_text(ti, ": 0x%X", tlv_value); + /* decode and display the TLV FCH burst */ + fch_burst_decoder(tree, tvb, offset, tlv_len, pinfo); + hf = hf_m2m_value_fch_burst_uint24; + encoding = ENC_BIG_ENDIAN; + expected_len = 3; + break; + + case TLV_CDMA_CODE: + /* add the description */ + tlv_value = tvb_get_ntoh24( tvb, offset ); + proto_item_append_text(ti, ": 0x%X", tlv_value); + /* decode and display the CDMA Code */ + cdma_code_decoder(tree, tvb, offset, tlv_len, pinfo); + hf = hf_m2m_value_cdma_code_uint24; + encoding = ENC_BIG_ENDIAN; + expected_len = 3; + break; + + case TLV_CRC16_STATUS: + /* add the description */ + tlv_value = tvb_get_guint8( tvb, offset ); + proto_item_append_text(ti, ": %s", val_to_str_const(tlv_value, tlv_crc16_status, "Unknown")); + hf = hf_m2m_value_crc16_status_uint8; + encoding = ENC_BIG_ENDIAN; + expected_len = 1; + break; + + case TLV_BURST_POWER: + /* add the description */ + tlv_value = tvb_get_ntohs( tvb, offset ); + proto_item_append_text(ti, ": %d", tlv_value); + hf = hf_m2m_value_burst_power_uint16; + encoding = ENC_BIG_ENDIAN; + expected_len = 2; + break; + + case TLV_BURST_CINR: + /* add the description */ + tlv_value = tvb_get_ntohs( tvb, offset ); + proto_item_append_text(ti, ": 0x%X", tlv_value); + hf = hf_m2m_value_burst_cinr_uint16; + encoding = ENC_BIG_ENDIAN; + expected_len = 2; + break; + + case TLV_PREAMBLE: + /* add the description */ + tlv_value = tvb_get_ntohs( tvb, offset ); + proto_item_append_text(ti, ": 0x%X", tlv_value); + hf = hf_m2m_value_preamble_uint16; + encoding = ENC_BIG_ENDIAN; + expected_len = 2; + break; + + case TLV_HARQ_ACK_BURST: + /* display the Burst length info */ + proto_item_append_text(ti, " (%u bytes)", tlv_len); + /* decode and display the HARQ ACK Bursts */ + harq_ack_bursts_decoder(tree, tvb, offset, tlv_len, pinfo); + hf = hf_m2m_value_harq_ack_burst_bytes; + encoding = ENC_NA; + break; + + case TLV_PHY_ATTRIBUTES: + /* display the Burst length info */ + proto_item_append_text(ti, " (%u bytes)", tlv_len); + /* decode and display the PDU Burst Physical Attributes */ + physical_attributes_decoder(tree, tvb, offset, tlv_len, pinfo); + hf = hf_m2m_phy_attributes; + encoding = ENC_NA; + break; + + case TLV_EXTENDED_TLV: + /* display the Burst length info */ + proto_item_append_text(ti, " (%u bytes)", tlv_len); + /* decode and display the Extended TLV */ + extended_tlv_decoder(pinfo); + break; + + default: + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Unknown TLV Type"); + break; + } + /* expand the TLV detail */ + if (hf) { + if (offset - tlv_offset == expected_len) { + proto_tree_add_tlv(&m2m_tlv_info, tvb, offset - tlv_offset, pinfo, tlv_tree, hf, encoding); + } else { + expert_add_info_format(pinfo, NULL, &ei_m2m_unexpected_length, "Expected length %d, got %d.", expected_len, offset - tlv_offset); + } + } + offset += tlv_len; + /* update tlv_count */ + tlv_count--; + } + } + return tvb_captured_length(tvb); +} + +/* Decode and display the FCH burst */ +static void fch_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo) +{ + if(wimax_fch_burst_handle) + { /* call FCH dissector */ + call_dissector(wimax_fch_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree); + } + else /* display FCH info */ + { /* update the info column */ + col_append_str(pinfo->cinfo, COL_INFO, "FCH Burst: DL Frame Prefix"); + } +} + +/* Decode and display the CDMA Code Attribute */ +static void cdma_code_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo) +{ + if(wimax_cdma_code_burst_handle) + { /* call CDMA dissector */ + call_dissector(wimax_cdma_code_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree); + } + else /* display CDMA Code Attribute info */ + { /* update the info column */ + col_append_str(pinfo->cinfo, COL_INFO, "CDMA Code Attribute"); + } +} + +/* Decode and display the PDU Burst */ +static void pdu_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo, gint burst_number, gint frag_type, gint frag_number) +{ + fragment_head *pdu_frag; + tvbuff_t *pdu_tvb = NULL; + + /* update the info column */ + switch (frag_type) + { + case TLV_FIRST_FRAG: + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "First TLV Fragment (%d)", frag_number); + break; + case TLV_LAST_FRAG: + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Last TLV Fragment (%d)", frag_number); + break; + case TLV_MIDDLE_FRAG: + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Middle TLV Fragment %d", frag_number); + break; + } + if(frag_type == TLV_NO_FRAG) + { /* not fragmented PDU */ + pdu_tvb = tvb_new_subset_length(tvb, offset, length); + } + else /* fragmented PDU */ + { /* add the fragment */ + pdu_frag = fragment_add_seq(&pdu_reassembly_table, tvb, offset, pinfo, burst_number, NULL, frag_number - 1, length, ((frag_type==TLV_LAST_FRAG)?0:1), 0); + if(pdu_frag && frag_type == TLV_LAST_FRAG) + { + /* create the new tvb for defragmented frame */ + pdu_tvb = tvb_new_chain(tvb, pdu_frag->tvb_data); + /* add the defragmented data to the data source list */ + add_new_data_source(pinfo, pdu_tvb, "Reassembled WiMax PDU Frame"); + } + else + { + pdu_tvb = NULL; + if(frag_type == TLV_LAST_FRAG) + { /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Incomplete PDU frame"); + } + } + } + /* process the defragmented PDU burst */ + if(pdu_tvb) + { + if(wimax_pdu_burst_handle) + {/* decode and display PDU Burst */ + call_dissector(wimax_pdu_burst_handle, pdu_tvb, pinfo, tree); + } + else /* display PDU Burst info */ + { /* update the info column */ + col_append_str(pinfo->cinfo, COL_INFO, "PDU Burst"); + } + } +} + +/* Decode and display the Fast Feedback Burst */ +static void fast_feedback_burst_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo) +{ + if(wimax_ffb_burst_handle) + { /* display the TLV Fast Feedback Burst dissector info */ + call_dissector(wimax_ffb_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree); + } + else /* display the Fast Feedback Burst info */ + { /* update the info column */ + col_append_str(pinfo->cinfo, COL_INFO, "Fast Feedback Burst"); + } +} + +static void harq_ack_bursts_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo) +{ + if(wimax_hack_burst_handle) + { /* call the TLV HARQ ACK Bursts dissector */ + call_dissector(wimax_hack_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree); + } + else /* display the TLV HARQ ACK Bursts info */ + { /* update the info column */ + col_append_str(pinfo->cinfo, COL_INFO, "HARQ ACK Bursts"); + } +} + +static void physical_attributes_decoder(proto_tree *tree, tvbuff_t *tvb, gint offset, gint length, packet_info *pinfo) +{ + if(wimax_phy_attributes_burst_handle) + { /* call the TLV PDU Burst Physical Attributes dissector */ + call_dissector(wimax_phy_attributes_burst_handle, tvb_new_subset_length(tvb, offset, length), pinfo, tree); + } + else /* display the TLV PDU Burst Physical Attributes info */ + { /* update the info column */ + col_append_str(pinfo->cinfo, COL_INFO, "PHY-attr"); + } +} + +static void extended_tlv_decoder(packet_info *pinfo) +{ + /* display the Extended TLV info */ + /* update the info column */ + col_append_str(pinfo->cinfo, COL_INFO, "Extended TLV"); +} + +/* Display the raw WiMax TLV */ +void proto_tree_add_tlv(tlv_info_t *self, tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, gint hf, guint encoding) +{ + guint tlv_offset; + gint tlv_type, tlv_len; + + /* make sure the TLV information is valid */ + if(!self->valid) + { /* invalid TLV info */ + col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "Invalid TLV"); + return; + } + tlv_offset = offset; + /* display TLV type */ + proto_tree_add_item(tree, hf_m2m_type, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + tlv_offset++; + /* check the TLV length type */ + if( self->length_type ) + { /* multiple bytes TLV length */ + /* display the length of the TLV length with MSB */ + proto_tree_add_item(tree, hf_m2m_len_size, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + tlv_offset++; + if(self->size_of_length) + /* display the multiple byte TLV length */ + proto_tree_add_item(tree, hf_m2m_len, tvb, tlv_offset, self->size_of_length, ENC_BIG_ENDIAN); + else + return; + } + else /* display the single byte TLV length */ + proto_tree_add_item(tree, hf_m2m_len, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + + tlv_type = get_tlv_type(self); + /* Display Frame Number as special case for filter */ + if ( tlv_type == TLV_FRAME_NUM ) + { + return; + } + + /* get the TLV length */ + tlv_len = get_tlv_length(self); + proto_tree_add_item(tree, hf, tvb, (offset + self->value_offset), tlv_len, encoding); +} + +/* Register Wimax Mac to Mac Protocol */ +void proto_register_m2m(void) +{ + /* M2M TLV display */ + static hf_register_info hf[] = + { + { + &hf_m2m_sequence_number, + { + "Packet Sequence Number", "m2m.seq_number", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_frame_number, + { + "Value", "m2m.frame_number", + FT_UINT24, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_tlv_count, + { + "Number of TLVs in the packet", "m2m.tlv_count", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + } + }; + + /* WiMax TLV display */ + static hf_register_info hf_tlv[] = + { + { + &hf_m2m_type, + { + "Type", "m2m.tlv_type", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_len, + { + "Length", "m2m.tlv_len", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_len_size, + { + "Length Size", "m2m.tlv_len_size", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, +#if 0 + { + &hf_m2m_value_bytes, + { + "Value (hex)", "m2m.multibyte_tlv_value", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, +#endif + { + &hf_m2m_value_protocol_vers_uint8, + { + "Value", "m2m.protocol_vers_tlv_value", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_burst_num_uint8, + { + "Value", "m2m.burst_num_tlv_value", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_frag_type_uint8, + { + "Value", "m2m.frag_type_tlv_value", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_frag_num_uint8, + { + "Value", "m2m.frag_num_tlv_value", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_pdu_burst, + { + "Value (hex)", "m2m.pdu_burst_tlv_value", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_fast_fb, + { + "Value (hex)", "m2m.fast_fb_tlv_value", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_fch_burst_uint24, + { + "Value", "m2m.fch_burst_tlv_value", + FT_UINT24, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_cdma_code_uint24, + { + "Value", "m2m.cdma_code_tlv_value", + FT_UINT24, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_crc16_status_uint8, + { + "Value", "m2m.crc16_status_tlv_value", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_burst_power_uint16, + { + "Value", "m2m.burst_power_tlv_value", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_burst_cinr_uint16, + { + "Value", "m2m.burst_cinr_tlv_value", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_preamble_uint16, + { + "Value", "m2m.preamble_tlv_value", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_value_harq_ack_burst_bytes, + { + "Value (hex)", "m2m.harq_ack_burst_tlv_value", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_m2m_phy_attributes, + { + "Value (hex)", "m2m.phy_attributes", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_wimax_invalid_tlv, + { + "Invalid TLV (hex)", "m2m.invalid_tlv", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + } + }; + + static gint *ett[] = + { + &ett_m2m, + &ett_m2m_tlv, + &ett_m2m_fch, + &ett_m2m_cdma, + &ett_m2m_ffb, + }; + + static ei_register_info ei[] = { + { &ei_m2m_unexpected_length, { "m2m.unexpected_length", PI_MALFORMED, PI_ERROR, "Unexpected length", EXPFILL }}, + }; + + expert_module_t* expert_m2m; + + proto_m2m = proto_register_protocol ( + "WiMax Mac to Mac Packet", /* name */ + "M2M (m2m)", /* short name */ + "m2m" /* abbrev */ + ); + + proto_register_field_array(proto_m2m, hf, array_length(hf)); + proto_register_field_array(proto_m2m, hf_tlv, array_length(hf_tlv)); + proto_register_subtree_array(ett, array_length(ett)); + expert_m2m = expert_register_protocol(proto_m2m); + expert_register_field_array(expert_m2m, ei, array_length(ei)); + m2m_handle = register_dissector("mac_mgmt_msg_m2m_handler", dissect_m2m, proto_m2m); + + /* Register reassembly table */ + reassembly_table_register(&pdu_reassembly_table, + &addresses_reassembly_table_functions); +} + +/* Register Wimax Mac to Mac Protocol handler */ +void proto_reg_handoff_m2m(void) +{ + dissector_add_uint("ethertype", ETHERTYPE_WMX_M2M, m2m_handle); + + /* find the wimax handlers */ + wimax_cdma_code_burst_handle = find_dissector("wimax_cdma_code_burst_handler"); + wimax_fch_burst_handle = find_dissector("wimax_fch_burst_handler"); + wimax_ffb_burst_handle = find_dissector("wimax_ffb_burst_handler"); + wimax_hack_burst_handle = find_dissector("wimax_hack_burst_handler"); + wimax_pdu_burst_handle = find_dissector("wimax_pdu_burst_handler"); + wimax_phy_attributes_burst_handle = find_dissector("wimax_phy_attributes_burst_handler"); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/packet-wmx.c b/plugins/epan/wimax/packet-wmx.c new file mode 100644 index 00000000..5a38b111 --- /dev/null +++ b/plugins/epan/wimax/packet-wmx.c @@ -0,0 +1,366 @@ +/* packet-wmx.c + * WiMax Protocol and dissectors + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include + +#include +#include +#include "wimax-int.h" +#include "wimax_tlv.h" +#include "wimax_utils.h" + +void proto_register_wimax(void); +void proto_reg_handoff_wimax(void); + +/* Global variables */ +gint proto_wimax = -1; +gint8 arq_enabled = 0; +gint scheduling_service_type = 0; +gint mac_sdu_length = 49; /* default SDU size is 49 bytes (11.13.16) */ +extern guint global_cid_max_basic; +extern gboolean include_cor2_changes; + +address bs_address = ADDRESS_INIT_NONE; + + +static int hf_tlv_type = -1; +static int hf_tlv_length = -1; +static int hf_tlv_length_size = -1; + +#define MAX_NUM_TLVS 256 +/* Global TLV array to retrieve unique subtree identifiers */ +static gint ett_tlv[MAX_NUM_TLVS]; + +static const gchar tlv_val_1byte[] = "TLV value: %s (0x%02x)"; +static const gchar tlv_val_2byte[] = "TLV value: %s (0x%04x)"; +static const gchar tlv_val_3byte[] = "TLV value: %s (0x%06x)"; +static const gchar tlv_val_4byte[] = "TLV value: %s (0x%08x)"; +static const gchar tlv_val_5byte[] = "TLV value: %s (0x%08x...)"; + +/*************************************************************/ +/* add_tlv_subtree() */ +/* Return a pointer to a proto_item of a TLV value that */ +/* already contains the type and length of the given TLV. */ +/* tree - the parent to which the new tree will */ +/* be attached */ +/* hfindex - the index of the item to be attached */ +/* tvb - a pointer to the packet data */ +/* start - offset within the packet */ +/* length - length of this item */ +/* encoding - encoding for proto_tree_add_item */ +/* return: */ +/* pointer to a proto_item */ +/*************************************************************/ +proto_item *add_tlv_subtree(tlv_info_t *self, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, const guint encoding) +{ + header_field_info *hf; + proto_tree *tlv_tree; + proto_item *tlv_item; + gint tlv_value_length, tlv_val_offset; + guint8 size_of_tlv_length_field; + guint8 tlv_type; + + /* Make sure we're dealing with a valid TLV here */ + if (get_tlv_type(self) < 0) + return tree; + + /* Retrieve the necessary TLV information */ + tlv_val_offset = get_tlv_value_offset(self); + tlv_value_length = get_tlv_length(self); + size_of_tlv_length_field = get_tlv_size_of_length(self); + tlv_type = get_tlv_type(self); + + hf = proto_registrar_get_nth(hfindex); + + tlv_tree = proto_tree_add_subtree(tree, tvb, start, tlv_value_length+tlv_val_offset, ett_tlv[tlv_type], NULL, hf->name); + + proto_tree_add_uint(tlv_tree, hf_tlv_type, tvb, start, 1, tlv_type); + if (size_of_tlv_length_field > 0) /* It is */ + { + /* display the length of the length field TLV */ + proto_tree_add_uint(tlv_tree, hf_tlv_length_size, tvb, start+1, 1, size_of_tlv_length_field); + /* display the TLV length */ + proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+2, size_of_tlv_length_field, tlv_value_length); + } else { /* It is not */ + /* display the TLV length */ + proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+1, 1, tlv_value_length); + } + + tlv_item = proto_tree_add_item(tlv_tree, hfindex, tvb, start+tlv_val_offset, tlv_value_length, encoding); + + /* Return a pointer to the value level */ + return tlv_item; +} + +/*************************************************************/ +/* add_tlv_subtree_no_item() */ +/* Return a pointer to a proto_tree of a TLV value that */ +/* already contains the type and length, but no value */ +/* tree - the parent to which the new tree will */ +/* be attached */ +/* hfindex - the index of the item to be attached */ +/* tvb - a pointer to the packet data */ +/* start - offset within the packet */ +/* length - length of this item */ +/* return: */ +/* pointer to a proto_tree (to then add value) */ +/*************************************************************/ +proto_tree *add_tlv_subtree_no_item(tlv_info_t *self, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start) +{ + header_field_info *hf; + proto_tree *tlv_tree; + gint tlv_value_length, tlv_val_offset; + guint8 size_of_tlv_length_field; + guint8 tlv_type; + + /* Make sure we're dealing with a valid TLV here */ + if (get_tlv_type(self) < 0) + return tree; + + /* Retrieve the necessary TLV information */ + tlv_val_offset = get_tlv_value_offset(self); + tlv_value_length = get_tlv_length(self); + size_of_tlv_length_field = get_tlv_size_of_length(self); + tlv_type = get_tlv_type(self); + + hf = proto_registrar_get_nth(hfindex); + + tlv_tree = proto_tree_add_subtree(tree, tvb, start, tlv_value_length+tlv_val_offset, ett_tlv[tlv_type], NULL, hf->name); + + proto_tree_add_uint(tlv_tree, hf_tlv_type, tvb, start, 1, tlv_type); + if (size_of_tlv_length_field > 0) /* It is */ + { + /* display the length of the length field TLV */ + proto_tree_add_uint(tlv_tree, hf_tlv_length_size, tvb, start+1, 1, size_of_tlv_length_field); + /* display the TLV length */ + proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+2, size_of_tlv_length_field, tlv_value_length); + } else { /* It is not */ + /* display the TLV length */ + proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+1, 1, tlv_value_length); + } + + /* Return a pointer to the tree level (to manually add item) */ + return tlv_tree; +} + +/*************************************************************/ +/* add_protocol_subtree() */ +/* Return a pointer to a proto_tree that already contains */ +/* the type and length of a given TLV. */ +/* tree - the parent to which the new tree will */ +/* be attached */ +/* hfindex - the index of the item to be attached */ +/* tvb - a pointer to the packet data */ +/* start - offset within the packet */ +/* length - length of this item */ +/* format - printf style formatting string */ +/* ... - arguments to format */ +/* return: */ +/* pointer to a proto_tree */ +/*************************************************************/ +proto_tree *add_protocol_subtree(tlv_info_t *self, gint idx, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length _U_, const char *label) +{ + /* Declare local variables */ + proto_tree *tlv_tree; + proto_item *tlv_item; + gint tlv_value_length, tlv_val_offset; + guint8 size_of_tlv_length_field; + guint8 tlv_type; + guint32 tlv_value; + const gchar *hex_fmt; + + /* Make sure we're dealing with a valid TLV here */ + if (get_tlv_type(self) < 0) + return tree; + + /* Retrieve the necessary TLV information */ + tlv_val_offset = get_tlv_value_offset(self); + tlv_value_length = get_tlv_length(self); + size_of_tlv_length_field = get_tlv_size_of_length(self); + tlv_type = get_tlv_type(self); + + /* display the TLV name and display the value in hex. Highlight type, length, and value. */ + tlv_item = proto_tree_add_protocol_format(tree, hfindex, tvb, start, tlv_value_length+tlv_val_offset, "%s (%u byte(s))", label, tlv_value_length); + tlv_tree = proto_item_add_subtree(tlv_item, ett_tlv[tlv_type]); + + proto_tree_add_uint(tlv_tree, hf_tlv_type, tvb, start, 1, tlv_type); + if (size_of_tlv_length_field > 0) /* It is */ + { + /* display the length of the length field TLV */ + proto_tree_add_uint(tlv_tree, hf_tlv_length_size, tvb, start+1, 1, size_of_tlv_length_field); + /* display the TLV length */ + proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+2, size_of_tlv_length_field, tlv_value_length); + } else { /* It is not */ + /* display the TLV length */ + proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+1, 1, tlv_value_length); + } + + /* display the TLV value and make it a subtree */ + switch (tlv_value_length) + { + case 1: + tlv_value = tvb_get_guint8(tvb, start+tlv_val_offset); + hex_fmt = tlv_val_1byte; + break; + case 2: + tlv_value = tvb_get_ntohs(tvb, start+tlv_val_offset); + hex_fmt = tlv_val_2byte; + break; + case 3: + tlv_value = tvb_get_ntoh24(tvb, start+tlv_val_offset); + hex_fmt = tlv_val_3byte; + break; + case 4: + tlv_value = tvb_get_ntohl(tvb, start+tlv_val_offset); + hex_fmt = tlv_val_4byte; + break; + default: + tlv_value = tvb_get_ntohl(tvb, start+tlv_val_offset); + hex_fmt = tlv_val_5byte; + break; + } + /* Show "TLV value: " */ + tlv_tree = proto_tree_add_subtree_format(tlv_tree, tvb, start+tlv_val_offset, tlv_value_length, idx, NULL, hex_fmt, label, tlv_value); + + /* Return a pointer to the value level */ + return tlv_tree; +} + + + +/* WiMax protocol dissector */ +static int dissect_wimax(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_, void* data _U_) +{ + /* display the WiMax protocol name */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "WiMax"); + /* Clear out stuff in the info column */ + col_clear(pinfo->cinfo, COL_INFO); + + return tvb_captured_length(tvb); +} + +gboolean is_down_link(packet_info *pinfo) +{ + if (pinfo->p2p_dir == P2P_DIR_RECV) + return TRUE; + if (pinfo->p2p_dir == P2P_DIR_UNKNOWN) + if(bs_address.len && !cmp_address(&bs_address, &pinfo->src)) + return TRUE; + return FALSE; +} + + +/* Register Wimax Protocol */ +void proto_register_wimax(void) +{ + int i; + module_t *wimax_module; + + static hf_register_info hf[] = { + { &hf_tlv_type, { "TLV type", "wmx.tlv_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_tlv_length, { "TLV length", "wmx.tlv_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_tlv_length_size, { "Size of TLV length field", "wmx.tlv_length_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + }; + + gint *ett_reg[MAX_NUM_TLVS]; + + /* Register the WiMax protocols here */ + proto_wimax = proto_register_protocol ( + "WiMax Protocol", /* name */ + "WiMax (wmx)", /* short name */ + "wmx" /* abbrev */ + ); + + proto_register_field_array(proto_wimax, hf, array_length(hf)); + + /* Register the ett TLV array to retrieve unique subtree identifiers */ + for (i = 0; i < MAX_NUM_TLVS; i++) + { + ett_tlv[i] = -1; + ett_reg[i] = &ett_tlv[i]; + } + + proto_register_subtree_array(ett_reg, array_length(ett_reg)); + + /* Register the WiMax dissector */ + register_dissector("wmx", dissect_wimax, proto_wimax); + + wimax_module = prefs_register_protocol(proto_wimax, NULL); + + prefs_register_uint_preference(wimax_module, "basic_cid_max", + "Maximum Basic CID", + "Set the maximum Basic CID" + " used in the Wimax decoder" + " (if other than the default of 320)." + " Note: The maximum Primary CID is" + " double the maximum Basic CID.", + 10, &global_cid_max_basic); + + prefs_register_bool_preference(wimax_module, "corrigendum_2_version", + "Corrigendum 2 Version", + "Set to TRUE to use the Corrigendum" + " 2 version of Wimax message decoding." + " Set to FALSE to use the 802.16e-2005" + " version.", + &include_cor2_changes); + prefs_register_obsolete_preference(wimax_module, "wimax.basic_cid_max"); + prefs_register_obsolete_preference(wimax_module, "wimax.corrigendum_2_version"); + + /* + * Call sub-registrations in the correct order because they depend + * on proto_register_wimax() being run first. + */ + wimax_proto_register_wimax_cdma(); + wimax_proto_register_wimax_compact_dlmap_ie(); + wimax_proto_register_wimax_compact_ulmap_ie(); + wimax_proto_register_wimax_fch(); + wimax_proto_register_wimax_ffb(); + wimax_proto_register_wimax_hack(); + wimax_proto_register_wimax_harq_map(); + wimax_proto_register_wimax_pdu(); + wimax_proto_register_wimax_phy_attributes(); + wimax_proto_register_wimax_utility_decoders(); + wimax_proto_register_mac_header_generic(); + wimax_proto_register_mac_header_type_1(); + wimax_proto_register_mac_header_type_2(); +} + +/* + * If we're going to give the register routines for the above files special + * names to ensure that they're called in the above order in the above + * routine, we have to do the same with their handoff routines, if they + * have any - that's the way the registration generation stuff now works. + */ +void proto_reg_handoff_wimax(void) +{ + wimax_proto_reg_handoff_wimax_pdu(); + wimax_proto_reg_handoff_mac_header_generic(); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax-int.h b/plugins/epan/wimax/wimax-int.h new file mode 100644 index 00000000..eff30418 --- /dev/null +++ b/plugins/epan/wimax/wimax-int.h @@ -0,0 +1,30 @@ +/* wimax-int.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __WIMAX_INT_H__ +#define __WIMAX_INT_H__ + +void wimax_proto_register_wimax_cdma(void); +void wimax_proto_register_wimax_compact_dlmap_ie(void); +void wimax_proto_register_wimax_compact_ulmap_ie(void); +void wimax_proto_register_wimax_fch(void); +void wimax_proto_register_wimax_ffb(void); +void wimax_proto_register_wimax_hack(void); +void wimax_proto_register_wimax_harq_map(void); +void wimax_proto_register_wimax_pdu(void); +void wimax_proto_register_wimax_phy_attributes(void); +void wimax_proto_register_wimax_utility_decoders(void); +void wimax_proto_register_mac_header_generic(void); +void wimax_proto_register_mac_header_type_1(void); +void wimax_proto_register_mac_header_type_2(void); + +void wimax_proto_reg_handoff_wimax_pdu(void); +void wimax_proto_reg_handoff_mac_header_generic(void); + +#endif diff --git a/plugins/epan/wimax/wimax_bits.h b/plugins/epan/wimax/wimax_bits.h new file mode 100644 index 00000000..f844d549 --- /dev/null +++ b/plugins/epan/wimax/wimax_bits.h @@ -0,0 +1,194 @@ +/* wimax_bits.h + * WiMax MAC Management UL-MAP Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Mike Harvey + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __wimax_bits_h__ +#define __wimax_bits_h__ + +#include + +/******************************************************************** + * Functions for working with nibbles and bits + */ + +/* SWAR functions */ +#define _BITS(n,hi,lo) (((n)>>(lo))&((1<<(((hi)-(lo))+1))-1)) +#define _ADD_SWAP(x,y) { (x) = (x) + (y); (y) = (x) - (y); (x) = (x) - (y); } +#define _XOR_SWAP(x,y) { (x) ^= (y); (y) ^= (x); (x) ^= (y); } +#define _SWAP(x,y) do { int t = (x); (x) = (y); (y) = t; } while(0) + + +/******************************************************************** + * Functions for working with nibbles + * + */ + +#define NIBBLE_MASK 0x0F +#define BYTE_MASK 0xFF + +/* extract the nibble at the given nibble address 'n' of tvbuff_t 't' */ +#define TVB_NIB_NIBBLE(n,t) \ + (((n) & 1) \ + ? tvb_get_guint8((t), (n)/2) & NIBBLE_MASK \ + : (tvb_get_guint8((t), (n)/2) >> 4) & NIBBLE_MASK) + +/* extract the byte at the given nibble address 'n' of tvbuff_t 't' */ +#define TVB_NIB_BYTE(n,t) \ + (n) & 1 \ + ? (tvb_get_ntohs((t), (n)/2) >> 4) & BYTE_MASK \ + : tvb_get_guint8((t), (n)/2) + +/* extract 12 bits at the given nibble address */ +#define TVB_NIB_BITS12(n,t) \ + (TVB_NIB_NIBBLE(n+2,t) | (TVB_NIB_BYTE(n,t) << 4)) + +/* extract the word at the given nibble address 'n' of tvbuff_t 't' */ +#define TVB_NIB_WORD(n,t) \ + (n) & 1 \ + ? (gint)((tvb_get_ntohl((t), (n)/2) >> 12) & 0x0000FFFF) \ + : tvb_get_ntohs((t), (n)/2) + +/* extract the word at the given nibble address 'n' of tvbuff_t 't' */ +#define TVB_NIB_LONG(n,t) \ + (n) & 1 \ + ? (tvb_get_ntohl((t), (n)/2) << 4) | ((tvb_get_guint8((t), (n)/2 + 4) >> 4) & NIBBLE_MASK) \ + : tvb_get_ntohl((t), (n)/2) + +/* Only currently used with nib == 1 or 2 */ +#define TVB_NIB_NIBS(nib, t, num) \ + ((num) == 1 ? TVB_NIB_NIBBLE(nib,t) : \ + ((num) == 2 ? TVB_NIB_BYTE(nib,t) : \ + ((num) == 3 ? TVB_NIB_BITS12(nib,t) : \ + ((num) == 4 ? TVB_NIB_WORD(nib,t) : \ + 0)))) + +/* to highlight nibfields correctly in wireshark + * AddItem(..., WSADDR(buf,bit), WSLEN(bit), ...) */ + +/* determine starting byte to highlight a series of nibbles */ +#define NIB_ADDR(nib) ((nib)/2) +/* determine number of bytes to highlight a series of nibbles */ +#define NIB_LEN(nib,len) ((1 + ((nib) &1) + (len))/2) + +#define NIBHI(nib,len) NIB_ADDR(nib),NIB_LEN(nib,len) + +/******************************************************************** + * bitfield functions - for extracting bitfields from a buffer + * + * TODO: 64 bit functions use two 32-bit values; + * would be better to use 32+8 bits to avoid overrunning buffers + * + */ + +/* find the byte-address for the bitfield */ +#define ADDR(bit) ((bit) / 8) +#define ADDR16(bit) ((bit) / 8) +#define ADDR32(bit) ((bit) / 8) + +/* find the offset (from the MSB) to the start of the bitfield */ +#define OFFSET(bit) ((bit) % 8) +#define OFFSET16(bit) ((bit) % 8) +#define OFFSET32(bit) ((bit) % 8) + +/* find the number of bits to shift right (SHIFT64 is upper dword) */ +#define SHIFT(bit,num) ( 8 - ((bit)%8) - (num)) +#define SHIFT16(bit,num) (16 - ((bit)%8) - (num)) +#define SHIFT32(bit,num) (32 - ((bit)%8) - (num)) +#define SHIFT64a(bit,num) (num - (32 - OFFSET32(bit))) +#define SHIFT64b(bit,num) (32 - ((num) - (32 - OFFSET32(bit)))) + +/* create a mask to mask off the bitfield */ +#define MASK8(num) (0xFF >> (8 - (num))) +#define MASK16(num) (0xFFFF >> (16 - (num))) +#define MASK32(num) (0xFFFFFFFF >> (32 - (num))) +#define MASK64a(bit) (MASK32(32 - OFFSET32(bit))) +#define MASK64b(bit,num) (MASK32(num - (32 - OFFSET32(bit)))) + +/* note that if you have a bitfield of length 2 or more, it may cross a + * byte boundary so you should use TVB_BIT_BITS16 */ + +/* extract a single bit + * bit ... bit address + * tvb ... tvbuff_t + */ +#define TVB_BIT_BIT(bit, tvb) \ + (( tvb_get_guint8(tvb, ADDR(bit)) >> SHIFT(bit,1) ) & 0x1) + +/* extract bitfield up to 9 bits + * bit ... bit address + * tvb ... tvbuff_t + * num ... length of bitfield + */ +#define TVB_BIT_BITS16(bit, tvb, num) \ + (( tvb_get_ntohs(tvb, ADDR16(bit)) >> SHIFT16(bit,num) ) & MASK16(num)) + +/* extract bitfield up to 24 bits + * bit ... bit address + * tvb ... tvbuff_t + * num ... length of bitfield + */ + +#define TVB_BIT_BITS32(bit, tvb, num) \ + ((tvb_get_ntohl(tvb, ADDR32(bit)) >> SHIFT32(bit,num) ) & MASK32(num)) + +/* bitfield up to 32 bits */ +#define TVB_BIT_BITS64a(bit, tvb, num) \ + ((tvb_get_ntohl(tvb, ADDR32(bit)) & MASK64a(bit)) << SHIFT64a(bit,num)) + +#define TVB_BIT_BITS64b(bit, tvb, num) \ + ((tvb_get_ntohl(tvb, ADDR32(bit)+4) >> SHIFT64b(bit,num) ) & MASK64b(bit,num)) + +#define TVB_BIT_BITS64(bit, tvb, num) \ + ( (OFFSET32(bit)+(num)) <= 32 \ + ? TVB_BIT_BITS32(bit,tvb,num) \ + : TVB_BIT_BITS64a(bit,tvb,num) \ + | TVB_BIT_BITS64b(bit,tvb,num) ) + +#define TVB_BIT_BITS(bit, tvb, num) \ + ((num) == 1 ? (gint)TVB_BIT_BIT(bit,tvb) : \ + ((num) <= 9 ? (gint)TVB_BIT_BITS16(bit,tvb,num) : \ + ((num) <= 24 ? (gint)TVB_BIT_BITS32(bit,tvb,num) : \ + ((num) <= 32 ? (gint)TVB_BIT_BITS64(bit,tvb,num) : \ + (gint)0 )))) + +/* to highlight bitfields correctly in wireshark + * AddItem(..., WSADDR(buf,bit), WSLEN(bit), ...) */ + +/* determine starting byte to highlight a series of nibbles */ +#define BIT_ADDR(bit) (ADDR(bit)) +/* determine number of bytes to highlight */ +#define BIT_LEN(bit,len) (1 + ((OFFSET(bit) + len - 1) / 8)) + +#define BITHI(bit,len) BIT_ADDR(bit),BIT_LEN(bit,len) + +/******************************************************************** + * padding functions - return number of nibbles/bits needed to + * pad to a byte boundary */ + +#define BIT_PADDING(bit, bits) ((bit) % (bits)) ? ((bits) - ((bit) % (bits))) : 0 +#define NIB_PADDING(nib) ((nib) & 0x1) + +/******************************************************************** + * conversion functions - between bytes, nibbles, and bits */ + +#define BYTE_TO_BIT(n) ((n) * 8) +#define BYTE_TO_NIB(n) ((n) * 2) + +#define BIT_TO_BYTE(n) ((n) / 8) +#define BIT_TO_NIB(n) ((n) / 4) + +#define NIB_TO_BYTE(n) ((n) / 2) +#define NIB_TO_BIT(n) ((n) * 4) + +#endif + diff --git a/plugins/epan/wimax/wimax_cdma_code_decoder.c b/plugins/epan/wimax/wimax_cdma_code_decoder.c new file mode 100644 index 00000000..65b52109 --- /dev/null +++ b/plugins/epan/wimax/wimax_cdma_code_decoder.c @@ -0,0 +1,116 @@ +/* wimax_cdma_code_decoder.c + * WiMax CDMA CODE Attribute decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax-int.h" + +static int proto_wimax_cdma_code_decoder = -1; +static gint ett_wimax_cdma_code_decoder = -1; + +static int hf_wimax_ranging_code = -1; +static int hf_wimax_ranging_symbol_offset = -1; +static int hf_wimax_ranging_subchannel_offset = -1; + +static int dissect_wimax_cdma_code_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + gint offset = 0; + proto_item *cdma_item; + proto_tree *cdma_tree; + + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "CDMA Code Attribute"); + if (tree) + { /* we are being asked for details */ + /* display CDMA dissector info */ + cdma_item = proto_tree_add_item(tree, proto_wimax_cdma_code_decoder, tvb, offset, -1, ENC_NA); + /* add CDMA Code subtree */ + cdma_tree = proto_item_add_subtree(cdma_item, ett_wimax_cdma_code_decoder); + /* display the first CDMA Code */ + proto_tree_add_item(cdma_tree, hf_wimax_ranging_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the 2nd CDMA Code */ + proto_tree_add_item(cdma_tree, hf_wimax_ranging_symbol_offset, tvb, offset+1, 1, ENC_BIG_ENDIAN); + /* display the 3rd CDMA Code */ + proto_tree_add_item(cdma_tree, hf_wimax_ranging_subchannel_offset, tvb, offset+2, 1, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax CDMA Protocol */ +void wimax_proto_register_wimax_cdma(void) +{ + /* TLV display */ + static hf_register_info hf[] = + { + { + &hf_wimax_ranging_code, + { + "Ranging Code", "wmx.cdma.ranging_code", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_wimax_ranging_symbol_offset, + { + "Ranging Symbol Offset", "wmx.cdma.ranging_symbol_offset", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_wimax_ranging_subchannel_offset, + { + "Ranging Sub-Channel Offset", "wmx.cdma.ranging_subchannel_offset", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_wimax_cdma_code_decoder, + }; + + proto_wimax_cdma_code_decoder = proto_register_protocol ( + "WiMax CDMA Code Attribute", /* name */ + "CDMA Code Attribute", /* short name */ + "wmx.cdma" /* abbrev */ + ); + + /* register the field display messages */ + proto_register_field_array(proto_wimax_cdma_code_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("wimax_cdma_code_burst_handler", dissect_wimax_cdma_code_decoder, proto_wimax_cdma_code_decoder); +} + + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_compact_dlmap_ie_decoder.c b/plugins/epan/wimax/wimax_compact_dlmap_ie_decoder.c new file mode 100644 index 00000000..c69bd687 --- /dev/null +++ b/plugins/epan/wimax/wimax_compact_dlmap_ie_decoder.c @@ -0,0 +1,2111 @@ +/* wimax_compact_dlmap_ie_decoder.c + * WiMax HARQ Map Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax-int.h" +#include "wimax_compact_dlmap_ie_decoder.h" + +extern gint proto_wimax; + +/* MASKs */ +#define MSB_NIBBLE_MASK 0xF0 +#define LSB_NIBBLE_MASK 0x0F + +#define CID_TYPE_NORMAL 0 +#define CID_TYPE_RCID11 1 +#define CID_TYPE_RCID7 2 +#define CID_TYPE_RCID3 3 + +/* Global Variables */ +guint cid_type = 0; +guint band_amc_subchannel_type = 0; +guint max_logical_bands = 12; +guint num_of_broadcast_symbols = 0; +guint num_of_dl_band_amc_symbols = 0; +guint num_of_ul_band_amc_symbols = 0; +/* from switch HARQ mode extension IE */ +guint harq_mode = 0; + +/* forward reference */ +static guint wimax_compact_dlmap_format_configuration_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +static guint wimax_compact_dlmap_rcid_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +static guint wimax_compact_dlmap_harq_control_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +static guint wimax_compact_dlmap_cqich_control_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +static guint wimax_cdlmap_extension_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +guint wimax_extended_diuc_dependent_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); + +static gint proto_wimax_compact_dlmap_ie_decoder = -1; + +#if 0 /* not used ?? */ +static gint ett_wimax_compact_dlmap_ie_decoder = -1; +static gint ett_wimax_format_configuration_ie_decoder = -1; +static gint ett_wimax_rcid_ie_decoder = -1; +static gint ett_wimax_harq_control_ie_decoder = -1; +static gint ett_wimax_extended_diuc_dependent_ie_decoder = -1; +static gint ett_wimax_cqich_control_ie_decoder = -1; +static gint ett_wimax_extension_type_ie_decoder = -1; +#endif + +/* New Format Indications */ +static const true_false_string tfs_indication = +{ + "New format", + "No new format" +}; + +/* Prefixes */ +static const true_false_string tfs_prefix = +{ + "Enable HARQ", + "Temporary Disable HARQ" +}; + +/* CQICH Indicator */ +static const true_false_string tfs_cqich_ind = +{ + "With CQICH Control IE", + "No CQICH Control IE" +}; + +/* CID types */ +static const value_string vals_cid_types[] = +{ + { 0, "Normal CID" }, + { 1, "RCID11 (default)" }, + { 2, "RCID7" }, + { 3, "RCID3" }, + { 0, NULL } +}; + +/* Subchannel Types */ +static const value_string vals_subchannel_types[] = +{ + { 0, "Default Type" }, + { 1, "1 bin x 6 symbols Type" }, + { 2, "2 bin x 3 symbols Type" }, + { 3, "3 bin x 2 symbols Type" }, + { 0, NULL } +}; + +/* Max Logical Bands */ +static const value_string vals_max_logical_bands[] = +{ + { 0, "3 Bands" }, + { 1, "6 Bands" }, + { 2, "12 Bands (default)" }, + { 3, "24 Bands" }, + { 0, NULL } +}; + +/* Repetition Coding Indications */ +static const value_string rep_msgs[] = +{ + { 0, "No Repetition Coding" }, + { 1, "Repetition Coding of 2 Used" }, + { 2, "Repetition Coding of 4 Used" }, + { 3, "Repetition Coding of 6 Used" }, + { 0, NULL } +}; + +/* Repetition Coding Indications */ +static const value_string vals_allocation_modes[] = +{ + { 0, "Same Number Of Subchannels For The Selected Bands" }, + { 1, "Different Same Number Of Subchannels For The Selected Bands" }, + { 2, "Total Number Of Subchannels For The Selected Bands Determined by Nsch Code and Nep Code" }, + { 3, "Reserved" }, + { 0, NULL } +}; + +/* Masks */ +#define DL_MAP_TYPE_MASK 0xE0 +#define UL_MAP_APPEND_MASK 0x10 +#define SHORTENED_DIUC_MASK 0xE0 +#define COMPANDED_SC_MASK 0x1F +#define DL_MAP_TYPE_MASK_1 0x0E +#define UL_MAP_APPEND_MASK_1 0x01 +#define SHORTENED_DIUC_MASK_1 0x0E00 +#define COMPANDED_SC_MASK_1 0x01F0 + +/* display indexies */ +static gint hf_cdlmap_dl_map_type = -1; +static gint hf_cdlmap_ul_map_append = -1; +static gint hf_cdlmap_reserved = -1; +static gint hf_cdlmap_nep_code = -1; +static gint hf_cdlmap_nsch_code = -1; +static gint hf_cdlmap_num_bands = -1; +static gint hf_cdlmap_band_index = -1; +static gint hf_cdlmap_nb_bitmap = -1; +static gint hf_cdlmap_dl_map_type_1 = -1; +static gint hf_cdlmap_ul_map_append_1 = -1; +static gint hf_cdlmap_reserved_1 = -1; +static gint hf_cdlmap_nep_code_1 = -1; +static gint hf_cdlmap_nsch_code_1 = -1; +static gint hf_cdlmap_num_bands_1 = -1; +/*static gint hf_cdlmap_band_index_1 = -1;*/ +static gint hf_cdlmap_nb_bitmap_1 = -1; + +static gint hf_cdlmap_shortened_diuc = -1; +static gint hf_cdlmap_companded_sc = -1; +static gint hf_cdlmap_shortened_uiuc = -1; +static gint hf_cdlmap_shortened_diuc_1 = -1; +static gint hf_cdlmap_companded_sc_1 = -1; +static gint hf_cdlmap_shortened_uiuc_1 = -1; + +static gint hf_cdlmap_bin_offset = -1; +static gint hf_cdlmap_bin_offset_1 = -1; + +static gint hf_cdlmap_diuc_num_of_subchannels = -1; +static gint hf_cdlmap_diuc_num_of_subchannels_1 = -1; +static gint hf_cdlmap_diuc_repetition_coding_indication = -1; +static gint hf_cdlmap_diuc_repetition_coding_indication_1 = -1; +static gint hf_cdlmap_diuc_reserved = -1; +static gint hf_cdlmap_diuc_reserved_1 = -1; + +static gint hf_cdlmap_bit_map_length = -1; +static gint hf_cdlmap_bit_map_length_1 = -1; +static gint hf_cdlmap_bit_map = -1; + +static gint hf_cdlmap_diuc = -1; +static gint hf_cdlmap_diuc_1 = -1; + +static gint hf_cdlmap_allocation_mode = -1; +static gint hf_cdlmap_allocation_mode_rsvd = -1; +static gint hf_cdlmap_num_subchannels = -1; +static gint hf_cdlmap_allocation_mode_1 = -1; +static gint hf_cdlmap_allocation_mode_rsvd_1 = -1; +static gint hf_cdlmap_num_subchannels_1 = -1; + +/* static gint hf_cdlmap_reserved_type = -1; */ +static gint hf_cdlmap_reserved_type_1 = -1; + +/* display indexies */ +static gint hf_format_config_ie_dl_map_type = -1; +static gint hf_format_config_ie_dl_map_type_1 = -1; +static gint hf_format_config_ie_dl_map_type_32 = -1; +static gint hf_format_config_ie_new_format_indication = -1; +static gint hf_format_config_ie_new_format_indication_1 = -1; +static gint hf_format_config_ie_new_format_indication_32 = -1; +static gint hf_format_config_ie_cid_type = -1; +static gint hf_format_config_ie_cid_type_1 = -1; +static gint hf_format_config_ie_safety_pattern = -1; +static gint hf_format_config_ie_safety_pattern_1 = -1; +static gint hf_format_config_ie_subchannel_type = -1; +static gint hf_format_config_ie_subchannel_type_1 = -1; +static gint hf_format_config_ie_max_logical_bands = -1; +static gint hf_format_config_ie_max_logical_bands_1 = -1; +static gint hf_format_config_ie_num_of_broadcast_symbol = -1; +static gint hf_format_config_ie_num_of_broadcast_symbol_1 = -1; +static gint hf_format_config_ie_num_of_dl_band_amc_symbol = -1; +static gint hf_format_config_ie_num_of_dl_band_amc_symbol_1 = -1; +static gint hf_format_config_ie_num_of_ul_band_amc_symbol = -1; +static gint hf_format_config_ie_num_of_ul_band_amc_symbol_1 = -1; + +/* Format Configuration IE Masks */ +#define FORMAT_CONFIG_IE_DL_MAP_TYPE_MASK 0xE0000000 +#define FORMAT_CONFIG_IE_NEW_FORMAT_IND_MASK 0x10000000 +#define CID_TYPE_MASK_1 0x0C000000 +#define SAFETY_PATTERN_MASK_1 0x03E00000 +#define BAND_AMC_SUBCHANNEL_TYPE_MASK_1 0x00180000 +#define MAX_LOGICAL_BANDS_MASK_1 0x00060000 +#define NUM_BROADCAST_SYMBOLS_MASK_1 0x0001F000 +#define NUM_DL_AMC_SYMBOLS_MASK_1 0x00000FC0 +#define NUM_UL_AMC_SYMBOLS_MASK_1 0x0000003F +#define CID_TYPE_MASK 0xC0000000 +#define SAFETY_PATTERN_MASK 0x3E000000 +#define BAND_AMC_SUBCHANNEL_TYPE_MASK 0x01800000 +#define MAX_LOGICAL_BANDS_MASK 0x00600000 +#define NUM_BROADCAST_SYMBOLS_MASK 0x001F0000 +#define NUM_DL_AMC_SYMBOLS_MASK 0x0000FC00 +#define NUM_UL_AMC_SYMBOLS_MASK 0x000003F0 + +/* display indexies */ +static gint hf_harq_rcid_ie_prefix = -1; +static gint hf_harq_rcid_ie_prefix_1 = -1; +static gint hf_harq_rcid_ie_normal_cid = -1; +static gint hf_harq_rcid_ie_normal_cid_1 = -1; +static gint hf_harq_rcid_ie_cid3 = -1; +static gint hf_harq_rcid_ie_cid3_1 = -1; +static gint hf_harq_rcid_ie_cid7 = -1; +static gint hf_harq_rcid_ie_cid7_1 = -1; +static gint hf_harq_rcid_ie_cid11 = -1; +static gint hf_harq_rcid_ie_cid11_1 = -1; +static gint hf_harq_rcid_ie_cid11_2 = -1; +static gint hf_harq_rcid_ie_cid11_3 = -1; + +/* Masks */ +#define WIMAX_RCID_IE_NORMAL_CID_MASK_1 0x0FFFF0 +#define WIMAX_RCID_IE_PREFIX_MASK 0x8000 +#define WIMAX_RCID_IE_PREFIX_MASK_1 0x0800 +#define WIMAX_RCID_IE_CID3_MASK 0x7000 +#define WIMAX_RCID_IE_CID3_MASK_1 0x0700 +#define WIMAX_RCID_IE_CID7_MASK 0x7F00 +#define WIMAX_RCID_IE_CID7_MASK_1 0x07F0 +#define WIMAX_RCID_IE_CID11_MASK 0x7FF0 +#define WIMAX_RCID_IE_CID11_MASK_1 0x07FF + +/* HARQ MAP HARQ Control IE display indexies */ +static gint hf_harq_control_ie_prefix = -1; +static gint hf_harq_control_ie_ai_sn = -1; +static gint hf_harq_control_ie_spid = -1; +static gint hf_harq_control_ie_acid = -1; +static gint hf_harq_control_ie_reserved = -1; +static gint hf_harq_control_ie_prefix_1 = -1; +static gint hf_harq_control_ie_ai_sn_1 = -1; +static gint hf_harq_control_ie_spid_1 = -1; +static gint hf_harq_control_ie_acid_1 = -1; +static gint hf_harq_control_ie_reserved_1 = -1; + +/* Masks */ +#define WIMAX_HARQ_CONTROL_IE_PREFIX_MASK 0x80 +#define WIMAX_HARQ_CONTROL_IE_AI_SN_MASK 0x40 +#define WIMAX_HARQ_CONTROL_IE_SPID_MASK 0x30 +#define WIMAX_HARQ_CONTROL_IE_ACID_MASK 0x0F +#define WIMAX_HARQ_CONTROL_IE_RESERVED_MASK 0x70 +#define WIMAX_HARQ_CONTROL_IE_PREFIX_MASK_1 0x0800 +#define WIMAX_HARQ_CONTROL_IE_AI_SN_MASK_1 0x0400 +#define WIMAX_HARQ_CONTROL_IE_SPID_MASK_1 0x0300 +#define WIMAX_HARQ_CONTROL_IE_ACID_MASK_1 0x00F0 +#define WIMAX_HARQ_CONTROL_IE_RESERVED_MASK_1 0x0700 + +/* HARQ MAP CQICH Control IE display indexies */ +static gint hf_cqich_control_ie_indicator = -1; +static gint hf_cqich_control_ie_alloc_id = -1; +static gint hf_cqich_control_ie_period = -1; +static gint hf_cqich_control_ie_frame_offset = -1; +static gint hf_cqich_control_ie_duration = -1; +static gint hf_cqich_control_ie_cqi_rep_threshold = -1; +static gint hf_cqich_control_ie_indicator_1 = -1; +static gint hf_cqich_control_ie_alloc_id_1 = -1; +static gint hf_cqich_control_ie_period_1 = -1; +static gint hf_cqich_control_ie_frame_offset_1 = -1; +static gint hf_cqich_control_ie_duration_1 = -1; +static gint hf_cqich_control_ie_cqi_rep_threshold_1 = -1; + +/* Masks */ +#define WIMAX_CQICH_CONTROL_IE_INDICATOR_MASK 0x8000 +#define WIMAX_CQICH_CONTROL_IE_ALLOCATION_INDEX_MASK 0x7E00 +#define WIMAX_CQICH_CONTROL_IE_PERIOD_MASK 0x0180 +#define WIMAX_CQICH_CONTROL_IE_FRAME_OFFSET_MASK 0x0070 +#define WIMAX_CQICH_CONTROL_IE_DURATION_MASK 0x000F +#define WIMAX_CQICH_CONTROL_IE_CQI_REP_THRESHOLD_MASK 0x7000 +#define WIMAX_CQICH_CONTROL_IE_INDICATOR_MASK_1 0x080000 +#define WIMAX_CQICH_CONTROL_IE_ALLOCATION_INDEX_MASK_1 0x07E000 +#define WIMAX_CQICH_CONTROL_IE_PERIOD_MASK_1 0x001800 +#define WIMAX_CQICH_CONTROL_IE_FRAME_OFFSET_MASK_1 0x000700 +#define WIMAX_CQICH_CONTROL_IE_DURATION_MASK_1 0x0000F0 +#define WIMAX_CQICH_CONTROL_IE_CQI_REP_THRESHOLD_MASK_1 0x070000 + +/* Extension Type */ +#define EXTENSION_TYPE_MASK 0xE000 +#define EXTENSION_TYPE_MASK_1 0x0E00 +#define EXTENSION_SUBTYPE_MASK 0x1F00 +#define EXTENSION_SUBTYPE_MASK_1 0x01F0 +#define EXTENSION_LENGTH_MASK 0x00F0 +#define EXTENSION_LENGTH_MASK_1 0x000F + +static gint hf_cdlmap_extension_type = -1; +static gint hf_cdlmap_extension_subtype = -1; +static gint hf_cdlmap_extension_length = -1; +static gint hf_cdlmap_extension_type_1 = -1; +static gint hf_cdlmap_extension_subtype_1 = -1; +static gint hf_cdlmap_extension_length_1 = -1; + +static gint hf_cdlmap_extension_time_diversity_mbs = -1; +static gint hf_cdlmap_extension_harq_mode = -1; +static gint hf_cdlmap_extension_unknown_sub_type = -1; +static gint hf_cdlmap_extension_time_diversity_mbs_1 = -1; +static gint hf_cdlmap_extension_harq_mode_1 = -1; +static gint hf_cdlmap_extension_unknown_sub_type_1 = -1; + +/* Extended DIUC dependent IE display indexies */ +static gint hf_extended_diuc_dependent_ie_diuc = -1; +static gint hf_extended_diuc_dependent_ie_diuc_1 = -1; +static gint hf_extended_diuc_dependent_ie_length = -1; +static gint hf_extended_diuc_dependent_ie_length_1 = -1; +static gint hf_extended_diuc_dependent_ie_channel_measurement = -1; +static gint hf_extended_diuc_dependent_ie_stc_zone = -1; +static gint hf_extended_diuc_dependent_ie_aas_dl = -1; +static gint hf_extended_diuc_dependent_ie_data_location = -1; +static gint hf_extended_diuc_dependent_ie_cid_switch = -1; +static gint hf_extended_diuc_dependent_ie_mimo_dl_basic = -1; +static gint hf_extended_diuc_dependent_ie_mimo_dl_enhanced = -1; +static gint hf_extended_diuc_dependent_ie_harq_map_pointer = -1; +static gint hf_extended_diuc_dependent_ie_phymod_dl = -1; +static gint hf_extended_diuc_dependent_ie_dl_pusc_burst_allocation = -1; +static gint hf_extended_diuc_dependent_ie_ul_interference_and_noise_level = -1; +static gint hf_extended_diuc_dependent_ie_unknown_diuc = -1; + + +/* Compact DL-MAP IE Types (table 89) */ +#define COMPACT_DL_MAP_TYPE_NORMAL_SUBCHANNEL 0 +#define COMPACT_DL_MAP_TYPE_BAND_AMC 1 +#define COMPACT_DL_MAP_TYPE_SAFETY 2 +#define COMPACT_DL_MAP_TYPE_UIUC 3 +#define COMPACT_DL_MAP_TYPE_FORMAT_CONF_IE 4 +#define COMPACT_DL_MAP_TYPE_HARQ_ACK_BITMAP_IE 5 +#define COMPACT_DL_MAP_TYPE_RESERVED 6 +#define COMPACT_DL_MAP_TYPE_EXTENSION 7 + +/* Compact DL-MAP IE decoder */ +guint wimax_compact_dlmap_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint diuc, byte, length = 0; + guint dl_map_type, ul_map_append; + guint dl_map_offset, nibble_length, bit_map_length; + guint nband, band_count, i, allocation_mode; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Compact DL-MAP IEs"); +#endif + /* set the local offset */ + dl_map_offset = offset; + /* Get the first byte */ + byte = tvb_get_guint8(tvb, dl_map_offset); + if(nibble_offset & 1) + { + dl_map_type = ((byte & DL_MAP_TYPE_MASK_1) >> 1); + ul_map_append = (byte & UL_MAP_APPEND_MASK_1); + } + else + { + dl_map_type = ((byte & DL_MAP_TYPE_MASK) >> 5); + ul_map_append = (byte & UL_MAP_APPEND_MASK); + } + switch (dl_map_type) + { + case COMPACT_DL_MAP_TYPE_NORMAL_SUBCHANNEL:/* 6.3.2.3.43.6.1 */ + if(nibble_offset & 1) + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the UL-MAP append */ + proto_tree_add_item(tree, hf_cdlmap_ul_map_append_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + nibble_offset = 0; + } + else + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the UL-MAP append */ + proto_tree_add_item(tree, hf_cdlmap_ul_map_append, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length = 1; + /* decode RCID IE */ + nibble_length = wimax_compact_dlmap_rcid_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + /* check harq mode */ + if(!harq_mode) + { /* display the Nep and Nsch Code */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_nep_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + proto_tree_add_item(tree, hf_cdlmap_nsch_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_nep_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_nsch_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + length += 2; + } + else if(harq_mode == 1) + { /* display the Shortened DIUC and Companded SC */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_shortened_diuc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_shortened_diuc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + /* move to next byte */ + dl_map_offset++; + length += 2; + } + /* decode HARQ Control IE */ + nibble_length = wimax_compact_dlmap_harq_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += ((nibble_offset + nibble_length) >> 1); + nibble_offset = ((nibble_offset + nibble_length) & 1); + /* decode CQICH Control IE */ + nibble_length = wimax_compact_dlmap_cqich_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += ((nibble_offset + nibble_length) >> 1); + nibble_offset = ((nibble_offset + nibble_length) & 1); + if(ul_map_append) + { /* check harq mode */ + if(harq_mode == 1) + { /* display the Shortened UIUC and Companded SC */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_shortened_uiuc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_shortened_uiuc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + /* move to next byte */ + dl_map_offset++; + length += 2; + } + else if(!harq_mode) + { /* display the Nep and Nsch Code */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_nep_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + proto_tree_add_item(tree, hf_cdlmap_nsch_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_nep_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_nsch_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + length += 2; + } + /* decode HARQ Control IE */ + nibble_length = wimax_compact_dlmap_harq_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + } + break; + case COMPACT_DL_MAP_TYPE_BAND_AMC:/* 6.3.2.3.43.6.2 */ + if(nibble_offset & 1) + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_cdlmap_reserved_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + nibble_offset = 0; + } + else + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_cdlmap_reserved, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length = 1; + /* decode RCID IE */ + nibble_length = wimax_compact_dlmap_rcid_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + /* check harq mode */ + if(!harq_mode) + { /* display the Nep and Nsch Code */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_nep_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + proto_tree_add_item(tree, hf_cdlmap_nsch_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_nep_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_nsch_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + length += 2; + } + else if(harq_mode == 1) + { /* display the Shortened DIUC and Companded SC */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_shortened_diuc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_shortened_diuc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + /* move to next byte */ + dl_map_offset++; + length += 2; + } + /* get the Nband */ + if(max_logical_bands) + { /* get and display the Nband */ + nband = tvb_get_guint8(tvb, dl_map_offset); + if(nibble_offset & 1) + { + nband = (nband & LSB_NIBBLE_MASK); + /* display the Nband */ + proto_tree_add_item(tree, hf_cdlmap_num_bands_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + nibble_offset = 0; + if(max_logical_bands == 3) + { + proto_tree_add_item(tree, hf_cdlmap_band_index, tvb, dl_map_offset, nband, ENC_NA); + length += (nband * 2); + /* update offset */ + dl_map_offset += nband; + } + else + { + nibble_offset = (nband & 1); + proto_tree_add_item(tree, hf_cdlmap_band_index, tvb, dl_map_offset, ((nband >> 1) + nibble_offset), ENC_NA); + length += nband; + /* update offset */ + dl_map_offset += (nband >> 1); + } + } + else + { + nband = ((nband & MSB_NIBBLE_MASK) >> 4); + /* display the Nband */ + proto_tree_add_item(tree, hf_cdlmap_num_bands, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + if(max_logical_bands == 3) + { + proto_tree_add_item(tree, hf_cdlmap_band_index, tvb, dl_map_offset, (nband + nibble_offset), ENC_NA); + length += (nband * 2); + /* update offset */ + dl_map_offset += nband; + } + else + { + proto_tree_add_item(tree, hf_cdlmap_band_index, tvb, dl_map_offset, ((nband >> 1) + nibble_offset), ENC_NA); + length += nband; + /* update offset */ + dl_map_offset += ((nband + nibble_offset) >> 1); + if(nband & 1) + nibble_offset = 0; + } + } + length++; + band_count = nband; + } + else + { + band_count = 1; + /* display the Nb-BITMAP */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_nb_bitmap_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + nibble_offset = 0; + } + else + { + proto_tree_add_item(tree, hf_cdlmap_nb_bitmap, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length++; + } + /* Get the Allocation Mode */ + byte = tvb_get_guint8(tvb, dl_map_offset); + if(nibble_offset & 1) + { + allocation_mode = ((byte & 0x0C) >> 2); + proto_tree_add_item(tree, hf_cdlmap_allocation_mode_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_allocation_mode_rsvd_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 0; + dl_map_offset++; + } + else + { + allocation_mode = ((byte & 0xC0) >> 6); + proto_tree_add_item(tree, hf_cdlmap_allocation_mode, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_allocation_mode_rsvd, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + /* Decode Allocation Mode - need to be done */ + if(!allocation_mode) + { + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_num_subchannels_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_num_subchannels, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + dl_map_offset++; + } + else if(allocation_mode == 1) + { + for(i=0; i> 1); + nibble_offset = ((nibble_offset + nibble_length) & 1); + /* decode CQICH Control IE */ + nibble_length = wimax_compact_dlmap_cqich_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + break; + case COMPACT_DL_MAP_TYPE_SAFETY:/* 6.3.2.3.43.6.3 */ + if(nibble_offset & 1) + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the UL-MAP append */ + proto_tree_add_item(tree, hf_cdlmap_ul_map_append_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + nibble_offset = 0; + } + else + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the UL-MAP append */ + proto_tree_add_item(tree, hf_cdlmap_ul_map_append, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length = 1; + /* decode RCID IE */ + nibble_length = wimax_compact_dlmap_rcid_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + /* check harq mode */ + if(!harq_mode) + { /* display the Nep and Nsch Code */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_nep_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + proto_tree_add_item(tree, hf_cdlmap_nsch_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_nep_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_nsch_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + length += 2; + } + else if(harq_mode == 1) + { /* display the Shortened DIUC and Companded SC */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_shortened_diuc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_shortened_diuc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + /* move to next byte */ + dl_map_offset++; + length += 2; + } + /* display BIN offset */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_bin_offset_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + else + { + proto_tree_add_item(tree, hf_cdlmap_bin_offset, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + length += 2; + /* decode HARQ Control IE */ + nibble_length = wimax_compact_dlmap_harq_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += ((nibble_offset + nibble_length) >> 1); + nibble_offset = ((nibble_offset + nibble_length) & 1); + /* decode CQICH Control IE */ + nibble_length = wimax_compact_dlmap_cqich_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += ((nibble_offset + nibble_length) >> 1); + nibble_offset = ((nibble_offset + nibble_length) & 1); + if(ul_map_append) + { /* check harq mode */ + if(harq_mode == 1) + { /* display the Shortened DIUC and Companded SC */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_shortened_diuc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_shortened_diuc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_companded_sc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + /* move to next byte */ + dl_map_offset++; + length += 2; + } + else if(!harq_mode) + { /* display the Nep and Nsch Code */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_nep_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + proto_tree_add_item(tree, hf_cdlmap_nsch_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_nep_code, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_nsch_code_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + length += 2; + } + /* display BIN offset */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_bin_offset_1, tvb, dl_map_offset, 2, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + else + { + proto_tree_add_item(tree, hf_cdlmap_bin_offset, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + length += 2; + /* decode HARQ Control IE */ + nibble_length = wimax_compact_dlmap_harq_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + } + break; + case COMPACT_DL_MAP_TYPE_UIUC:/* 6.3.2.3.43.6.4 */ + if(nibble_offset & 1) + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_cdlmap_reserved_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + /* get the new byte */ + byte = tvb_get_guint8(tvb, dl_map_offset); + /* get the DIUC */ + diuc = ((byte & MSB_NIBBLE_MASK) >> 4); + /* display the DIUC */ + proto_tree_add_item(tree, hf_cdlmap_diuc, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_cdlmap_reserved, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* get the DIUC */ + diuc = (tvb_get_guint8(tvb, dl_map_offset) & LSB_NIBBLE_MASK); + /* display the DIUC */ + proto_tree_add_item(tree, hf_cdlmap_diuc_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + dl_map_offset++; + } + length = 2; + if(diuc == 15) + { /* Extended DIUC dependent IE */ + nibble_length = wimax_extended_diuc_dependent_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + } + else + { /* decode RCID IE */ + nibble_length = wimax_compact_dlmap_rcid_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + /* display Number of subchannels */ + if(nibble_offset & 1) + proto_tree_add_item(tree, hf_cdlmap_diuc_num_of_subchannels_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + else + proto_tree_add_item(tree, hf_cdlmap_diuc_num_of_subchannels, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + length += 2; + /* display the repetition coding indication and reserved bits */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_cdlmap_diuc_repetition_coding_indication_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_diuc_reserved_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_cdlmap_diuc_repetition_coding_indication, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_cdlmap_diuc_reserved, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + } + length += 1; + } + /* decode HARQ Control IE */ + nibble_length = wimax_compact_dlmap_harq_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + dl_map_offset += ((nibble_offset + nibble_length) >> 1); + nibble_offset = ((nibble_offset + nibble_length) & 1); + /* decode CQICH Control IE */ + nibble_length = wimax_compact_dlmap_cqich_control_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length += nibble_length; + break; + case COMPACT_DL_MAP_TYPE_FORMAT_CONF_IE:/* 6.3.2.3.43.2 */ + /* decode the format configuration IE */ + nibble_length = wimax_compact_dlmap_format_configuration_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset); + length = nibble_length; + break; + case COMPACT_DL_MAP_TYPE_HARQ_ACK_BITMAP_IE:/* 6.3.2.3.43.6.5 */ + if(nibble_offset & 1) + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_cdlmap_reserved_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + length = 1; + /* move to next byte */ + dl_map_offset++; + /* get the bit map length */ + byte = tvb_get_guint8(tvb, dl_map_offset); + bit_map_length = ((byte & MSB_NIBBLE_MASK) >> 4); + /* display BITMAP Length */ + proto_tree_add_item(tree, hf_cdlmap_bit_map_length, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display BITMAP */ + proto_tree_add_item(tree, hf_cdlmap_bit_map, tvb, dl_map_offset, bit_map_length + 1, ENC_NA); + length += (1 + bit_map_length * 2); + } + else + { + /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_dl_map_type, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_cdlmap_reserved, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display BITMAP Length */ + proto_tree_add_item(tree, hf_cdlmap_bit_map_length_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + length = 2; + /* get the bit map length */ + bit_map_length = (byte & LSB_NIBBLE_MASK); + /* move to next byte */ + dl_map_offset++; + /* display BITMAP */ + proto_tree_add_item(tree, hf_cdlmap_bit_map, tvb, dl_map_offset, bit_map_length, ENC_NA); + length += (bit_map_length * 2); + } + break; + case COMPACT_DL_MAP_TYPE_EXTENSION:/* 6.3.2.3.43.6.6 */ + /* decode the Compact DL-MAP externsion IE */ + nibble_length = wimax_cdlmap_extension_ie_decoder(tree, pinfo, tvb, dl_map_offset, nibble_offset);/*, cqich_indicator);*/ + length = nibble_length; + break; + default:/* Reserved Type */ + /* display the reserved type */ + proto_tree_add_item(tree, hf_cdlmap_reserved_type_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + length = 1; + break; + } + /* Update the nibble_offset and length */ + return length; +} + +/* Format Configuration IE shifts */ +#define CID_TYPE_SHIFT 30 +#define SAFETY_PATTERN_SHIFT 25 +#define BAND_AMC_SUBCHANNEL_TYPE_SHIFT 23 +#define MAX_LOGICAL_BANDS_SHIFT 21 +#define NUM_BROADCAST_SYMBOLS_SHIFT 16 +#define NUM_DL_AMC_SYMBOLS_SHIFT 10 +#define NUM_UL_AMC_SYMBOLS_SHIFT 4 +#define CID_TYPE_SHIFT_1 (CID_TYPE_SHIFT-NUM_UL_AMC_SYMBOLS_SHIFT) +#define SAFETY_PATTERN_SHIFT_1 (SAFETY_PATTERN_SHIFT-NUM_UL_AMC_SYMBOLS_SHIFT) +#define BAND_AMC_SUBCHANNEL_TYPE_SHIFT_1 (BAND_AMC_SUBCHANNEL_TYPE_SHIFT-NUM_UL_AMC_SYMBOLS_SHIFT) +#define MAX_LOGICAL_BANDS_SHIFT_1 (MAX_LOGICAL_BANDS_SHIFT-NUM_UL_AMC_SYMBOLS_SHIFT) +#define NUM_BROADCAST_SYMBOLS_SHIFT_1 (NUM_BROADCAST_SYMBOLS_SHIFT-NUM_UL_AMC_SYMBOLS_SHIFT) +#define NUM_DL_AMC_SYMBOLS_SHIFT_1 (NUM_DL_AMC_SYMBOLS_SHIFT-NUM_UL_AMC_SYMBOLS_SHIFT) +/*#define NUM_UL_AMC_SYMBOLS_SHIFT_1 0*/ + +/* Compact DL-MAP Format Configuration IE (6.3.2.3.43.2) decoder */ +static guint wimax_compact_dlmap_format_configuration_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint length = 0; + guint dl_map_type, new_format_ind; + guint dl_map_offset; + guint32 tvb_value; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Format Configuration IE"); +#endif + /* set the local offset */ + dl_map_offset = offset; + /* Get the first byte */ + tvb_value = tvb_get_guint8(tvb, dl_map_offset); + if(nibble_offset & 1) + { /* get the DL-MAP type */ + dl_map_type = ((tvb_value & DL_MAP_TYPE_MASK_1) >> 1); + /* ensure the dl-map type is Format Configuration IE */ + if(dl_map_type != COMPACT_DL_MAP_TYPE_FORMAT_CONF_IE) + return 0; + new_format_ind = (tvb_value & 0x01); + /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_format_config_ie_dl_map_type_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the New format Indication */ + proto_tree_add_item(tree, hf_format_config_ie_new_format_indication_1, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* update the length in nibble */ + length = 1; + /* move to next byte */ + dl_map_offset++; + if(new_format_ind) + { /* display the CID Type */ + proto_tree_add_item(tree, hf_format_config_ie_cid_type, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the Safety Pattern */ + proto_tree_add_item(tree, hf_format_config_ie_safety_pattern, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the Subchannel pattern */ + proto_tree_add_item(tree, hf_format_config_ie_subchannel_type, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the max logical bands */ + proto_tree_add_item(tree, hf_format_config_ie_max_logical_bands, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the number of broadcast symbols */ + proto_tree_add_item(tree, hf_format_config_ie_num_of_broadcast_symbol, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the number of dl band AMC symbols */ + proto_tree_add_item(tree, hf_format_config_ie_num_of_dl_band_amc_symbol, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the number of ul band AMC symbols */ + proto_tree_add_item(tree, hf_format_config_ie_num_of_ul_band_amc_symbol, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* update the length in nibble */ + length += 7; + /* Get the next 32-bit word */ + tvb_value = tvb_get_ntohl(tvb, dl_map_offset); + /* get the CID type */ + cid_type = ((tvb_value & CID_TYPE_MASK) >> CID_TYPE_SHIFT); + /* get the subchannel type for band AMC */ + band_amc_subchannel_type = ((tvb_value & BAND_AMC_SUBCHANNEL_TYPE_MASK) >> BAND_AMC_SUBCHANNEL_TYPE_SHIFT); + /* get the max logical bands */ + max_logical_bands = ((tvb_value & MAX_LOGICAL_BANDS_MASK) >> MAX_LOGICAL_BANDS_SHIFT); + /* get the number of symbols for broadcast */ + num_of_broadcast_symbols = ((tvb_value & NUM_BROADCAST_SYMBOLS_MASK) >> NUM_BROADCAST_SYMBOLS_SHIFT); + /* get the number of symbols for DL band AMC */ + num_of_dl_band_amc_symbols = ((tvb_value & NUM_DL_AMC_SYMBOLS_MASK) >> NUM_DL_AMC_SYMBOLS_SHIFT); + /* get the number of symbols for UL band AMC */ + num_of_ul_band_amc_symbols = ((tvb_value & NUM_UL_AMC_SYMBOLS_MASK) >> NUM_UL_AMC_SYMBOLS_SHIFT); + } + } + else + { + dl_map_type = ((tvb_value & DL_MAP_TYPE_MASK) >> 5); + /* ensure the dl-map type is Format Configuration IE */ + if(dl_map_type != COMPACT_DL_MAP_TYPE_FORMAT_CONF_IE) + return 0; + new_format_ind = (tvb_value & 0x10); + if(new_format_ind) + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_format_config_ie_dl_map_type_32, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the New format Indication */ + proto_tree_add_item(tree, hf_format_config_ie_new_format_indication_32, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the CID Type */ + proto_tree_add_item(tree, hf_format_config_ie_cid_type_1, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the Safety Pattern */ + proto_tree_add_item(tree, hf_format_config_ie_safety_pattern_1, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the Subchannel pattern */ + proto_tree_add_item(tree, hf_format_config_ie_subchannel_type_1, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the max logical bands */ + proto_tree_add_item(tree, hf_format_config_ie_max_logical_bands_1, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the number of broadcast symbols */ + proto_tree_add_item(tree, hf_format_config_ie_num_of_broadcast_symbol_1, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the number of dl band AMC symbols */ + proto_tree_add_item(tree, hf_format_config_ie_num_of_dl_band_amc_symbol_1, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* display the number of ul band AMC symbols */ + proto_tree_add_item(tree, hf_format_config_ie_num_of_ul_band_amc_symbol_1, tvb, dl_map_offset, 4, ENC_BIG_ENDIAN); + /* update the length in nibble */ + length = 8; + /* Get the next 32-bit word */ + tvb_value = tvb_get_ntohl(tvb, dl_map_offset); + /* get the CID type */ + cid_type = ((tvb_value & CID_TYPE_MASK_1) >> CID_TYPE_SHIFT_1); + /* get the subchannel type for band AMC */ + band_amc_subchannel_type = ((tvb_value & BAND_AMC_SUBCHANNEL_TYPE_MASK_1) >> BAND_AMC_SUBCHANNEL_TYPE_SHIFT_1); + /* get the max logical bands */ + max_logical_bands = ((tvb_value & MAX_LOGICAL_BANDS_MASK_1) >> MAX_LOGICAL_BANDS_SHIFT_1); + /* get the number of symbols for broadcast */ + num_of_broadcast_symbols = ((tvb_value & NUM_BROADCAST_SYMBOLS_MASK_1) >> NUM_BROADCAST_SYMBOLS_SHIFT_1); + /* get the number of symbols for DL band AMC */ + num_of_dl_band_amc_symbols = ((tvb_value & NUM_DL_AMC_SYMBOLS_MASK_1) >> NUM_DL_AMC_SYMBOLS_SHIFT_1); + /* get the number of symbols for UL band AMC */ + num_of_ul_band_amc_symbols = (tvb_value & NUM_UL_AMC_SYMBOLS_MASK_1); + } + else + { /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_format_config_ie_dl_map_type, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* display the New format Indication */ + proto_tree_add_item(tree, hf_format_config_ie_new_format_indication, tvb, dl_map_offset, 1, ENC_BIG_ENDIAN); + /* update the length in nibble */ + length = 1; + } + } + /* return the IE length in nibbles */ + return length; +} + +/* Compact DL-MAP Reduced CID IE (6.3.2.3.43.3) decoder */ +static guint wimax_compact_dlmap_rcid_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint length = 0; + guint prefix; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RCID IE"); +#endif + if(nibble_offset & 1) + { + if(cid_type == CID_TYPE_NORMAL) + { /* display the normal CID */ + proto_tree_add_item(tree, hf_harq_rcid_ie_normal_cid_1, tvb, offset, 3, ENC_BIG_ENDIAN); + length = 4; + } + else + { /* Get the prefix bit */ + prefix = (tvb_get_guint8(tvb, offset) & 0x08); + /* display the prefix */ + proto_tree_add_item(tree, hf_harq_rcid_ie_prefix_1, tvb, offset, 2, ENC_BIG_ENDIAN); + if(prefix) + { /* display the CID11 */ + proto_tree_add_item(tree, hf_harq_rcid_ie_cid11_3, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 3; + } + else + { + if(cid_type == CID_TYPE_RCID11) + { /* display the CID11 */ + proto_tree_add_item(tree, hf_harq_rcid_ie_cid11_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 3; + } + else if(cid_type == CID_TYPE_RCID7) + { /* display the normal CID7 */ + proto_tree_add_item(tree, hf_harq_rcid_ie_cid7_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 2; + } + else if(cid_type == CID_TYPE_RCID3) + { /* display the CID3 */ + proto_tree_add_item(tree, hf_harq_rcid_ie_cid3_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 1; + } + } + } + } + else + { + if(cid_type == CID_TYPE_NORMAL) + { /* display the normal CID */ + proto_tree_add_item(tree, hf_harq_rcid_ie_normal_cid, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 4; + } + else + { /* Get the prefix bit */ + prefix = (tvb_get_guint8(tvb, offset) & 0x08); + /* display the prefix */ + proto_tree_add_item(tree, hf_harq_rcid_ie_prefix, tvb, offset, 2, ENC_BIG_ENDIAN); + if(prefix || (cid_type == CID_TYPE_RCID11)) + { /* display the CID11 */ + proto_tree_add_item(tree, hf_harq_rcid_ie_cid11_2, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 3; + } + else + { + if(cid_type == CID_TYPE_RCID11) + { /* display the CID11 */ + proto_tree_add_item(tree, hf_harq_rcid_ie_cid11, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 3; + } + else if(cid_type == CID_TYPE_RCID7) + { /* display the CID7 */ + proto_tree_add_item(tree, hf_harq_rcid_ie_cid7, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 2; + } + else if(cid_type == CID_TYPE_RCID3) + { /* display the CID3 */ + proto_tree_add_item(tree, hf_harq_rcid_ie_cid3, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 1; + } + } + } + } + /* return the IE length in nibbles */ + return length; +} + +/* Compact DL-MAP HARQ Control IE (6.3.2.3.43.4) decoder */ +static guint wimax_compact_dlmap_harq_control_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint byte, prefix, length = 0; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "HARQ Control IE"); +#endif + /* Get the first byte */ + byte = tvb_get_guint8(tvb, offset); + if(nibble_offset & 1) + { /* Get the prefix bit */ + prefix = (byte & 0x08); + /* display the prefix */ + proto_tree_add_item(tree, hf_harq_control_ie_prefix_1, tvb, offset, 2, ENC_BIG_ENDIAN); + if(prefix) + { /* display the ai_sn */ + proto_tree_add_item(tree, hf_harq_control_ie_ai_sn_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the spid */ + proto_tree_add_item(tree, hf_harq_control_ie_spid_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the acid */ + proto_tree_add_item(tree, hf_harq_control_ie_acid_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 2; + } + else + { /* display the reserved bits */ + proto_tree_add_item(tree, hf_harq_control_ie_reserved_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 1; + } + } + else + { /* Get the prefix bit */ + prefix = (byte & 0x80); + /* display the prefix */ + proto_tree_add_item(tree, hf_harq_control_ie_prefix, tvb, offset, 1, ENC_BIG_ENDIAN); + if(prefix) + { /* display the ai_sn */ + proto_tree_add_item(tree, hf_harq_control_ie_ai_sn, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the spid */ + proto_tree_add_item(tree, hf_harq_control_ie_spid, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the acid */ + proto_tree_add_item(tree, hf_harq_control_ie_acid, tvb, offset, 1, ENC_BIG_ENDIAN); + length = 2; + } + else + { /* display the reserved bits */ + proto_tree_add_item(tree, hf_harq_control_ie_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + length = 1; + } + } + /* return the IE length in nibbles */ + return length; +} + +/* Compact DL-MAP CQICH Control IE (6.3.2.3.43.5) decoder */ +static guint wimax_compact_dlmap_cqich_control_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint byte, cqich_indicator, length = 0; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "CQICH Control IE"); +#endif + /* Get the first byte */ + byte = tvb_get_guint8(tvb, offset); + if(nibble_offset & 1) + { /* Get the CQICH indicator */ + cqich_indicator = (byte & 0x08); + if(cqich_indicator) + { /* display the CQICH indicator */ + proto_tree_add_item(tree, hf_cqich_control_ie_indicator_1, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the allocation index */ + proto_tree_add_item(tree, hf_cqich_control_ie_alloc_id_1, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the period */ + proto_tree_add_item(tree, hf_cqich_control_ie_period_1, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the frame offset */ + proto_tree_add_item(tree, hf_cqich_control_ie_frame_offset_1, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the duration */ + proto_tree_add_item(tree, hf_cqich_control_ie_duration_1, tvb, offset, 3, ENC_BIG_ENDIAN); + length = 4; + } + else + { /* display the CQICH indicator */ + proto_tree_add_item(tree, hf_cqich_control_ie_indicator_1, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the CQI reporting threshold */ + proto_tree_add_item(tree, hf_cqich_control_ie_cqi_rep_threshold_1, tvb, offset, 1, ENC_BIG_ENDIAN); + length = 1; + } + } + else + { /* Get the CQICH indicator */ + cqich_indicator = (byte & 0x80); + if(cqich_indicator) + { /* display the CQICH indicator */ + proto_tree_add_item(tree, hf_cqich_control_ie_indicator, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the allocation index */ + proto_tree_add_item(tree, hf_cqich_control_ie_alloc_id, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the period */ + proto_tree_add_item(tree, hf_cqich_control_ie_period, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the frame offset */ + proto_tree_add_item(tree, hf_cqich_control_ie_frame_offset, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the duration */ + proto_tree_add_item(tree, hf_cqich_control_ie_duration, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 4; + } + else + { /* display the CQICH indicator */ + proto_tree_add_item(tree, hf_cqich_control_ie_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the CQI reporting threshold */ + proto_tree_add_item(tree, hf_cqich_control_ie_cqi_rep_threshold, tvb, offset, 1, ENC_BIG_ENDIAN); + length = 1; + } + } + /* return the IE length in nibbles */ + return length; +} + +/* DL-MAP Extension IE sub-types */ +#define TIME_DIVERSITY_MBS 0 +#define HARQ_MODE_SWITCH 1 + +/* Compact DL-MAP Extension IE (6.3.2.3.43.6.6) decoder */ +static guint wimax_cdlmap_extension_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint tvb_value, dl_map_type, sub_type, length; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DL-MAP Extension IE"); +#endif + /* Get the first 16-bit word */ + tvb_value = tvb_get_ntohs(tvb, offset); + if(nibble_offset & 1) + { /* Get the dl-map type */ + dl_map_type = ((tvb_value & 0x0E00) >> 9); + if(dl_map_type != COMPACT_DL_MAP_TYPE_EXTENSION) + return 0; + /* Get the sub-type */ + sub_type = ((tvb_value & 0x01F0) >> 4); + /* Get the IE length */ + length = (tvb_value & 0x000F); + /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_extension_type_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the DL-MAP extension subtype */ + proto_tree_add_item(tree, hf_cdlmap_extension_subtype_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the IE length */ + proto_tree_add_item(tree, hf_cdlmap_extension_length_1, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + switch (sub_type) + { + case TIME_DIVERSITY_MBS: + /* display the time-diversity MBS in HEX */ + proto_tree_add_item(tree, hf_cdlmap_extension_time_diversity_mbs_1, tvb, offset, (length - 2), ENC_NA); + break; + case HARQ_MODE_SWITCH: + /* display the HARQ mode */ + proto_tree_add_item(tree, hf_cdlmap_extension_harq_mode, tvb, offset, 1, ENC_BIG_ENDIAN); + /* Get the next byte */ + tvb_value = tvb_get_guint8(tvb, offset); + /* get the HARQ mode */ + harq_mode = ((tvb_value & MSB_NIBBLE_MASK) >> 4); + break; + default: + /* display the unknown sub-type in HEX */ + proto_tree_add_item(tree, hf_cdlmap_extension_unknown_sub_type_1, tvb, offset, (length - 2), ENC_NA); + break; + } + } + else + { /* Get the dl-map type */ + dl_map_type = ((tvb_value & 0xE000) >> 13); + if(dl_map_type != COMPACT_DL_MAP_TYPE_EXTENSION) + return 0; + /* Get the sub-type */ + sub_type = ((tvb_value & 0x1F00) >> 8); + /* Get the IE length */ + length = ((tvb_value & 0x00F0) >> 4); + /* display the DL-MAP type */ + proto_tree_add_item(tree, hf_cdlmap_extension_type, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the DL-MAP extension subtype */ + proto_tree_add_item(tree, hf_cdlmap_extension_subtype, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the IE length */ + proto_tree_add_item(tree, hf_cdlmap_extension_length, tvb, offset, 2, ENC_BIG_ENDIAN); + switch (sub_type) + { + case TIME_DIVERSITY_MBS: + /* display the time-diversity MBS in HEX */ + proto_tree_add_item(tree, hf_cdlmap_extension_time_diversity_mbs, tvb, (offset + 1), (length - 1), ENC_NA); + break; + case HARQ_MODE_SWITCH: + /* display the HARQ mode */ + proto_tree_add_item(tree, hf_cdlmap_extension_harq_mode_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* get the HARQ mode */ + harq_mode = (tvb_value & 0x000F); + break; + default: + /* display the unknown sub-type in HEX */ + proto_tree_add_item(tree, hf_cdlmap_extension_unknown_sub_type, tvb, (offset + 1), (length - 1), ENC_NA); + break; + } + } + /* return the IE length in nibbles */ + return (length * 2); +} + +/* Extended DIUCs (table 277a) */ +#define CHANNEL_MEASUREMENT_IE 0 +#define STC_ZONE_IE 1 +#define AAS_DL_IE 2 +#define DATA_LOCATION_IN_ANOTHER_BS_IE 3 +#define CID_SWITCH_IE 4 +#define MIMO_DL_BASIC_IE 5 +#define MIMO_DL_ENHANCED_IE 6 +#define HARQ_MAP_POINTER_IE 7 +#define PHYMOD_DL_IE 8 +#define DL_PUSC_BURST_ALLOCATION_IN_OTHER_SEGMENT_IE 11 +#define UL_INTERFERENCE_AND_NOISE_LEVEL_IE 15 + +/* Extended DIUC IE (8.4.5.3.2) */ +guint wimax_extended_diuc_dependent_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint ext_diuc, length; + guint8 byte; + + /* get the first byte */ + byte = tvb_get_guint8(tvb, offset); + if(nibble_offset & 1) + { /* get the extended DIUC */ + ext_diuc = (byte & LSB_NIBBLE_MASK); + /* display extended DIUC */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_diuc_1, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + offset++; + /* get the 2nd byte */ + byte = tvb_get_guint8(tvb, offset); + /* get the length */ + length = ((byte & MSB_NIBBLE_MASK) >> 4); + /* display extended DIUC length */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_length, tvb, offset, 1, ENC_BIG_ENDIAN); + /* 8.4.5.3.2.1 (table 277a) */ + switch (ext_diuc) + { + case CHANNEL_MEASUREMENT_IE: + /* 8.4.5.3.? Channel_Measurement_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_channel_measurement, tvb, offset, (length + 1), ENC_NA); + break; + case STC_ZONE_IE: + /* 8.4.5.3.4 STC_Zone_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_stc_zone, tvb, offset, (length + 1), ENC_NA); + break; + case AAS_DL_IE: + /* 8.4.5.3.3 AAS_DL_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_aas_dl, tvb, offset, (length + 1), ENC_NA); + break; + case DATA_LOCATION_IN_ANOTHER_BS_IE: + /* 8.4.5.3.6 Data_location_in_another_BS_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_data_location, tvb, offset, (length + 1), ENC_NA); + break; + case CID_SWITCH_IE: + /* 8.4.5.3.7 CID_Switch_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_cid_switch, tvb, offset, (length + 1), ENC_NA); + break; + case MIMO_DL_BASIC_IE: + /* 8.4.5.3.8 MIMO_DL_Basic_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_mimo_dl_basic, tvb, offset, (length + 1), ENC_NA); + break; + case MIMO_DL_ENHANCED_IE: + /* 8.4.5.3.9 MIMO_DL_Enhanced_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_mimo_dl_enhanced, tvb, offset, (length + 1), ENC_NA); + break; + case HARQ_MAP_POINTER_IE: + /* 8.4.5.3.10 HARQ_Map_Pointer_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_harq_map_pointer, tvb, offset, (length + 1), ENC_NA); + break; + case PHYMOD_DL_IE: + /* 8.4.5.3.11 PHYMOD_DL_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_phymod_dl, tvb, offset, (length + 1), ENC_NA); + break; + case DL_PUSC_BURST_ALLOCATION_IN_OTHER_SEGMENT_IE: + /* 8.4.5.3.13 DL PUSC Burst Allocation in Other Segment IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_dl_pusc_burst_allocation, tvb, offset, (length + 1), ENC_NA); + break; + case UL_INTERFERENCE_AND_NOISE_LEVEL_IE: + /* 8.4.5.3.19 UL_interference_and_noise_level_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_ul_interference_and_noise_level, tvb, offset, (length + 1), ENC_NA); + break; + default: + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_unknown_diuc, tvb, offset, (length + 1), ENC_NA); + break; + } + } + else + { /* get the extended DIUC */ + ext_diuc = ((byte & MSB_NIBBLE_MASK) >> 4); + /* get the length */ + length = (byte & LSB_NIBBLE_MASK); + /* display extended DIUC */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_diuc, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display extended DIUC length */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_length_1, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + offset++; + /* 8.4.5.3.2.1 (table 277a) */ + switch (ext_diuc) + { + case CHANNEL_MEASUREMENT_IE: + /* 8.4.5.3.? Channel_Measurement_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_channel_measurement, tvb, offset, length, ENC_NA); + break; + case STC_ZONE_IE: + /* 8.4.5.3.4 STC_Zone_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_stc_zone, tvb, offset, length, ENC_NA); + break; + case AAS_DL_IE: + /* 8.4.5.3.3 AAS_DL_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_aas_dl, tvb, offset, length, ENC_NA); + break; + case DATA_LOCATION_IN_ANOTHER_BS_IE: + /* 8.4.5.3.6 Data_location_in_another_BS_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_data_location, tvb, offset, length, ENC_NA); + break; + case CID_SWITCH_IE: + /* 8.4.5.3.7 CID_Switch_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_cid_switch, tvb, offset, length, ENC_NA); + break; + case MIMO_DL_BASIC_IE: + /* 8.4.5.3.8 MIMO_DL_Basic_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_mimo_dl_basic, tvb, offset, length, ENC_NA); + break; + case MIMO_DL_ENHANCED_IE: + /* 8.4.5.3.9 MIMO_DL_Enhanced_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_mimo_dl_enhanced, tvb, offset, length, ENC_NA); + break; + case HARQ_MAP_POINTER_IE: + /* 8.4.5.3.10 HARQ_Map_Pointer_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_harq_map_pointer, tvb, offset, length, ENC_NA); + break; + case PHYMOD_DL_IE: + /* 8.4.5.3.11 PHYMOD_DL_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_phymod_dl, tvb, offset, length, ENC_NA); + break; + case DL_PUSC_BURST_ALLOCATION_IN_OTHER_SEGMENT_IE: + /* 8.4.5.3.13 DL PUSC Burst Allocation in Other Segment IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_dl_pusc_burst_allocation, tvb, offset, length, ENC_NA); + break; + case UL_INTERFERENCE_AND_NOISE_LEVEL_IE: + /* 8.4.5.3.19 UL_interference_and_noise_level_IE */ + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_ul_interference_and_noise_level, tvb, offset, length, ENC_NA); + break; + default: + proto_tree_add_item(tree, hf_extended_diuc_dependent_ie_unknown_diuc, tvb, offset, length, ENC_NA); + break; + } + } + return ((length + 1) * 2 ); /* length in nibbles */ + +} + +/* Register Wimax Compact DL-MAP IE Protocol */ +void wimax_proto_register_wimax_compact_dlmap_ie(void) +{ + /* Compact DL-MAP IE display */ + static hf_register_info hf_compact_dlmap[] = + { + { + &hf_cdlmap_dl_map_type, + {"DL-MAP Type", "wmx.compact_dlmap.dl_map_type", FT_UINT8, BASE_DEC, NULL, DL_MAP_TYPE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_dl_map_type_1, + {"DL-MAP Type", "wmx.compact_dlmap.dl_map_type", FT_UINT8, BASE_DEC, NULL, DL_MAP_TYPE_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_ul_map_append, + {"UL-MAP Append", "wmx.compact_dlmap.ul_map_append", FT_UINT8, BASE_HEX, NULL, UL_MAP_APPEND_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_ul_map_append_1, + {"UL-MAP Append", "wmx.compact_dlmap.ul_map_append", FT_UINT8, BASE_HEX, NULL, UL_MAP_APPEND_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_reserved, + {"Reserved", "wmx.compact_dlmap.reserved", FT_UINT8, BASE_HEX, NULL, UL_MAP_APPEND_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_reserved_1, + {"Reserved", "wmx.compact_dlmap.reserved", FT_UINT8, BASE_HEX, NULL, UL_MAP_APPEND_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_nep_code, + {"Nep Code", "wmx.compact_dlmap.nep_code", FT_UINT8, BASE_HEX, NULL, MSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_nep_code_1, + {"Nep Code", "wmx.compact_dlmap.nep_code", FT_UINT8, BASE_HEX, NULL, LSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_nsch_code, + {"Nsch Code", "wmx.compact_dlmap.nsch_code", FT_UINT8, BASE_HEX, NULL, MSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_nsch_code_1, + {"Nsch Code", "wmx.compact_dlmap.nsch_code", FT_UINT8, BASE_HEX, NULL, LSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_num_bands, + {"Number Of Bands", "wmx.compact_dlmap.num_bands", FT_UINT8, BASE_HEX, NULL, MSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_num_bands_1, + {"Number Of Bands", "wmx.compact_dlmap.num_bands", FT_UINT8, BASE_HEX, NULL, LSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_band_index, + {"Band Index", "wmx.compact_dlmap.band_index", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#if 0 + { + &hf_cdlmap_band_index_1, + {"Band Index", "wmx.compact_dlmap.band_index", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif + { + &hf_cdlmap_nb_bitmap, + {"Number Of Bits For Band BITMAP", "wmx.compact_dlmap.nb_bitmap", FT_UINT8, BASE_HEX, NULL, MSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_nb_bitmap_1, + {"Number Of Bits For Band BITMAP", "wmx.compact_dlmap.nb_bitmap", FT_UINT8, BASE_HEX, NULL, LSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_shortened_uiuc, + {"Shortened UIUC", "wmx.compact_dlmap.shortened_uiuc", FT_UINT8, BASE_HEX, NULL, SHORTENED_DIUC_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_shortened_uiuc_1, + {"Shortened UIUC", "wmx.compact_dlmap.shortened_uiuc", FT_UINT16, BASE_HEX, NULL, SHORTENED_DIUC_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_shortened_diuc, + {"Shortened DIUC", "wmx.compact_dlmap.shortened_diuc", FT_UINT8, BASE_HEX, NULL, SHORTENED_DIUC_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_shortened_diuc_1, + {"Shortened DIUC", "wmx.compact_dlmap.shortened_diuc", FT_UINT16, BASE_HEX, NULL, SHORTENED_DIUC_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_companded_sc, + {"Companded SC", "wmx.compact_dlmap.companded_sc", FT_UINT8, BASE_HEX, NULL, COMPANDED_SC_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_companded_sc_1, + {"Companded SC", "wmx.compact_dlmap.companded_sc", FT_UINT16, BASE_HEX, NULL, COMPANDED_SC_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_bin_offset, + {"BIN Offset", "wmx.compact_dlmap.bin_offset", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cdlmap_bin_offset_1, + {"BIN Offset", "wmx.compact_dlmap.bin_offset", FT_UINT16, BASE_HEX, NULL, 0x0FF0, NULL, HFILL} + }, + { + &hf_cdlmap_diuc_num_of_subchannels, + {"Number Of Subchannels", "wmx.compact_dlmap.diuc_num_of_subchannels", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cdlmap_diuc_num_of_subchannels_1, + {"Number Of Subchannels", "wmx.compact_dlmap.diuc_num_of_subchannels", FT_UINT16, BASE_DEC, NULL, 0x0FF0, NULL, HFILL} + }, + { + &hf_cdlmap_diuc_repetition_coding_indication, + {"Repetition Coding Indication", "wmx.compact_dlmap.diuc_repetition_coding_indication", FT_UINT8, BASE_DEC, VALS(rep_msgs), 0xC0, NULL, HFILL} + }, + { + &hf_cdlmap_diuc_repetition_coding_indication_1, + {"Repetition Coding Indication", "wmx.compact_dlmap.diuc_repetition_coding_indication", FT_UINT8, BASE_DEC, VALS(rep_msgs), 0x0C, NULL, HFILL} + }, + { + &hf_cdlmap_diuc_reserved, + {"Reserved", "wmx.compact_dlmap.diuc_reserved", FT_UINT8, BASE_HEX, NULL, 0x30, NULL, HFILL} + }, + { + &hf_cdlmap_diuc_reserved_1, + {"Reserved", "wmx.compact_dlmap.diuc_reserved", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL} + }, + { + &hf_cdlmap_bit_map_length, + {"BIT MAP Length", "wmx.compact_dlmap.bit_map_length", FT_UINT8, BASE_DEC, NULL, MSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_bit_map_length_1, + {"BIT MAP Length", "wmx.compact_dlmap.bit_map_length", FT_UINT8, BASE_DEC, NULL, LSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_bit_map, + {"BIT MAP", "wmx.compact_dlmap.bit_map", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cdlmap_diuc, + {"DIUC", "wmx.compact_dlmap.diuc", FT_UINT8, BASE_HEX, NULL, MSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_diuc_1, + {"DIUC", "wmx.compact_dlmap.diuc", FT_UINT8, BASE_HEX, NULL, LSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_allocation_mode, + {"Allocation Mode", "wmx.compact_dlmap.allocation_mode", FT_UINT8, BASE_DEC, VALS(vals_allocation_modes), 0xC0, NULL, HFILL} + }, + { + &hf_cdlmap_allocation_mode_1, + {"Allocation Mode", "wmx.compact_dlmap.allocation_mode", FT_UINT8, BASE_DEC, VALS(vals_allocation_modes), 0x0C, NULL, HFILL} + }, + { + &hf_cdlmap_allocation_mode_rsvd, + {"Reserved", "wmx.compact_dlmap.allocation_mode_rsvd", FT_UINT8, BASE_DEC, NULL, 0x30, NULL, HFILL} + }, + { + &hf_cdlmap_allocation_mode_rsvd_1, + {"Reserved", "wmx.compact_dlmap.allocation_mode_rsvd", FT_UINT8, BASE_DEC, NULL, 0x03, NULL, HFILL} + }, + { + &hf_cdlmap_num_subchannels, + {"Number Of Subchannels", "wmx.compact_dlmap.num_subchannels", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cdlmap_num_subchannels_1, + {"Number Of Subchannels", "wmx.compact_dlmap.num_subchannels", FT_UINT16, BASE_DEC, NULL, 0x0FF0, NULL, HFILL} + }, +#if 0 + { + &hf_cdlmap_reserved_type, + {"DL-MAP Reserved Type", "wmx.compact_dlmap.reserved_type", FT_UINT8, BASE_DEC, NULL, DL_MAP_TYPE_MASK, NULL, HFILL} + }, +#endif + { + &hf_cdlmap_reserved_type_1, + {"DL-MAP Reserved Type", "wmx.compact_dlmap.reserved_type", FT_UINT8, BASE_DEC, NULL, DL_MAP_TYPE_MASK_1, NULL, HFILL} + } + }; + + /* HARQ MAP Format Configuration IE display */ + static hf_register_info hf_format_config[] = + { + { + &hf_format_config_ie_dl_map_type, + {"DL-MAP Type", "wmx.format_config_ie.dl_map_type", FT_UINT8, BASE_DEC, NULL, DL_MAP_TYPE_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_dl_map_type_1, + {"DL-MAP Type", "wmx.format_config_ie.dl_map_type", FT_UINT8, BASE_DEC, NULL, DL_MAP_TYPE_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_dl_map_type_32, + {"DL-MAP Type", "wmx.format_config_ie.dl_map_type", FT_UINT32, BASE_DEC, NULL, FORMAT_CONFIG_IE_DL_MAP_TYPE_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_new_format_indication, + {"New Format Indication", "wmx.format_config_ie.new_format_indication", FT_BOOLEAN, 8, TFS(&tfs_indication), UL_MAP_APPEND_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_new_format_indication_1, + {"New Format Indication", "wmx.format_config_ie.new_format_indication", FT_BOOLEAN, 8, TFS(&tfs_indication), UL_MAP_APPEND_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_new_format_indication_32, + {"New Format Indication", "wmx.format_config_ie.new_format_indication", FT_BOOLEAN, 32, TFS(&tfs_indication), FORMAT_CONFIG_IE_NEW_FORMAT_IND_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_cid_type, + {"HARQ MAP Indicator", "wmx.harq_map.format_config_ie.indicator", FT_UINT32, BASE_HEX, VALS(vals_cid_types), CID_TYPE_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_cid_type_1, + {"CID Type", "wmx.harq_map.format_config_ie.cid_type", FT_UINT32, BASE_HEX, VALS(vals_cid_types), CID_TYPE_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_safety_pattern, + {"Safety Pattern", "wmx.harq_map.format_config_ie.safety_pattern", FT_UINT32, BASE_HEX, NULL, SAFETY_PATTERN_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_safety_pattern_1, + {"Safety Pattern", "wmx.harq_map.format_config_ie.safety_pattern", FT_UINT32, BASE_HEX, NULL, SAFETY_PATTERN_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_subchannel_type, + {"Subchannel Type For Band AMC", "wmx.harq_map.format_config_ie.subchannel_type", FT_UINT32, BASE_HEX, VALS(vals_subchannel_types), BAND_AMC_SUBCHANNEL_TYPE_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_subchannel_type_1, + {"Subchannel Type For Band AMC", "wmx.harq_map.format_config_ie.subchannel_type", FT_UINT32, BASE_HEX, VALS(vals_subchannel_types), BAND_AMC_SUBCHANNEL_TYPE_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_max_logical_bands, + {"Max Logical Bands", "wmx.harq_map.format_config_ie.max_logical_bands", FT_UINT32, BASE_HEX, VALS(vals_max_logical_bands), MAX_LOGICAL_BANDS_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_max_logical_bands_1, + {"Max Logical Bands", "wmx.harq_map.format_config_ie.max_logical_bands", FT_UINT32, BASE_HEX, VALS(vals_max_logical_bands), MAX_LOGICAL_BANDS_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_num_of_broadcast_symbol, + {"Number Of Symbols for Broadcast", "wmx.harq_map.format_config_ie.num_of_broadcast_symbol", FT_UINT32, BASE_HEX, NULL, NUM_BROADCAST_SYMBOLS_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_num_of_broadcast_symbol_1, + {"Number Of Symbols for Broadcast", "wmx.harq_map.num_of_broadcast_symbol", FT_UINT32, BASE_HEX, NULL, NUM_BROADCAST_SYMBOLS_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_num_of_dl_band_amc_symbol, + {"Number Of Symbols for Broadcast", "wmx.harq_map.format_config_ie.num_of_dl_band_amc_symbol", FT_UINT32, BASE_HEX, NULL, NUM_DL_AMC_SYMBOLS_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_num_of_dl_band_amc_symbol_1, + {"Number Of Symbols for Broadcast", "wmx.harq_map.num_of_dl_band_amc_symbol", FT_UINT32, BASE_HEX, NULL, NUM_DL_AMC_SYMBOLS_MASK_1, NULL, HFILL} + }, + { + &hf_format_config_ie_num_of_ul_band_amc_symbol, + {"Number Of Symbols for Broadcast", "wmx.harq_map.format_config_ie.num_of_ul_band_amc_symbol", FT_UINT32, BASE_HEX, NULL, NUM_UL_AMC_SYMBOLS_MASK, NULL, HFILL} + }, + { + &hf_format_config_ie_num_of_ul_band_amc_symbol_1, + {"Number Of Symbols for Broadcast", "wmx.harq_map.num_of_ul_band_amc_symbol", FT_UINT32, BASE_HEX, NULL, NUM_UL_AMC_SYMBOLS_MASK_1, NULL, HFILL} + } + }; + + /* HARQ MAP Reduced CID IE display */ + static hf_register_info hf_rcid[] = + { + { + &hf_harq_rcid_ie_normal_cid, + {"Normal CID", "wmx.harq_map.rcid_ie.normal_cid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_normal_cid_1, + {"Normal CID", "wmx.harq_map.rcid_ie.normal_cid", FT_UINT24, BASE_HEX, NULL, WIMAX_RCID_IE_NORMAL_CID_MASK_1, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_prefix, + {"Prefix", "wmx.harq_map.rcid_ie.prefix", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_PREFIX_MASK, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_prefix_1, + {"Prefix", "wmx.harq_map.rcid_ie.prefix", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_PREFIX_MASK_1, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_cid3, + {"3 LSB Of Basic CID", "wmx.harq_map.rcid_ie.cid3", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_CID3_MASK, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_cid3_1, + {"3 LSB Of Basic CID", "wmx.harq_map.rcid_ie.cid3", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_CID3_MASK_1, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_cid7, + {"7 LSB Of Basic CID", "wmx.harq_map.rcid_ie.cid7", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_CID7_MASK, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_cid7_1, + {"7 LSB Of Basic CID", "wmx.harq_map.rcid_ie.cid7", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_CID7_MASK_1, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_cid11, + {"11 LSB Of Basic CID", "wmx.harq_map.rcid_ie.cid11", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_CID11_MASK, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_cid11_1, + {"11 LSB Of Basic CID", "wmx.harq_map.rcid_ie.cid11", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_CID11_MASK_1, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_cid11_2, + {"11 LSB Of Multicast, AAS or Broadcast CID", "wmx.harq_map.rcid_ie.cid11", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_CID11_MASK, NULL, HFILL} + }, + { + &hf_harq_rcid_ie_cid11_3, + {"11 LSB Of Multicast, AAS or Broadcast CID", "wmx.harq_map.rcid_ie.cid11", FT_UINT16, BASE_HEX, NULL, WIMAX_RCID_IE_CID11_MASK_1, NULL, HFILL} + } + }; + + /* HARQ MAP HARQ Control IE display */ + static hf_register_info hf_harq_control[] = + { + { + &hf_harq_control_ie_prefix, + {"Prefix", "wmx.harq_map.harq_control_ie.prefix", FT_BOOLEAN, 8, TFS(&tfs_prefix), WIMAX_HARQ_CONTROL_IE_PREFIX_MASK, NULL, HFILL} + }, + { + &hf_harq_control_ie_ai_sn, + {"HARQ ID Sequence Number(AI_SN)", "wmx.harq_map.harq_control_ie.ai_sn", FT_UINT8, BASE_HEX, NULL, WIMAX_HARQ_CONTROL_IE_AI_SN_MASK, NULL, HFILL} + }, + { + &hf_harq_control_ie_spid, + {"Subpacket ID (SPID)", "wmx.harq_map.harq_control_ie.spid", FT_UINT8, BASE_HEX, NULL, WIMAX_HARQ_CONTROL_IE_SPID_MASK, NULL, HFILL} + }, + { + &hf_harq_control_ie_acid, + {"HARQ CH ID (ACID)", "wmx.harq_map.harq_control_ie.acid", FT_UINT8, BASE_HEX, NULL, WIMAX_HARQ_CONTROL_IE_ACID_MASK, NULL, HFILL} + }, + { + &hf_harq_control_ie_reserved, + {"Reserved", "wmx.harq_map.harq_control_ie.reserved", FT_UINT8, BASE_HEX, NULL, WIMAX_HARQ_CONTROL_IE_RESERVED_MASK, NULL, HFILL} + }, + { + &hf_harq_control_ie_prefix_1, + {"Prefix", "wmx.harq_map.harq_control_ie.prefix", FT_BOOLEAN, 16, TFS(&tfs_prefix), WIMAX_HARQ_CONTROL_IE_PREFIX_MASK_1, NULL, HFILL} + }, + { + &hf_harq_control_ie_ai_sn_1, + {"HARQ ID Sequence Number(AI_SN)", "wmx.harq_map.harq_control_ie.ai_sn", FT_UINT16, BASE_HEX, NULL, WIMAX_HARQ_CONTROL_IE_AI_SN_MASK_1, NULL, HFILL} + }, + { + &hf_harq_control_ie_spid_1, + {"Subpacket ID (SPID)", "wmx.harq_map.harq_control_ie.spid", FT_UINT16, BASE_HEX, NULL, WIMAX_HARQ_CONTROL_IE_SPID_MASK_1, NULL, HFILL} + }, + { + &hf_harq_control_ie_acid_1, + {"HARQ CH ID (ACID)", "wmx.harq_map.harq_control_ie.acid", FT_UINT16, BASE_HEX, NULL, WIMAX_HARQ_CONTROL_IE_ACID_MASK_1, NULL, HFILL} + }, + { + &hf_harq_control_ie_reserved_1, + {"Reserved", "wmx.harq_map.harq_control_ie.reserved", FT_UINT16, BASE_HEX, NULL, WIMAX_HARQ_CONTROL_IE_RESERVED_MASK_1, NULL, HFILL} + } + }; + + /* HARQ MAP CQICH Control IE display */ + static hf_register_info hf_cqich_control[] = + { + { + &hf_cqich_control_ie_indicator, + {"CQICH Indicator", "wmx.harq_map.cqich_control_ie.cqich_indicator", FT_BOOLEAN, 16, TFS(&tfs_cqich_ind), WIMAX_CQICH_CONTROL_IE_INDICATOR_MASK, NULL, HFILL} + }, + { + &hf_cqich_control_ie_alloc_id, + {"Allocation Index", "wmx.harq_map.cqich_control_ie.alloc_id", FT_UINT16, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_ALLOCATION_INDEX_MASK, NULL, HFILL} + }, + { + &hf_cqich_control_ie_period, + {"PERIOD", "wmx.harq_map.cqich_control_ie.period", FT_UINT16, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_PERIOD_MASK, NULL, HFILL} + }, + { + &hf_cqich_control_ie_frame_offset, + {"Frame Offset", "wmx.harq_map.cqich_control_ie.frame_offset", FT_UINT16, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_FRAME_OFFSET_MASK, NULL, HFILL} + }, + { + &hf_cqich_control_ie_duration, + {"Duration", "wmx.harq_map.cqich_control_ie.duration", FT_UINT16, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_DURATION_MASK, NULL, HFILL} + }, + { + &hf_cqich_control_ie_cqi_rep_threshold, + {"CQI Reporting Threshold", "wmx.harq_map.cqich_control_ie.cqi_rep_threshold", FT_UINT16, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_CQI_REP_THRESHOLD_MASK, NULL, HFILL} + }, + { + &hf_cqich_control_ie_indicator_1, + {"CQICH Indicator", "wmx.harq_map.cqich_control_ie.cqich_indicator", FT_BOOLEAN, 24, TFS(&tfs_cqich_ind), WIMAX_CQICH_CONTROL_IE_INDICATOR_MASK_1, NULL, HFILL} + }, + { + &hf_cqich_control_ie_alloc_id_1, + {"Allocation Index", "wmx.harq_map.cqich_control_ie.alloc_id", FT_UINT24, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_ALLOCATION_INDEX_MASK_1, NULL, HFILL} + }, + { + &hf_cqich_control_ie_period_1, + {"PERIOD", "wmx.harq_map.cqich_control_ie.period", FT_UINT24, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_PERIOD_MASK_1, NULL, HFILL} + }, + { + &hf_cqich_control_ie_frame_offset_1, + {"Frame Offset", "wmx.harq_map.cqich_control_ie.frame_offset", FT_UINT24, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_FRAME_OFFSET_MASK_1, NULL, HFILL} + }, + { + &hf_cqich_control_ie_duration_1, + {"Duration", "wmx.harq_map.cqich_control_ie.duration", FT_UINT24, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_DURATION_MASK_1, NULL, HFILL} + }, + { + &hf_cqich_control_ie_cqi_rep_threshold_1, + {"CQI Reporting Threshold", "wmx.harq_map.cqich_control_ie.cqi_rep_threshold", FT_UINT24, BASE_HEX, NULL, WIMAX_CQICH_CONTROL_IE_CQI_REP_THRESHOLD_MASK_1, NULL, HFILL} + } + }; + + static hf_register_info hf_extension_type[] = + { + { + &hf_cdlmap_extension_type, + {"DL-MAP Type", "wmx.extension_type.dl_map_type", FT_UINT16, BASE_DEC, NULL, EXTENSION_TYPE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_extension_type_1, + {"DL-MAP Type", "wmx.extension_type.dl_map_type", FT_UINT16, BASE_DEC, NULL, EXTENSION_TYPE_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_extension_subtype, + {"Extension Subtype", "wmx.extension_type.subtype", FT_UINT16, BASE_DEC, NULL, EXTENSION_SUBTYPE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_extension_subtype_1, + {"Extension Subtype", "wmx.extension_type.subtype", FT_UINT16, BASE_DEC, NULL, EXTENSION_SUBTYPE_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_extension_length, + {"Extension Length", "wmx.extension_type.length", FT_UINT16, BASE_DEC, NULL, EXTENSION_LENGTH_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_extension_length_1, + {"Extension Length", "wmx.extension_type.length", FT_UINT16, BASE_DEC, NULL, EXTENSION_LENGTH_MASK_1, NULL, HFILL} + }, + { + &hf_cdlmap_extension_time_diversity_mbs, + {"Time Diversity MBS", "wmx.extension_type.time_diversity_mbs", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cdlmap_extension_time_diversity_mbs_1, + {"Time Diversity MBS", "wmx.extension_type.time_diversity_mbs", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cdlmap_extension_harq_mode_1, + {"HARQ Mode Switch", "wmx.extension_type.harq_mode", FT_UINT16, BASE_HEX, NULL, 0x000F, NULL, HFILL} + }, + { + &hf_cdlmap_extension_harq_mode, + {"HARQ Mode Switch", "wmx.extension_type.harq_mode", FT_UINT8, BASE_HEX, NULL, MSB_NIBBLE_MASK, NULL, HFILL} + }, + { + &hf_cdlmap_extension_unknown_sub_type, + {"Unknown Extension Subtype", "wmx.extension_type.unknown_sub_type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cdlmap_extension_unknown_sub_type_1, + {"Unknown Extension Subtype", "wmx.extension_type.unknown_sub_type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + } + }; + + /* Extended DIUC dependent IE */ + static hf_register_info hf_extended_diuc[] = + { + { + &hf_extended_diuc_dependent_ie_diuc, + {"Extended DIUC", "wmx.extended_diuc_dependent_ie.diuc", FT_UINT8, BASE_HEX, NULL, MSB_NIBBLE_MASK, NULL, HFILL } + }, + { + &hf_extended_diuc_dependent_ie_diuc_1, + {"Extended DIUC", "wmx.extended_diuc_dependent_ie.diuc", FT_UINT8, BASE_HEX, NULL, LSB_NIBBLE_MASK, NULL, HFILL } + }, + { + &hf_extended_diuc_dependent_ie_length, + {"Length", "wmx.extended_diuc_dependent_ie.length", FT_UINT8, BASE_DEC, NULL, MSB_NIBBLE_MASK, NULL, HFILL } + }, + { + &hf_extended_diuc_dependent_ie_length_1, + {"Length", "wmx.extended_diuc_dependent_ie.length", FT_UINT8, BASE_DEC, NULL, LSB_NIBBLE_MASK, NULL, HFILL } + }, + { /* 8.4.5.3.? Channel_Measurement_IE */ + &hf_extended_diuc_dependent_ie_channel_measurement, + {"Channel_Measurement_IE (not implemented)", "wmx.extended_diuc_dependent_ie.channel_measurement", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.4 STC_Zone_IE */ + &hf_extended_diuc_dependent_ie_stc_zone, + {"STC_Zone_IE (not implemented)", "wmx.extended_diuc_dependent_ie.stc_zone", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.3 AAS_DL_IE */ + &hf_extended_diuc_dependent_ie_aas_dl, + {"AAS_DL_IE (not implemented)", "wmx.extended_diuc_dependent_ie.aas_dl", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.6 Data_location_in_another_BS_IE */ + &hf_extended_diuc_dependent_ie_data_location, + {"Data_location_in_another_BS_IE (not implemented)", "wmx.extended_diuc_dependent_ie.data_location", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.7 CID_Switch_IE */ + &hf_extended_diuc_dependent_ie_cid_switch, + {"CID_Switch_IE (not implemented)", "wmx.extended_diuc_dependent_ie.cid_switch", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + + { /* 8.4.5.3.8 MIMO_DL_Basic_IE */ + &hf_extended_diuc_dependent_ie_mimo_dl_basic, + {"MIMO_DL_Basic_IE (not implemented)", "wmx.extended_diuc_dependent_ie.mimo_dl_basic", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.9 MIMO_DL_Enhanced_IE */ + &hf_extended_diuc_dependent_ie_mimo_dl_enhanced, + {"MIMO_DL_Enhanced_IE (not implemented)", "wmx.extended_diuc_dependent_ie.mimo_dl_enhanced", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.10 HARQ_Map_Pointer_IE */ + &hf_extended_diuc_dependent_ie_harq_map_pointer, + {"HARQ_Map_Pointer_IE (not implemented)", "wmx.extended_diuc_dependent_ie.harq_map_pointer", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.11 PHYMOD_DL_IE */ + &hf_extended_diuc_dependent_ie_phymod_dl, + {"PHYMOD_DL_IE (not implemented)", "wmx.extended_diuc_dependent_ie.phymod_dl", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.13 DL PUSC Burst Allocation in Other Segment IE */ + &hf_extended_diuc_dependent_ie_dl_pusc_burst_allocation, + {"DL_PUSC_Burst_Allocation_in_Other_Segment_IE (not implemented)", "wmx.extended_diuc_dependent_ie.dl_pusc_burst_allocation", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* 8.4.5.3.19 UL_interference_and_noise_level_IE */ + &hf_extended_diuc_dependent_ie_ul_interference_and_noise_level, + {"UL_interference_and_noise_level_IE (not implemented)", "wmx.extended_diuc_dependent_ie.ul_interference_and_noise_level", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + }, + { /* unknown DIUC */ + &hf_extended_diuc_dependent_ie_unknown_diuc, + {"Unknown Extended DIUC", "wmx.extended_diuc_dependent_ie.unknown_diuc", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } + } + }; + +#if 0 /* Not used ?? */ + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_wimax_compact_dlmap_ie_decoder, + &ett_wimax_format_configuration_ie_decoder, + &ett_wimax_rcid_ie_decoder, + &ett_wimax_harq_control_ie_decoder, + &ett_wimax_extended_diuc_dependent_ie_decoder, + &ett_wimax_cqich_control_ie_decoder, + &ett_wimax_extension_type_ie_decoder, + }; + proto_register_subtree_array(ett, array_length(ett)); +#endif + + proto_wimax_compact_dlmap_ie_decoder = proto_wimax; + + proto_register_field_array(proto_wimax_compact_dlmap_ie_decoder, hf_compact_dlmap, array_length(hf_compact_dlmap)); + proto_register_field_array(proto_wimax_compact_dlmap_ie_decoder, hf_format_config, array_length(hf_format_config)); + proto_register_field_array(proto_wimax_compact_dlmap_ie_decoder, hf_rcid, array_length(hf_rcid)); + proto_register_field_array(proto_wimax_compact_dlmap_ie_decoder, hf_harq_control, array_length(hf_harq_control)); + proto_register_field_array(proto_wimax_compact_dlmap_ie_decoder, hf_cqich_control, array_length(hf_cqich_control)); + proto_register_field_array(proto_wimax_compact_dlmap_ie_decoder, hf_extension_type, array_length(hf_extension_type)); + proto_register_field_array(proto_wimax_compact_dlmap_ie_decoder, hf_extended_diuc, array_length(hf_extended_diuc)); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_compact_dlmap_ie_decoder.h b/plugins/epan/wimax/wimax_compact_dlmap_ie_decoder.h new file mode 100644 index 00000000..f91c8d23 --- /dev/null +++ b/plugins/epan/wimax/wimax_compact_dlmap_ie_decoder.h @@ -0,0 +1,20 @@ +/* wimax_compact_dlmap_ie_decoder.h + * Declarations of routines exported by WiMax HARQ Map Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef _WIMAX_COMPACT_DLMAP_IE_DECODER_H_ +#define _WIMAX_COMPACT_DLMAP_IE_DECODER_H_ + +extern guint wimax_compact_dlmap_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); + +#endif /* _WIMAX_COMPACT_DLMAP_IE_DECODER_H_ */ diff --git a/plugins/epan/wimax/wimax_compact_ulmap_ie_decoder.c b/plugins/epan/wimax/wimax_compact_ulmap_ie_decoder.c new file mode 100644 index 00000000..efa90abd --- /dev/null +++ b/plugins/epan/wimax/wimax_compact_ulmap_ie_decoder.c @@ -0,0 +1,2125 @@ +/* wimax_compact_ulmap_ie_decoder.c + * WiMax Compact UL-MAP IE decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax-int.h" +#include "wimax_compact_ulmap_ie_decoder.h" + +/* MASKs */ +#define MSB_NIBBLE_MASK 0xF0 +#define LSB_NIBBLE_MASK 0x0F + +#define CID_TYPE_NORMAL 0 +#define CID_TYPE_RCID11 1 +#define CID_TYPE_RCID7 2 +#define CID_TYPE_RCID3 3 + +/* Global Variables */ +extern guint cid_type; +extern guint band_amc_subchannel_type; +extern guint max_logical_bands; +extern guint num_of_broadcast_symbols; +extern guint num_of_dl_band_amc_symbols; +extern guint num_of_ul_band_amc_symbols; +extern guint harq_mode; +extern gint proto_wimax; + +/* forward reference */ +guint wimax_cdma_allocation_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +guint wimax_extended_uiuc_dependent_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +static guint wimax_compact_ulmap_rcid_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +static guint wimax_compact_ulmap_harq_control_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); +static guint wimax_culmap_extension_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); + +static gint proto_wimax_compact_ulmap_ie_decoder = -1; + +#if 0 /* not used ?? */ +static gint ett_wimax_compact_ulmap_ie_decoder = -1; +static gint ett_wimax_rcid_ie_decoder = -1; +static gint ett_wimax_harq_control_ie_decoder = -1; +static gint ett_wimax_extended_uiuc_dependent_ie_decoder = -1; +static gint ett_wimax_extension_type_ie_decoder = -1; +#endif + +/* Prefixes */ +static const true_false_string tfs_prefix = +{ + "Enable HARQ", + "Temporary Disable HARQ" +}; + +/* Region Changes */ +static const true_false_string tfs_region_change = +{ + "Region Changed", + "No Region Change" +}; + +/* Region Changes */ +static const true_false_string tfs_yes_no_ie = +{ + "Yes", + "No" +}; + +/* Repetition Coding Indications */ +static const value_string vals_repetitions[] = +{ + { 0, "No Repetition Coding" }, + { 1, "Repetition Coding of 2 Used" }, + { 2, "Repetition Coding of 4 Used" }, + { 3, "Repetition Coding of 6 Used" }, + { 0, NULL } +}; + +/* Allocation Modes */ +static const value_string vals_allocation_modes[] = +{ + { 0, "Same Number Of Subchannels For The Selected Bands" }, + { 1, "Different Same Number Of Subchannels For The Selected Bands" }, + { 2, "Total Number Of Subchannels For The Selected Bands Determined by Nsch Code and Nep Code" }, + { 3, "Reserved" }, + { 0, NULL } +}; + +/* CTypes */ +static const value_string vals_ctypes[] = +{ + { 0, "2 Mini-subchannels (defines M=2)" }, + { 1, "2 Mini-subchannels (defines M=2)" }, + { 2, "3 Mini-subchannels (defines M=3)" }, + { 3, "6 Mini-subchannels (defines M=6)" }, + { 0, NULL } +}; + +/* Masks */ +#define UL_MAP_TYPE_MASK 0xE0 +#define UL_MAP_RESERVED_MASK 0x10 +#define SHORTENED_UIUC_MASK 0xE0 +#define COMPANDED_SC_MASK 0x1F +#define UL_MAP_TYPE_MASK_1 0x0E +#define UL_MAP_RESERVED_MASK_1 0x01 +#define SHORTENED_UIUC_MASK_1 0x0E00 +#define COMPANDED_SC_MASK_1 0x01F0 +#define MIDDLE_BYTE_MASK 0x0FF0 + +#define ALLOCATION_MODE_MASK 0xC0 +#define ALLOCATION_MODE_MASK_1 0x0C + +/* display indexies */ +static gint hf_culmap_ul_map_type = -1; +static gint hf_culmap_reserved = -1; +static gint hf_culmap_nep_code = -1; +static gint hf_culmap_nsch_code = -1; +static gint hf_culmap_num_bands = -1; +static gint hf_culmap_band_index = -1; +static gint hf_culmap_nb_bitmap = -1; +static gint hf_culmap_ul_map_type_1 = -1; +static gint hf_culmap_reserved_1 = -1; +static gint hf_culmap_nep_code_1 = -1; +static gint hf_culmap_nsch_code_1 = -1; +static gint hf_culmap_num_bands_1 = -1; +/*static gint hf_culmap_band_index_1 = -1;*/ +static gint hf_culmap_nb_bitmap_1 = -1; + +static gint hf_culmap_shortened_uiuc = -1; +static gint hf_culmap_companded_sc = -1; +static gint hf_culmap_shortened_uiuc_1 = -1; +static gint hf_culmap_companded_sc_1 = -1; + +static gint hf_culmap_bin_offset = -1; +static gint hf_culmap_bin_offset_1 = -1; + +static gint hf_culmap_uiuc_ofdma_symbol_offset = -1; +static gint hf_culmap_uiuc_ofdma_symbol_offset_1 = -1; +static gint hf_culmap_uiuc_subchannel_offset_7 = -1; +static gint hf_culmap_uiuc_num_of_ofdma_symbols_7 = -1; +static gint hf_culmap_uiuc_num_of_subchannels_7 = -1; +static gint hf_culmap_uiuc_ranging_method = -1; +static gint hf_culmap_uiuc_reserved = -1; +static gint hf_culmap_uiuc_subchannel_offset_7_1 = -1; +static gint hf_culmap_uiuc_num_of_ofdma_symbols_7_1 = -1; +static gint hf_culmap_uiuc_num_of_subchannels_7_1 = -1; +static gint hf_culmap_uiuc_ranging_method_1 = -1; +static gint hf_culmap_uiuc_reserved_1 = -1; +static gint hf_culmap_uiuc_repetition_coding_indication = -1; +static gint hf_culmap_uiuc_repetition_coding_indication_1 = -1; +/* static gint hf_culmap_uiuc_reserved1 = -1; */ +/* static gint hf_culmap_uiuc_reserved11_1 = -1; */ +static gint hf_culmap_uiuc_subchannel_offset = -1; +static gint hf_culmap_uiuc_subchannel_offset_1 = -1; +static gint hf_culmap_uiuc_num_of_ofdma_symbols = -1; +static gint hf_culmap_uiuc_num_of_ofdma_symbols_1 = -1; +static gint hf_culmap_uiuc_num_of_subchannels = -1; +static gint hf_culmap_uiuc_num_of_subchannels_1 = -1; + +static gint hf_culmap_harq_region_change_indication = -1; +static gint hf_culmap_harq_region_change_indication_1 = -1; +static gint hf_culmap_cqi_region_change_indication = -1; +static gint hf_culmap_cqi_region_change_indication_1 = -1; + +static gint hf_culmap_uiuc = -1; +static gint hf_culmap_uiuc_1 = -1; + +static gint hf_culmap_allocation_mode = -1; +static gint hf_culmap_allocation_mode_rsvd = -1; +static gint hf_culmap_num_subchannels = -1; +static gint hf_culmap_allocation_mode_1 = -1; +static gint hf_culmap_allocation_mode_rsvd_1 = -1; +static gint hf_culmap_num_subchannels_1 = -1; + +/* static gint hf_culmap_reserved_type = -1; */ +static gint hf_culmap_reserved_type_1 = -1; + +/* display indexies */ +static gint hf_rcid_ie_prefix = -1; +static gint hf_rcid_ie_prefix_1 = -1; +static gint hf_rcid_ie_normal_cid = -1; +static gint hf_rcid_ie_normal_cid_1 = -1; +static gint hf_rcid_ie_cid3 = -1; +static gint hf_rcid_ie_cid3_1 = -1; +static gint hf_rcid_ie_cid7 = -1; +static gint hf_rcid_ie_cid7_1 = -1; +static gint hf_rcid_ie_cid11 = -1; +static gint hf_rcid_ie_cid11_1 = -1; +static gint hf_rcid_ie_cid11_2 = -1; +static gint hf_rcid_ie_cid11_3 = -1; + +/* Masks */ +#define WIMAX_RCID_IE_NORMAL_CID_MASK_1 0x0FFFF0 +#define WIMAX_RCID_IE_PREFIX_MASK 0x8000 +#define WIMAX_RCID_IE_PREFIX_MASK_1 0x0800 +#define WIMAX_RCID_IE_CID3_MASK 0x7000 +#define WIMAX_RCID_IE_CID3_MASK_1 0x0700 +#define WIMAX_RCID_IE_CID7_MASK 0x7F00 +#define WIMAX_RCID_IE_CID7_MASK_1 0x07F0 +#define WIMAX_RCID_IE_CID11_MASK 0x7FF0 +#define WIMAX_RCID_IE_CID11_MASK_1 0x07FF + +/* HARQ MAP HARQ Control IE display indexies */ +static gint hf_harq_control_ie_prefix = -1; +static gint hf_harq_control_ie_ai_sn = -1; +static gint hf_harq_control_ie_spid = -1; +static gint hf_harq_control_ie_acid = -1; +static gint hf_harq_control_ie_reserved = -1; +static gint hf_harq_control_ie_prefix_1 = -1; +static gint hf_harq_control_ie_ai_sn_1 = -1; +static gint hf_harq_control_ie_spid_1 = -1; +static gint hf_harq_control_ie_acid_1 = -1; +static gint hf_harq_control_ie_reserved_1 = -1; + +/* Masks */ +#define WIMAX_HARQ_CONTROL_IE_PREFIX_MASK 0x80 +#define WIMAX_HARQ_CONTROL_IE_AI_SN_MASK 0x40 +#define WIMAX_HARQ_CONTROL_IE_SPID_MASK 0x30 +#define WIMAX_HARQ_CONTROL_IE_ACID_MASK 0x0F +#define WIMAX_HARQ_CONTROL_IE_RESERVED_MASK 0x70 +#define WIMAX_HARQ_CONTROL_IE_PREFIX_MASK_1 0x0800 +#define WIMAX_HARQ_CONTROL_IE_AI_SN_MASK_1 0x0400 +#define WIMAX_HARQ_CONTROL_IE_SPID_MASK_1 0x0300 +#define WIMAX_HARQ_CONTROL_IE_ACID_MASK_1 0x00F0 +#define WIMAX_HARQ_CONTROL_IE_RESERVED_MASK_1 0x0700 + +/* Extension Type */ +#define EXTENSION_TYPE_MASK 0xE000 +#define EXTENSION_TYPE_MASK_1 0x0E00 +#define EXTENSION_SUBTYPE_MASK 0x1F00 +#define EXTENSION_SUBTYPE_MASK_1 0x01F0 +#define EXTENSION_LENGTH_MASK 0x00F0 +#define EXTENSION_LENGTH_MASK_1 0x000F + +static gint hf_culmap_extension_type = -1; +static gint hf_culmap_extension_subtype = -1; +static gint hf_culmap_extension_length = -1; +static gint hf_culmap_extension_type_1 = -1; +static gint hf_culmap_extension_subtype_1 = -1; +static gint hf_culmap_extension_length_1 = -1; + +/* static gint hf_culmap_extension_time_diversity_mbs = -1; */ +static gint hf_culmap_extension_harq_mode = -1; +static gint hf_culmap_extension_unknown_sub_type = -1; +/* static gint hf_culmap_extension_time_diversity_mbs_1 = -1; */ +static gint hf_culmap_extension_harq_mode_1 = -1; +static gint hf_culmap_extension_unknown_sub_type_1 = -1; + +/* UL-MAP CDMA Allocation IE */ +#define CDMA_ALLOCATION_DURATION_MASK 0xFC00 +#define CDMA_ALLOCATION_UIUC_MASK 0x03C0 +#define CDMA_ALLOCATION_REPETITION_CODE_MASK 0x0030 +#define CDMA_ALLOCATION_FRAME_NUMBER_INDEX_MASK 0x000F + +#define CDMA_ALLOCATION_RANGING_SUBCHANNEL_MASK 0xFE +#define CDMA_ALLOCATION_BW_REQUEST_MANDATORY_MASK 0x01 + +#define CDMA_ALLOCATION_DURATION_MASK_1 0x0FC0 +#define CDMA_ALLOCATION_UIUC_MASK_1 0x003C +#define CDMA_ALLOCATION_REPETITION_CODE_MASK_1 0x0003 +#define CDMA_ALLOCATION_FRAME_NUMBER_INDEX_MASK_1 0xF0000000 +#define CDMA_ALLOCATION_RANGING_CODE_MASK_1 0x0FF00000 +#define CDMA_ALLOCATION_RANGING_SYMBOL_MASK_1 0x000FF000 +#define CDMA_ALLOCATION_RANGING_SUBCHANNEL_MASK_1 0x00000FE0 +#define CDMA_ALLOCATION_BW_REQUEST_MANDATORY_MASK_1 0x00000010 + +static gint hf_cdma_allocation_duration = -1; +static gint hf_cdma_allocation_uiuc = -1; +static gint hf_cdma_allocation_repetition = -1; +static gint hf_cdma_allocation_frame_number_index = -1; +static gint hf_cdma_allocation_ranging_code = -1; +static gint hf_cdma_allocation_ranging_symbol = -1; +static gint hf_cdma_allocation_ranging_subchannel = -1; +static gint hf_cdma_allocation_bw_req = -1; +static gint hf_cdma_allocation_duration_1 = -1; +static gint hf_cdma_allocation_uiuc_1 = -1; +static gint hf_cdma_allocation_repetition_1 = -1; +static gint hf_cdma_allocation_frame_number_index_1 = -1; +static gint hf_cdma_allocation_ranging_code_1 = -1; +static gint hf_cdma_allocation_ranging_symbol_1 = -1; +static gint hf_cdma_allocation_ranging_subchannel_1 = -1; +static gint hf_cdma_allocation_bw_req_1 = -1; + +/* UL-MAP Extended UIUCs (table 290a) */ +#define MINI_SUBCHANNEL_CTYPE_MASK 0xC0 +#define MINI_SUBCHANNEL_CTYPE_MASK_16 0x0C00 +#define MINI_SUBCHANNEL_DURATION_MASK 0x3F +#define MINI_SUBCHANNEL_DURATION_MASK_16 0x03F0 +#define MINI_SUBCHANNEL_CID_MASK 0xFFFF00 +#define MINI_SUBCHANNEL_UIUC_MASK 0x0000F0 +#define MINI_SUBCHANNEL_REPETITION_MASK 0x00000C +#define MINI_SUBCHANNEL_CID_MASK_1 0x0FFFF000 +#define MINI_SUBCHANNEL_UIUC_MASK_1 0x00000F00 +#define MINI_SUBCHANNEL_REPETITION_MASK_1 0x000000C0 +#define MINI_SUBCHANNEL_CID_MASK_2 0x03FFFF00 +#define MINI_SUBCHANNEL_UIUC_MASK_2 0x000000F0 +#define MINI_SUBCHANNEL_REPETITION_MASK_2 0x0000000C +#define MINI_SUBCHANNEL_CID_MASK_3 0x3FFFF000 +#define MINI_SUBCHANNEL_UIUC_MASK_3 0x00000F00 +#define MINI_SUBCHANNEL_REPETITION_MASK_3 0x000000C0 +#define MINI_SUBCHANNEL_PADDING_MASK 0xF0 +#define MINI_SUBCHANNEL_PADDING_MASK_1 0x0000000F + +static gint hf_extended_uiuc_ie_uiuc = -1; +static gint hf_extended_uiuc_ie_length = -1; +static gint hf_extended_uiuc_ie_uiuc_1 = -1; +static gint hf_extended_uiuc_ie_length_1 = -1; +static gint hf_extended_uiuc_ie_power_control = -1; +static gint hf_extended_uiuc_ie_power_measurement_frame = -1; +static gint hf_extended_uiuc_ie_power_control_24 = -1; +static gint hf_extended_uiuc_ie_power_measurement_frame_24 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_ctype = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_duration = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_ctype_16 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_duration_16 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_cid = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_uiuc = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_repetition = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_padding = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_cid_1 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_uiuc_1 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_repetition_1 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_cid_2 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_uiuc_2 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_repetition_2 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_cid_3 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_uiuc_3 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_repetition_3 = -1; +static gint hf_extended_uiuc_ie_mini_subchannel_alloc_padding_1 = -1; +static gint hf_extended_uiuc_ie_aas_ul = -1; +static gint hf_extended_uiuc_ie_cqich_alloc = -1; +static gint hf_extended_uiuc_ie_ul_zone = -1; +static gint hf_extended_uiuc_ie_phymod_ul = -1; +static gint hf_extended_uiuc_ie_mimo_ul_basic = -1; +static gint hf_extended_uiuc_ie_fast_tracking = -1; +static gint hf_extended_uiuc_ie_ul_pusc_burst_allocation = -1; +static gint hf_extended_uiuc_ie_fast_ranging = -1; +static gint hf_extended_uiuc_ie_ul_allocation_start = -1; +static gint hf_extended_uiuc_ie_unknown_uiuc = -1; + + +/* Compact UL-MAP IE Types (table 90) */ +#define COMPACT_UL_MAP_TYPE_NORMAL_SUBCHANNEL 0 +#define COMPACT_UL_MAP_TYPE_BAND_AMC 1 +#define COMPACT_UL_MAP_TYPE_SAFETY 2 +#define COMPACT_UL_MAP_TYPE_UIUC 3 +#define COMPACT_UL_MAP_TYPE_HARQ_REGION_IE 4 +#define COMPACT_UL_MAP_TYPE_CQICH_REGION_IE 5 +#define COMPACT_UL_MAP_TYPE_RESERVED 6 +#define COMPACT_UL_MAP_TYPE_EXTENSION 7 + +/* Compact UL-MAP IE decoder */ +guint wimax_compact_ulmap_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint uiuc, byte, length = 0; + guint ul_map_type; + guint harq_region_change_indication; + guint cqi_region_change_indication; + guint ul_map_offset, nibble_length; + guint nband, band_count, i, allocation_mode; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Compact UL-MAP IEs"); +#endif + /* set the local offset */ + ul_map_offset = offset; + /* Get the first byte */ + byte = tvb_get_guint8(tvb, ul_map_offset); + /* get the ul-map type */ + if(nibble_offset & 1) + { + ul_map_type = ((byte & UL_MAP_TYPE_MASK_1) >> 1); + } + else + { + ul_map_type = ((byte & UL_MAP_TYPE_MASK) >> 5); + } + /* process the Compact UL-MAP IE (table 90) */ + switch (ul_map_type) + { + case COMPACT_UL_MAP_TYPE_NORMAL_SUBCHANNEL:/* 6.3.2.3.43.7.1 */ + /* display the UL-MAP type and reserved bit */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_ul_map_type_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_culmap_reserved_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + nibble_offset = 0; + } + else + { + proto_tree_add_item(tree, hf_culmap_ul_map_type, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_culmap_reserved, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length = 1; + /* decode RCID IE */ + nibble_length = wimax_compact_ulmap_rcid_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset); + length += nibble_length; + ul_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + /* check harq mode */ + if(!harq_mode) + { /* display the Nep and Nsch Code */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_nep_code_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + proto_tree_add_item(tree, hf_culmap_nsch_code, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_culmap_nep_code, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_nsch_code_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + } + length += 2; + } + else if(harq_mode == 1) + { /* display the Shortened UIUC and Companded SC */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_shortened_uiuc_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_companded_sc_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_culmap_shortened_uiuc, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_companded_sc, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + /* move to next byte */ + ul_map_offset++; + length += 2; + } + /* decode HARQ Control IE */ + nibble_length = wimax_compact_ulmap_harq_control_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset); + length += nibble_length; + break; + case COMPACT_UL_MAP_TYPE_BAND_AMC:/* 6.3.2.3.43.7.2 */ + /* display the UL-MAP type and reserved bit */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_ul_map_type_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_culmap_reserved_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + nibble_offset = 0; + } + else + { + proto_tree_add_item(tree, hf_culmap_ul_map_type, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_culmap_reserved, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length = 1; + /* decode RCID IE */ + nibble_length = wimax_compact_ulmap_rcid_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset); + length += nibble_length; + ul_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + /* check harq mode */ + if(!harq_mode) + { /* display the Nep and Nsch Code */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_nep_code_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + proto_tree_add_item(tree, hf_culmap_nsch_code, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_culmap_nep_code, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_nsch_code_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + } + length += 2; + } + else if(harq_mode == 1) + { /* display the Shortened UIUC and Companded SC */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_shortened_uiuc_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_companded_sc_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_culmap_shortened_uiuc, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_companded_sc, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + /* move to next byte */ + ul_map_offset++; + length += 2; + } + /* get the Nband */ + if(max_logical_bands) + { /* get and display the Nband */ + nband = tvb_get_guint8(tvb, ul_map_offset); + length++; + if(nibble_offset & 1) + { + nband = (nband & LSB_NIBBLE_MASK); + /* display the Nband */ + proto_tree_add_item(tree, hf_culmap_num_bands_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + nibble_offset = 0; + if(max_logical_bands == 3) + { + proto_tree_add_item(tree, hf_culmap_band_index, tvb, ul_map_offset, nband, ENC_NA); + length += (nband * 2); + /* update offset */ + ul_map_offset += nband; + } + else + { + nibble_offset = (nband & 1); + proto_tree_add_item(tree, hf_culmap_band_index, tvb, ul_map_offset, ((nband >> 1) + nibble_offset), ENC_NA); + length += nband; + /* update offset */ + ul_map_offset += (nband >> 1); + } + } + else + { + nband = ((nband & MSB_NIBBLE_MASK) >> 4); + /* display the Nband */ + proto_tree_add_item(tree, hf_culmap_num_bands, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + if(max_logical_bands == 3) + { + proto_tree_add_item(tree, hf_culmap_band_index, tvb, ul_map_offset, (nband + nibble_offset), ENC_NA); + length += (nband * 2); + /* update offset */ + ul_map_offset += nband; + } + else + { + proto_tree_add_item(tree, hf_culmap_band_index, tvb, ul_map_offset, ((nband >> 1) + nibble_offset), ENC_NA); + length += nband; + /* update offset */ + ul_map_offset += ((nband + nibble_offset) >> 1); + if(nband & 1) + nibble_offset = 0; + } + } + band_count = nband; + } + else + { + band_count = 1; + /* display the Nb-BITMAP */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_nb_bitmap_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + nibble_offset = 0; + } + else + { + proto_tree_add_item(tree, hf_culmap_nb_bitmap, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length++; + } + /* Get the Allocation Mode */ + byte = tvb_get_guint8(tvb, ul_map_offset); + if(nibble_offset & 1) + { + allocation_mode = ((byte & ALLOCATION_MODE_MASK_1) >> 2); + proto_tree_add_item(tree, hf_culmap_allocation_mode_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_allocation_mode_rsvd_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 0; + ul_map_offset++; + } + else + { + allocation_mode = ((byte & ALLOCATION_MODE_MASK) >> 6); + proto_tree_add_item(tree, hf_culmap_allocation_mode, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_allocation_mode_rsvd, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length++; + /* Decode Allocation Mode - need to be done */ + if(!allocation_mode) + { + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_num_subchannels_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_culmap_num_subchannels, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + ul_map_offset++; + length += 2; + } + else if(allocation_mode == 1) + { + for(i=0; i> 1); + nibble_offset = (nibble_length & 1); + /* check harq mode */ + if(!harq_mode) + { /* display the Nep and Nsch Code */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_nep_code_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + proto_tree_add_item(tree, hf_culmap_nsch_code, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_culmap_nep_code, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_nsch_code_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + } + length += 2; + } + else if(harq_mode == 1) + { /* display the Shortened UIUC and Companded SC */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_shortened_uiuc_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_companded_sc_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tree, hf_culmap_shortened_uiuc, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_companded_sc, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + /* move to next byte */ + ul_map_offset++; + length += 2; + } + /* display BIN offset */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_bin_offset_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + } + else + { + proto_tree_add_item(tree, hf_culmap_bin_offset, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + } + length += 2; + /* decode HARQ Control IE */ + nibble_length = wimax_compact_ulmap_harq_control_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset); + length += nibble_length; + break; + case COMPACT_UL_MAP_TYPE_UIUC:/* 6.3.2.3.43.7.4 */ + /* display the UL-MAP type and reserved bit */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_ul_map_type_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_culmap_reserved_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + ul_map_offset++; + /* get the new byte */ + byte = tvb_get_guint8(tvb, ul_map_offset); + /* get the UIUC */ + uiuc = ((byte & MSB_NIBBLE_MASK) >> 4); + /* display the UIUC */ + proto_tree_add_item(tree, hf_culmap_uiuc, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + else + { + /* display the UL-MAP type */ + proto_tree_add_item(tree, hf_culmap_ul_map_type, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_culmap_reserved, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* get the UIUC */ + uiuc = (byte & LSB_NIBBLE_MASK); + /* display the UIUC */ + proto_tree_add_item(tree, hf_culmap_uiuc_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + } + length = 2; + /* decode RCID IE */ + nibble_length = wimax_compact_ulmap_rcid_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset); + length += nibble_length; + ul_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + if(uiuc == 15) + { /* Extended UIUC dependent IE */ + nibble_length = wimax_extended_uiuc_dependent_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset); + length += nibble_length; + ul_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + } + else if(uiuc == 14) + { /* CDMA Allocation IE */ + nibble_length = wimax_cdma_allocation_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset); + length += nibble_length; + ul_map_offset += (nibble_length >> 1); + nibble_offset = (nibble_length & 1); + } + else if(uiuc == 12) + { + if(nibble_offset & 1) + { + /* display the OFDMA symbol offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_ofdma_symbol_offset_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the subchannel offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_subchannel_offset_7_1, tvb, ul_map_offset, 4, ENC_BIG_ENDIAN); + /* display the number of OFDMA symbols */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_ofdma_symbols_7_1, tvb, ul_map_offset, 4, ENC_BIG_ENDIAN); + /* display the number of subchannels */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_subchannels_7_1, tvb, ul_map_offset, 4, ENC_BIG_ENDIAN); + /* display the ranging method */ + proto_tree_add_item(tree, hf_culmap_uiuc_ranging_method_1, tvb, ul_map_offset, 4, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_culmap_uiuc_reserved_1, tvb, ul_map_offset, 4, ENC_BIG_ENDIAN); + ul_map_offset += 3; + } + else + { /* display the OFDMA symbol offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_ofdma_symbol_offset, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the subchannel offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_subchannel_offset_7, tvb, ul_map_offset, 3, ENC_BIG_ENDIAN); + /* display the number of OFDMA symbols */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_ofdma_symbols_7, tvb, ul_map_offset, 3, ENC_BIG_ENDIAN); + /* display the number of subchannels */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_subchannels_7, tvb, ul_map_offset, 3, ENC_BIG_ENDIAN); + /* display the ranging method */ + proto_tree_add_item(tree, hf_culmap_uiuc_ranging_method, tvb, ul_map_offset, 3, ENC_BIG_ENDIAN); + /* display the reserved */ + proto_tree_add_item(tree, hf_culmap_uiuc_reserved, tvb, ul_map_offset, 3, ENC_BIG_ENDIAN); + ul_map_offset += 3; + } + length += 8; + } + else + { /* display Number of subchannels */ + if(nibble_offset & 1) + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_subchannels_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + else + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_subchannels, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + length += 2; + /* display the repetition coding indication and reserved bits */ + if(nibble_offset & 1) + { + proto_tree_add_item(tree, hf_culmap_uiuc_repetition_coding_indication_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_uiuc_reserved_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 0; + } + else + { + proto_tree_add_item(tree, hf_culmap_uiuc_repetition_coding_indication, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_culmap_uiuc_reserved, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + nibble_offset = 1; + } + length += 1; + } + /* decode HARQ Control IE */ + nibble_length = wimax_compact_ulmap_harq_control_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset); + length += nibble_length; + break; + case COMPACT_UL_MAP_TYPE_HARQ_REGION_IE:/* 6.3.2.3.43.7.5 */ + if(nibble_offset & 1) + { /* display the UL-MAP type */ + proto_tree_add_item(tree, hf_culmap_ul_map_type_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the HARQ Region Change Indication */ + proto_tree_add_item(tree, hf_culmap_harq_region_change_indication_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* get the HARQ Region Change Indication */ + harq_region_change_indication = (byte & 0x01); + /* move to next byte */ + ul_map_offset++; + nibble_offset = 0; + } + else + { /* display the UL-MAP type */ + proto_tree_add_item(tree, hf_culmap_ul_map_type, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the HARQ Region Change Indication */ + proto_tree_add_item(tree, hf_culmap_harq_region_change_indication, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* get the HARQ Region Change Indication */ + harq_region_change_indication = (byte & 0x10); + nibble_offset = 1; + } + length = 1; + if(harq_region_change_indication == 1) + { + if(nibble_offset & 1) + { + /* display the OFDMA symbol offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_ofdma_symbol_offset_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the subchannel offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_subchannel_offset_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the number of OFDMA symbols */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_ofdma_symbols_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the number of subchannels */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_subchannels_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + } + else + { /* display the OFDMA symbol offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_ofdma_symbol_offset, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the subchannel offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_subchannel_offset, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the number of OFDMA symbols */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_ofdma_symbols, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the number of subchannels */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_subchannels, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + } + length += 8; + } + break; + case COMPACT_UL_MAP_TYPE_CQICH_REGION_IE:/* 6.3.2.3.43.7.6 */ + if(nibble_offset & 1) + { /* display the UL-MAP type */ + proto_tree_add_item(tree, hf_culmap_ul_map_type_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the CQI Region Change Indication */ + proto_tree_add_item(tree, hf_culmap_cqi_region_change_indication_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* get the CQI Region Change Indication */ + cqi_region_change_indication = (byte & 0x01); + /* move to next byte */ + ul_map_offset++; + nibble_offset = 0; + } + else + { /* display the UL-MAP type */ + proto_tree_add_item(tree, hf_culmap_ul_map_type, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* display the CQI Region Change Indication */ + proto_tree_add_item(tree, hf_culmap_cqi_region_change_indication, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + /* get the CQI Region Change Indication */ + cqi_region_change_indication = (byte & 0x10); + nibble_offset = 1; + } + length = 1; + if(cqi_region_change_indication == 1) + { + if(nibble_offset & 1) + { + /* display the OFDMA symbol offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_ofdma_symbol_offset_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the subchannel offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_subchannel_offset_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the number of OFDMA symbols */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_ofdma_symbols_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the number of subchannels */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_subchannels_1, tvb, ul_map_offset, 2, ENC_BIG_ENDIAN); + ul_map_offset++; + } + else + { /* display the OFDMA symbol offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_ofdma_symbol_offset, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the subchannel offset */ + proto_tree_add_item(tree, hf_culmap_uiuc_subchannel_offset, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the number of OFDMA symbols */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_ofdma_symbols, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + /* display the number of subchannels */ + proto_tree_add_item(tree, hf_culmap_uiuc_num_of_subchannels, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + ul_map_offset++; + } + length += 8; + } + break; + case COMPACT_UL_MAP_TYPE_EXTENSION:/* 6.3.2.3.43.7.7 */ + /* decode the Compact UL-MAP externsion IE */ + nibble_length = wimax_culmap_extension_ie_decoder(tree, pinfo, tvb, ul_map_offset, nibble_offset);/*, cqich_indicator);*/ + length = nibble_length; + break; + default:/* Reserved Type */ + /* display the reserved type */ + proto_tree_add_item(tree, hf_culmap_reserved_type_1, tvb, ul_map_offset, 1, ENC_BIG_ENDIAN); + length = 1; + break; + } + /* Update the nibble_offset and length */ + return length; +} + +/* Compact UL-MAP Reduced CID IE (6.3.2.3.43.3) decoder */ +static guint wimax_compact_ulmap_rcid_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint length = 0; + guint prefix; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RCID IE"); +#endif + if(nibble_offset & 1) + { + if(cid_type == CID_TYPE_NORMAL) + { /* display the normal CID */ + proto_tree_add_item(tree, hf_rcid_ie_normal_cid_1, tvb, offset, 3, ENC_BIG_ENDIAN); + length = 4; + } + else + { /* Get the prefix bit */ + prefix = (tvb_get_guint8(tvb, offset) & 0x08); + /* display the prefix */ + proto_tree_add_item(tree, hf_rcid_ie_prefix_1, tvb, offset, 2, ENC_BIG_ENDIAN); + if(prefix) + { /* display the CID11 */ + proto_tree_add_item(tree, hf_rcid_ie_cid11_3, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 3; + } + else + { + if(cid_type == CID_TYPE_RCID11) + { /* display the CID11 */ + proto_tree_add_item(tree, hf_rcid_ie_cid11_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 3; + } + else if(cid_type == CID_TYPE_RCID7) + { /* display the normal CID7 */ + proto_tree_add_item(tree, hf_rcid_ie_cid7_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 2; + } + else if(cid_type == CID_TYPE_RCID3) + { /* display the CID3 */ + proto_tree_add_item(tree, hf_rcid_ie_cid3_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 1; + } + } + } + } + else + { + if(cid_type == CID_TYPE_NORMAL) + { /* display the normal CID */ + proto_tree_add_item(tree, hf_rcid_ie_normal_cid, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 4; + } + else + { /* Get the prefix bit */ + prefix = (tvb_get_guint8(tvb, offset) & 0x08); + /* display the prefix */ + proto_tree_add_item(tree, hf_rcid_ie_prefix, tvb, offset, 2, ENC_BIG_ENDIAN); + if(prefix || (cid_type == CID_TYPE_RCID11)) + { /* display the CID11 */ + proto_tree_add_item(tree, hf_rcid_ie_cid11_2, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 3; + } + else + { + if(cid_type == CID_TYPE_RCID11) + { /* display the CID11 */ + proto_tree_add_item(tree, hf_rcid_ie_cid11, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 3; + } + else if(cid_type == CID_TYPE_RCID7) + { /* display the CID7 */ + proto_tree_add_item(tree, hf_rcid_ie_cid7, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 2; + } + else if(cid_type == CID_TYPE_RCID3) + { /* display the CID3 */ + proto_tree_add_item(tree, hf_rcid_ie_cid3, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 1; + } + } + } + } + /* return the IE length in nibbles */ + return length; +} + +/* Compact UL-MAP HARQ Control IE (6.3.2.3.43.4) decoder */ +static guint wimax_compact_ulmap_harq_control_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint byte, prefix, length = 0; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "HARQ Control IE"); +#endif + /* Get the first byte */ + byte = tvb_get_guint8(tvb, offset); + if(nibble_offset & 1) + { /* Get the prefix bit */ + prefix = (byte & 0x08); + /* display the prefix */ + proto_tree_add_item(tree, hf_harq_control_ie_prefix_1, tvb, offset, 2, ENC_BIG_ENDIAN); + if(prefix) + { /* display the ai_sn */ + proto_tree_add_item(tree, hf_harq_control_ie_ai_sn_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the spid */ + proto_tree_add_item(tree, hf_harq_control_ie_spid_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the acid */ + proto_tree_add_item(tree, hf_harq_control_ie_acid_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 2; + } + else + { /* display the reserved bits */ + proto_tree_add_item(tree, hf_harq_control_ie_reserved_1, tvb, offset, 2, ENC_BIG_ENDIAN); + length = 1; + } + } + else + { /* Get the prefix bit */ + prefix = (byte & 0x80); + /* display the prefix */ + proto_tree_add_item(tree, hf_harq_control_ie_prefix, tvb, offset, 1, ENC_BIG_ENDIAN); + if(prefix) + { /* display the ai_sn */ + proto_tree_add_item(tree, hf_harq_control_ie_ai_sn, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the spid */ + proto_tree_add_item(tree, hf_harq_control_ie_spid, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the acid */ + proto_tree_add_item(tree, hf_harq_control_ie_acid, tvb, offset, 1, ENC_BIG_ENDIAN); + length = 2; + } + else + { /* display the reserved bits */ + proto_tree_add_item(tree, hf_harq_control_ie_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + length = 1; + } + } + /* return the IE length in nibbles */ + return length; +} + +/* UL-MAP Extension IE sub-types */ +#define HARQ_MODE_SWITCH 0 +#define EXTENSION_TYPE_SHIFT 13 +#define EXTENSION_TYPE_SHIFT_1 9 +#define EXTENSION_SUBTYPE_SHIFT 8 +#define EXTENSION_SUBTYPE_SHIFT_1 4 +#define EXTENSION_LENGTH_SHIFT 4 + +/* Compact UL-MAP Extension IE (6.3.2.3.43.7.7) decoder */ +static guint wimax_culmap_extension_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint tvb_value, ul_map_type, sub_type, length; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UL-MAP Extension IE"); +#endif + /* Get the first 16-bit word */ + tvb_value = tvb_get_ntohs(tvb, offset); + if(nibble_offset & 1) + { /* Get the ul-map type */ + ul_map_type = ((tvb_value & EXTENSION_TYPE_MASK_1) >> EXTENSION_TYPE_SHIFT_1); + if(ul_map_type != COMPACT_UL_MAP_TYPE_EXTENSION) + return 0; + /* Get the sub-type */ + sub_type = ((tvb_value & EXTENSION_SUBTYPE_MASK_1) >> EXTENSION_SUBTYPE_SHIFT_1); + /* Get the IE length */ + length = (tvb_value & EXTENSION_LENGTH_MASK_1); + /* display the UL-MAP type */ + proto_tree_add_item(tree, hf_culmap_extension_type_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the UL-MAP extension subtype */ + proto_tree_add_item(tree, hf_culmap_extension_subtype_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the IE length */ + proto_tree_add_item(tree, hf_culmap_extension_length_1, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + switch (sub_type) + { + case HARQ_MODE_SWITCH: + /* display the HARQ mode */ + proto_tree_add_item(tree, hf_culmap_extension_harq_mode, tvb, offset, 1, ENC_BIG_ENDIAN); + /* Get the next byte */ + tvb_value = tvb_get_guint8(tvb, offset); + /* get the HARQ mode */ + harq_mode = ((tvb_value & MSB_NIBBLE_MASK) >> 4); + break; + default: + /* display the unknown sub-type in HEX */ + proto_tree_add_item(tree, hf_culmap_extension_unknown_sub_type_1, tvb, offset, (length - 2), ENC_NA); + break; + } + } + else + { /* Get the UL-MAp type */ + ul_map_type = ((tvb_value & EXTENSION_TYPE_MASK) >> EXTENSION_TYPE_SHIFT); + if(ul_map_type != COMPACT_UL_MAP_TYPE_EXTENSION) + return 0; + /* Get the sub-type */ + sub_type = ((tvb_value & EXTENSION_SUBTYPE_MASK) >> EXTENSION_SUBTYPE_SHIFT); + /* Get the IE length */ + length = ((tvb_value & EXTENSION_LENGTH_MASK) >> EXTENSION_LENGTH_SHIFT); + /* display the UL-MAP type */ + proto_tree_add_item(tree, hf_culmap_extension_type, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the UL-MAP extension subtype */ + proto_tree_add_item(tree, hf_culmap_extension_subtype, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the IE length */ + proto_tree_add_item(tree, hf_culmap_extension_length, tvb, offset, 2, ENC_BIG_ENDIAN); + switch (sub_type) + { + case HARQ_MODE_SWITCH: + /* display the HARQ mode */ + proto_tree_add_item(tree, hf_culmap_extension_harq_mode_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* get the HARQ mode */ + harq_mode = (tvb_value & LSB_NIBBLE_MASK); + break; + default: + /* display the unknown sub-type in HEX */ + proto_tree_add_item(tree, hf_culmap_extension_unknown_sub_type, tvb, (offset + 1), (length - 1), ENC_NA); + break; + } + } + /* return the IE length in nibbles */ + return (length * 2); +} + +/* 8.4.5.4.3 (table 290) */ +guint wimax_cdma_allocation_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "CDMA Allocation IE"); +#endif + if(nibble_offset & 1) + { /* display the Duration */ + proto_tree_add_item(tree, hf_cdma_allocation_duration_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the UIUC */ + proto_tree_add_item(tree, hf_cdma_allocation_uiuc_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the Repetition Coding Indication */ + proto_tree_add_item(tree, hf_cdma_allocation_repetition_1, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the frame number index */ + proto_tree_add_item(tree, hf_cdma_allocation_frame_number_index_1, tvb, offset, 4, ENC_BIG_ENDIAN); + /* display the Ranging Code */ + proto_tree_add_item(tree, hf_cdma_allocation_ranging_code_1, tvb, offset, 4, ENC_BIG_ENDIAN); + /* display the Ranging Symbol */ + proto_tree_add_item(tree, hf_cdma_allocation_ranging_symbol_1, tvb, offset, 4, ENC_BIG_ENDIAN); + /* display the Ranging Subchannel */ + proto_tree_add_item(tree, hf_cdma_allocation_ranging_subchannel_1, tvb, offset, 4, ENC_BIG_ENDIAN); + /* display the BW Request Mandatory */ + proto_tree_add_item(tree, hf_cdma_allocation_bw_req_1, tvb, offset, 4, ENC_BIG_ENDIAN); + } + else + { /* display the Duration */ + proto_tree_add_item(tree, hf_cdma_allocation_duration, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the UIUC */ + proto_tree_add_item(tree, hf_cdma_allocation_uiuc, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the Repetition Coding Indication */ + proto_tree_add_item(tree, hf_cdma_allocation_repetition, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the frame number index */ + proto_tree_add_item(tree, hf_cdma_allocation_frame_number_index, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display the Ranging Code */ + proto_tree_add_item(tree, hf_cdma_allocation_ranging_code, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Ranging Symbol */ + proto_tree_add_item(tree, hf_cdma_allocation_ranging_symbol, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the Ranging Subchannel */ + proto_tree_add_item(tree, hf_cdma_allocation_ranging_subchannel, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display the BW Request Mandatory */ + proto_tree_add_item(tree, hf_cdma_allocation_bw_req, tvb, offset, 1, ENC_BIG_ENDIAN); + } + /* return the IE length in nibbles */ + return 8; +} + +/* Extended UIUCs (table 290a) */ +#define POWER_CONTROL_IE 0 +#define MINI_SUBCHANNEL_ALLOCATION_IE 1 +#define AAS_UL_IE 2 +#define CQICH_ALLOC_IE 3 +#define UL_ZONE_IE 4 +#define PHYMOD_UL_IE 5 +#define MIMO_UL_BASIC_IE 6 +#define UL_MAP_FAST_TRACKING_IE 7 +#define UL_PUSC_BURST_ALLOCATION_IN_OTHER_SEGMENT_IE 8 +#define FAST_RANGING_IE 9 +#define UL_ALLOCATION_START_IE 10 + +/* 8.4.5.4.4.1 (table 290b) */ +guint wimax_extended_uiuc_dependent_ie_decoder(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, guint offset, guint nibble_offset) +{ + guint ext_uiuc, length, m, i; + guint8 byte; + +#ifdef DEBUG + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Extended UIUC IE"); +#endif + + /* get the first byte */ + byte = tvb_get_guint8(tvb, offset); + if(nibble_offset & 1) + { /* get the extended UIUC */ + ext_uiuc = (byte & LSB_NIBBLE_MASK); + /* display extended UIUC */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_uiuc_1, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + offset++; + /* get the 2nd byte */ + byte = tvb_get_guint8(tvb, offset); + /* get the length */ + length = ((byte & MSB_NIBBLE_MASK) >> 4); + /* display extended UIUC length */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_length_1, tvb, offset, 1, ENC_BIG_ENDIAN); + } + else + { /* get the extended UIUC */ + ext_uiuc = ((byte & MSB_NIBBLE_MASK) >> 4); + /* get the length */ + length = (byte & LSB_NIBBLE_MASK); + /* display extended UIUC */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_uiuc, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display extended UIUC length */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_length, tvb, offset, 1, ENC_BIG_ENDIAN); + /* move to next byte */ + offset++; + } + /* 8.4.5.4.4.1 (table 290b) */ + switch (ext_uiuc) + { + case POWER_CONTROL_IE: + /* 8.4.5.4.5 Power Control IE */ + if(nibble_offset & 1) + { /* display power control value */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_power_control_24, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display power measurement frame value */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_power_measurement_frame_24, tvb, offset, 3, ENC_BIG_ENDIAN); + } + else + { /* display power control value */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_power_control, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display power measurement frame value */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_power_measurement_frame, tvb, (offset + 1), 1, ENC_BIG_ENDIAN); + } + break; + case MINI_SUBCHANNEL_ALLOCATION_IE: + /* 8.4.5.4.8 Mini Subchannel Allocation IE */ + /* set the M value */ + switch (length) + { + case 15: + m = 6; + break; + case 9: + m = 3; + break; + case 7: + default: + m = 2; + break; + } + if(nibble_offset & 1) + { + /* display MINI Subchannel Allocation CType value */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_mini_subchannel_alloc_ctype_16, tvb, offset, 2, ENC_BIG_ENDIAN); + /* display MINI Subchannel Allocation Duration value */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_mini_subchannel_alloc_duration_16, tvb, offset, 2, ENC_BIG_ENDIAN); + } + else + { /* display MINI Subchannel Allocation CType value */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_mini_subchannel_alloc_ctype, tvb, offset, 1, ENC_BIG_ENDIAN); + /* display MINI Subchannel Allocation Duration value */ + proto_tree_add_item(tree, hf_extended_uiuc_ie_mini_subchannel_alloc_duration, tvb, offset, 1, ENC_BIG_ENDIAN); + } + offset++; + /* decode and display CIDs, UIUCs, and Repetitions */ + for(i=0; i + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef _WIMAX_COMPACT_ULMAP_IE_DECODER_H_ +#define _WIMAX_COMPACT_ULMAP_IE_DECODER_H_ + +extern guint wimax_compact_ulmap_ie_decoder(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint nibble_offset); + +#endif /* _WIMAX_COMPACT_ULMAP_IE_DECODER_H_ */ diff --git a/plugins/epan/wimax/wimax_fch_decoder.c b/plugins/epan/wimax/wimax_fch_decoder.c new file mode 100644 index 00000000..60f0251b --- /dev/null +++ b/plugins/epan/wimax/wimax_fch_decoder.c @@ -0,0 +1,246 @@ +/* wimax_fch_decoder.c + * WiMax FCH Burst decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include + +#include +#include "wimax-int.h" + +extern gint proto_wimax; + +extern address bs_address; /* declared in packet-wmx.c */ + +static int proto_wimax_fch_decoder = -1; +static gint ett_wimax_fch_decoder = -1; + +#define FCH_BURST_LENGTH 3 +/* FCH Burst bits */ +#define USED_SUB_CHANNEL_GROUP_0 0x800000 +#define USED_SUB_CHANNEL_GROUP_1 0x400000 +#define USED_SUB_CHANNEL_GROUP_2 0x200000 +#define USED_SUB_CHANNEL_GROUP_3 0x100000 +#define USED_SUB_CHANNEL_GROUP_4 0x080000 +#define USED_SUB_CHANNEL_GROUP_5 0x040000 +#define FCH_RESERVED_1 0x020000 +#define REPETITION_CODING_INDICATION 0x018000 +#define CODING_INDICATION 0x007000 +#define DL_MAP_LENGTH 0x000FF0 +#define FCH_RESERVED_2 0x00000F + +static int hf_fch_used_subchannel_group0 = -1; +static int hf_fch_used_subchannel_group1 = -1; +static int hf_fch_used_subchannel_group2 = -1; +static int hf_fch_used_subchannel_group3 = -1; +static int hf_fch_used_subchannel_group4 = -1; +static int hf_fch_used_subchannel_group5 = -1; +static int hf_fch_reserved_1 = -1; +static int hf_fch_repetition_coding_indication = -1; +static int hf_fch_coding_indication = -1; +static int hf_fch_dlmap_length = -1; +static int hf_fch_reserved_2 = -1; + +static const value_string used_or_not_used[] = +{ + { 0, "Is Not Used" }, + { 1, "Is Used" }, + { 0, NULL } +}; + +/* DL Frame Prefix Repetition Coding Indications */ +static const value_string repetition_coding_indications[] = +{ + { 0, "No Repetition Coding" }, + { 1, "Repetition Coding of 2 Used" }, + { 2, "Repetition Coding of 4 Used" }, + { 3, "Repetition Coding of 6 Used" }, + { 0, NULL } +}; + +/* DL Frame Prefix Coding Indications */ +static const value_string coding_indications[] = +{ + { 0, "CC Encoding Used" }, + { 1, "BTC Encoding Used" }, + { 2, "CTC Encoding Used" }, + { 3, "ZT CC Encoding Used" }, + { 4, "CC Encoding with optional interleaver" }, + { 5, "LDPC Encoding Used" }, + { 6, "Reserved" }, + { 7, "Reserved" }, + { 0, NULL } +}; + +static int dissect_wimax_fch_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + gint offset = 0; + proto_item *fch_item = NULL; + proto_tree *fch_tree = NULL; + + /* save the base station address (once) */ + if(!bs_address.len) + copy_address(&bs_address, &(pinfo->src)); + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "FCH"); + if (tree) + { /* we are being asked for details */ + /* display FCH dissector info */ + fch_item = proto_tree_add_protocol_format(tree, proto_wimax_fch_decoder, tvb, offset, 3, "DL Frame Prefix (24 bits)"); + /* add FCH subtree */ + fch_tree = proto_item_add_subtree(fch_item, ett_wimax_fch_decoder); + /* Decode and display the used sub-channel groups */ + proto_tree_add_item(fch_tree, hf_fch_used_subchannel_group0, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + proto_tree_add_item(fch_tree, hf_fch_used_subchannel_group1, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + proto_tree_add_item(fch_tree, hf_fch_used_subchannel_group2, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + proto_tree_add_item(fch_tree, hf_fch_used_subchannel_group3, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + proto_tree_add_item(fch_tree, hf_fch_used_subchannel_group4, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + proto_tree_add_item(fch_tree, hf_fch_used_subchannel_group5, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + proto_tree_add_item(fch_tree, hf_fch_reserved_1, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + /* Decode and display the repetition coding indication */ + proto_tree_add_item(fch_tree, hf_fch_repetition_coding_indication, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + /* Decode and display the coding indication */ + proto_tree_add_item(fch_tree, hf_fch_coding_indication, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + /* Decode and display the DL MAP length */ + proto_tree_add_item(fch_tree, hf_fch_dlmap_length, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + proto_tree_add_item(fch_tree, hf_fch_reserved_2, tvb, offset, FCH_BURST_LENGTH, ENC_BIG_ENDIAN); + } + return tvb_captured_length(tvb); +} + +/* Register Wimax FCH Protocol */ +void wimax_proto_register_wimax_fch(void) +{ + /* TLV display */ + static hf_register_info hf[] = + { + { + &hf_fch_used_subchannel_group0, + { + "Sub-Channel Group 0", "wmx.fch.subchannel_group0", + FT_UINT24, BASE_DEC, VALS(used_or_not_used), USED_SUB_CHANNEL_GROUP_0, + NULL, HFILL + } + }, + { + &hf_fch_used_subchannel_group1, + { + "Sub-Channel Group 1", "wmx.fch.subchannel_group1", + FT_UINT24, BASE_DEC, VALS(used_or_not_used), USED_SUB_CHANNEL_GROUP_1, + NULL, HFILL + } + }, + { + &hf_fch_used_subchannel_group2, + { + "Sub-Channel Group 2", "wmx.fch.subchannel_group2", + FT_UINT24, BASE_DEC, VALS(used_or_not_used), USED_SUB_CHANNEL_GROUP_2, + NULL, HFILL + } + }, + { + &hf_fch_used_subchannel_group3, + { + "Sub-Channel Group 3", "wmx.fch.subchannel_group3", + FT_UINT24, BASE_DEC, VALS(used_or_not_used), USED_SUB_CHANNEL_GROUP_3, + NULL, HFILL + } + }, + { + &hf_fch_used_subchannel_group4, + { + "Sub-Channel Group 4", "wmx.fch.subchannel_group4", + FT_UINT24, BASE_DEC, VALS(used_or_not_used), USED_SUB_CHANNEL_GROUP_4, + NULL, HFILL + } + }, + { + &hf_fch_used_subchannel_group5, + { + "Sub-Channel Group 5", "wmx.fch.subchannel_group5", + FT_UINT24, BASE_DEC, VALS(used_or_not_used), USED_SUB_CHANNEL_GROUP_5, + NULL, HFILL + } + }, + { + &hf_fch_reserved_1, + { + "Reserved", "wmx.fch.reserved1", + FT_UINT24, BASE_DEC, NULL, FCH_RESERVED_1, + NULL, HFILL + } + }, + { + &hf_fch_repetition_coding_indication, + { + "Repetition Coding Indication", "wmx.fch.repetition_coding_indication", + FT_UINT24, BASE_DEC, VALS(repetition_coding_indications), REPETITION_CODING_INDICATION, + NULL, HFILL + } + }, + { + &hf_fch_coding_indication, + { + "Coding Indication", "wmx.fch.coding_indication", + FT_UINT24, BASE_DEC, VALS(coding_indications), CODING_INDICATION, + NULL, HFILL + } + }, + { + &hf_fch_dlmap_length, + { + "DL Map Length", "wmx.fch.dl_map_length", + FT_UINT24, BASE_DEC, NULL, DL_MAP_LENGTH, + NULL, HFILL + } + }, + { + &hf_fch_reserved_2, + { + "Reserved", "wmx.fch.reserved2", + FT_UINT24, BASE_DEC, NULL, FCH_RESERVED_2, + NULL, HFILL + } + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_wimax_fch_decoder, + }; + + proto_wimax_fch_decoder = proto_wimax; + + /* register the field display messages */ + proto_register_field_array(proto_wimax_fch_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("wimax_fch_burst_handler", dissect_wimax_fch_decoder, proto_wimax_fch_decoder); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_ffb_decoder.c b/plugins/epan/wimax/wimax_ffb_decoder.c new file mode 100644 index 00000000..8a9ccad3 --- /dev/null +++ b/plugins/epan/wimax/wimax_ffb_decoder.c @@ -0,0 +1,129 @@ +/* wimax_ffb_decoder.c + * WiMax Fast Feedback packet decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax-int.h" + +extern gint proto_wimax; + +static gint proto_wimax_ffb_decoder = -1; +static gint ett_wimax_ffb_decoder = -1; + +/* static gint hf_ffb_burst = -1; */ +static gint hf_ffb_num_of_ffbs = -1; +static gint hf_ffb_type = -1; +static gint hf_ffb_subchannel = -1; +static gint hf_ffb_symboloffset = -1; +static gint hf_ffb_value = -1; + + +static int dissect_wimax_ffb_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + gint offset = 0; + guint length, num_of_ffbs, i; + proto_item *ffb_item = NULL; + proto_tree *ffb_tree = NULL; + + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Fast Feedback Burst:"); + if (tree) + { /* we are being asked for details */ + /* get the tvb reported length */ + length = tvb_reported_length(tvb); + /* display Fast Feedback Burst dissector info */ + ffb_item = proto_tree_add_protocol_format(tree, proto_wimax_ffb_decoder, tvb, offset, length, "Fast Feedback Burst (%u bytes)", length); + /* add Fast Feedback Burst subtree */ + ffb_tree = proto_item_add_subtree(ffb_item, ett_wimax_ffb_decoder); + /* get the number of FFBs */ + num_of_ffbs = tvb_get_guint8(tvb, offset); + /* display the number of FFBs */ + proto_tree_add_item(ffb_tree, hf_ffb_num_of_ffbs, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the FFB type */ + proto_tree_add_item(ffb_tree, hf_ffb_type, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the FFBs */ + for(i = 0; i < num_of_ffbs; i++) + { + proto_tree_add_item(ffb_tree, hf_ffb_subchannel, tvb, offset++, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ffb_tree, hf_ffb_symboloffset, tvb, offset++, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ffb_tree, hf_ffb_value, tvb, offset++, 1, ENC_BIG_ENDIAN); + } + } + return tvb_captured_length(tvb); +} + +/* Register Wimax FFB Protocol */ +void wimax_proto_register_wimax_ffb(void) +{ + /* FFB display */ + static hf_register_info hf[] = + { +#if 0 + { + &hf_ffb_burst, + {"Fast Feedback Burst", "wmx.ffb.burst", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#endif + { + &hf_ffb_num_of_ffbs, + {"Number Of Fast Feedback", "wmx.ffb.num_of_ffbs", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_ffb_type, + {"Fast Feedback Type", "wmx.ffb.ffb_type", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_ffb_subchannel, + {"Physical Subchannel", "wmx.ffb.subchannel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_ffb_symboloffset, + {"Symbol Offset", "wmx.ffb.symbol_offset", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_ffb_value, + {"Fast Feedback Value", "wmx.ffb.ffb_value", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_wimax_ffb_decoder, + }; + + proto_wimax_ffb_decoder = proto_wimax; + + /* register the field display messages */ + proto_register_field_array(proto_wimax_ffb_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("wimax_ffb_burst_handler", dissect_wimax_ffb_decoder, proto_wimax_ffb_decoder); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_hack_decoder.c b/plugins/epan/wimax/wimax_hack_decoder.c new file mode 100644 index 00000000..1c44e299 --- /dev/null +++ b/plugins/epan/wimax/wimax_hack_decoder.c @@ -0,0 +1,141 @@ +/* wimax_hack_decoder.c + * WiMax HARQ ACK Burst decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax-int.h" + +extern gint proto_wimax; + +static gint proto_wimax_hack_decoder = -1; +static gint ett_wimax_hack_decoder = -1; + +static const value_string vals_flags[] = +{ + {0, "Even Half-Slot (tiles 0,2,4)"}, + {1, "Odd Half-Slot (tiles 1,3,5)"}, + {0, NULL} +}; + +static const value_string vals_values[] = +{ + {0, "ACK"}, + {1, "NACK"}, + {0, NULL} +}; + +/* static gint hf_hack_burst = -1; */ +static gint hf_hack_num_of_hacks = -1; +static gint hf_hack_half_slot_flag = -1; +static gint hf_hack_subchannel = -1; +static gint hf_hack_symboloffset = -1; +static gint hf_hack_value = -1; + + +static int dissect_wimax_hack_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + gint offset = 0; + guint length, num_of_hacks, i; + proto_item *hack_item = NULL; + proto_tree *hack_tree = NULL; + + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "HARQ ACK Burst:"); + if (tree) + { /* we are being asked for details */ + /* get the tvb reported length */ + length = tvb_reported_length(tvb); + /* display HARQ ACK Burst dissector info */ + hack_item = proto_tree_add_protocol_format(tree, proto_wimax_hack_decoder, tvb, offset, length, "HARQ ACK Burst (%u bytes)", length); + /* add HARQ ACK Burst subtree */ + hack_tree = proto_item_add_subtree(hack_item, ett_wimax_hack_decoder); + /* get the number of HARQ ACKs */ + num_of_hacks = tvb_get_guint8(tvb, offset); + /* display the number of HARQ ACKs */ + proto_tree_add_item(hack_tree, hf_hack_num_of_hacks, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the HARQ ACKs */ + for(i = 0; i < num_of_hacks; i++) + { + proto_tree_add_item(hack_tree, hf_hack_subchannel, tvb, offset++, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(hack_tree, hf_hack_symboloffset, tvb, offset++, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(hack_tree, hf_hack_half_slot_flag, tvb, offset++, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(hack_tree, hf_hack_value, tvb, offset++, 1, ENC_BIG_ENDIAN); + } + } + return tvb_captured_length(tvb); +} + +/* Register Wimax HARQ ACK Protocol */ +void wimax_proto_register_wimax_hack(void) +{ + /* HARQ ACK display */ + static hf_register_info hf[] = + { +#if 0 + { + &hf_hack_burst, + {"HARQ ACK Burst", "wmx.hack.burst", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#endif + { + &hf_hack_num_of_hacks, + {"Number Of HARQ ACKs/NACKs", "wmx.hack.num_of_hacks", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_hack_subchannel, + {"Physical Subchannel", "wmx.hack.subchannel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_hack_symboloffset, + {"Symbol Offset", "wmx.hack.symbol_offset", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_hack_half_slot_flag, + {"Half-Slot Flag", "wmx.hack.half_slot_flag", FT_UINT8, BASE_DEC, VALS(vals_flags), 0x0, NULL, HFILL} + }, + { + &hf_hack_value, + {"ACK Value", "wmx.hack.hack_value", FT_UINT8, BASE_DEC, VALS(vals_values), 0x0, NULL, HFILL} + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_wimax_hack_decoder, + }; + + proto_wimax_hack_decoder = proto_wimax; + + register_dissector("wimax_hack_burst_handler", dissect_wimax_hack_decoder, proto_wimax_hack_decoder); + proto_register_field_array(proto_wimax_hack_decoder, hf, array_length(hf)); + + proto_register_subtree_array(ett, array_length(ett)); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_harq_map_decoder.c b/plugins/epan/wimax/wimax_harq_map_decoder.c new file mode 100644 index 00000000..ec99de00 --- /dev/null +++ b/plugins/epan/wimax/wimax_harq_map_decoder.c @@ -0,0 +1,233 @@ +/* wimax_harq_map_decoder.c + * WiMax HARQ Map Message decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include +#include "crc.h" +#include "wimax-int.h" +#include "wimax_compact_dlmap_ie_decoder.h" +#include "wimax_compact_ulmap_ie_decoder.h" + +extern gint proto_wimax; + +static gint proto_wimax_harq_map_decoder = -1; +static gint ett_wimax_harq_map_decoder = -1; + +/* MASKs */ +#define LSB_NIBBLE_MASK 0x0F + +/* HARQ MAP masks */ +#define WIMAX_HARQ_MAP_INDICATOR_MASK 0xE00000 +#define WIMAX_HARQ_UL_MAP_APPENDED_MASK 0x100000 +#define WIMAX_HARQ_MAP_RESERVED_MASK 0x080000 +#define WIMAX_HARQ_MAP_MSG_LENGTH_MASK 0x07FC00 +#define WIMAX_HARQ_MAP_DL_IE_COUNT_MASK 0x0003F0 +#define WIMAX_HARQ_MAP_MSG_LENGTH_SHIFT 10 +#define WIMAX_HARQ_MAP_DL_IE_COUNT_SHIFT 4 + +/* HARQ MAP display indexies */ +static gint hf_harq_map_indicator = -1; +static gint hf_harq_ul_map_appended = -1; +static gint hf_harq_map_reserved = -1; +static gint hf_harq_map_msg_length = -1; +static gint hf_harq_dl_ie_count = -1; +static gint hf_harq_map_msg_crc = -1; +static gint hf_harq_map_msg_crc_status = -1; + +static expert_field ei_harq_map_msg_crc = EI_INIT; + + +/* Copied and renamed from proto.c because global value_strings don't work for plugins */ +static const value_string plugin_proto_checksum_vals[] = { + { PROTO_CHECKSUM_E_BAD, "Bad" }, + { PROTO_CHECKSUM_E_GOOD, "Good" }, + { PROTO_CHECKSUM_E_UNVERIFIED, "Unverified" }, + { PROTO_CHECKSUM_E_NOT_PRESENT, "Not present" }, + + { 0, NULL } +}; + +/* HARQ MAP message decoder */ +static int dissector_wimax_harq_map_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint i, offset = 0; + guint tvb_len, length, dl_ie_count; + guint ie_length; + proto_item *harq_map_item = NULL; + proto_tree *harq_map_tree = NULL; + guint nibble_offset; + proto_item *parent_item = NULL; + guint ulmap_appended; + guint32 harq_map_msg_crc, calculated_crc; + guint32 first_24bits; + + /* check the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + if(!tvb_len) + { /* do nothing if tvb is empty */ + return 0; + } + /* Ensure the right payload type */ + first_24bits = tvb_get_ntoh24(tvb, offset); + if((first_24bits & WIMAX_HARQ_MAP_INDICATOR_MASK) != WIMAX_HARQ_MAP_INDICATOR_MASK) + { /* do nothing if tvb is not a HARQ MAP message */ + return 0; + } + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "HARQ-MAP Message: "); + if (tree) + { /* we are being asked for details */ + /* get the parent */ + parent_item = proto_tree_get_parent(tree); + /* display HARQ-MAP Message and create subtree */ + harq_map_item = proto_tree_add_protocol_format(tree, proto_wimax_harq_map_decoder, tvb, offset, tvb_len, "HARQ-MAP Message (%u bytes)", tvb_len); + harq_map_tree = proto_item_add_subtree(harq_map_item, ett_wimax_harq_map_decoder); + /* display the HARQ MAP Indicator */ + proto_tree_add_item(harq_map_tree, hf_harq_map_indicator, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the HARQ MAp UL-MAP Appended */ + proto_tree_add_item(harq_map_tree, hf_harq_ul_map_appended, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the reserved bit */ + proto_tree_add_item(harq_map_tree, hf_harq_map_reserved, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the HARQ MAP message length */ + proto_tree_add_item(harq_map_tree, hf_harq_map_msg_length, tvb, offset, 3, ENC_BIG_ENDIAN); + /* display the DL IE count */ + proto_tree_add_item(harq_map_tree, hf_harq_dl_ie_count, tvb, offset, 3, ENC_BIG_ENDIAN); + /* get the message length */ + /* XXX - make sure the length isn't smaller than the minimum */ + length = ((first_24bits & WIMAX_HARQ_MAP_MSG_LENGTH_MASK) >> WIMAX_HARQ_MAP_MSG_LENGTH_SHIFT); + /* get the DL IE count */ + dl_ie_count = ((first_24bits & WIMAX_HARQ_MAP_DL_IE_COUNT_MASK) >> WIMAX_HARQ_MAP_DL_IE_COUNT_SHIFT); + /* get the UL MAP appended */ + ulmap_appended = (first_24bits & WIMAX_HARQ_UL_MAP_APPENDED_MASK); + + /* set the offsets to Compact DL-MAP IEs */ + offset += 2; + nibble_offset = 1; + /* process the compact dl_map ies */ + for(i=0; i> 1); + nibble_offset = ((nibble_offset + ie_length) & 1); + } + /* check if there exist the compact ul_map IEs */ + if (ulmap_appended) + { /* add the UL-MAp IEs info */ + proto_item_append_text(parent_item, ",UL-MAP IEs"); + /* process the compact ul_map ies */ + while(offset < (length - (int)sizeof(harq_map_msg_crc))) + { /* decode Compact UL-MAP IEs */ + ie_length = wimax_compact_ulmap_ie_decoder(harq_map_tree, pinfo, tvb, offset, nibble_offset); + /* Prevent endless loop with erroneous data. */ + if (ie_length < 2) + ie_length = 2; + offset += ((nibble_offset + ie_length) >> 1); + nibble_offset = ((nibble_offset + ie_length) & 1); + } + } + /* handle the padding */ + if(nibble_offset) + { + /* add the Padding info */ + proto_item_append_text(parent_item, ",Padding"); + proto_tree_add_protocol_format(harq_map_tree, proto_wimax_harq_map_decoder, tvb, offset, 1, "Padding Nibble: 0x%x", (tvb_get_guint8(tvb, offset) & LSB_NIBBLE_MASK)); + } + /* add the CRC info */ + proto_item_append_text(parent_item, ",CRC"); + /* calculate the HARQ MAM Message CRC */ + if (length >= (int)sizeof(harq_map_msg_crc)) { + calculated_crc = wimax_mac_calc_crc32(tvb_get_ptr(tvb, 0, length - (int)sizeof(harq_map_msg_crc)), length - (int)sizeof(harq_map_msg_crc)); + proto_tree_add_checksum(tree, tvb, length - (int)sizeof(harq_map_msg_crc), hf_harq_map_msg_crc, hf_harq_map_msg_crc_status, &ei_harq_map_msg_crc, + pinfo, calculated_crc, ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY); + } + } + return tvb_captured_length(tvb); +} + +/* Register Wimax HARQ MAP Protocol */ +void wimax_proto_register_wimax_harq_map(void) +{ + /* HARQ MAP display */ + static hf_register_info hf_harq_map[] = + { + { + &hf_harq_map_indicator, + {"HARQ MAP Indicator", "wmx.harq_map.indicator", FT_UINT24, BASE_HEX, NULL, WIMAX_HARQ_MAP_INDICATOR_MASK, NULL, HFILL} + }, + { + &hf_harq_ul_map_appended, + {"HARQ UL-MAP Appended", "wmx.harq_map.ul_map_appended", FT_UINT24, BASE_HEX, NULL, WIMAX_HARQ_UL_MAP_APPENDED_MASK, NULL, HFILL} + }, + { + &hf_harq_map_reserved, + {"Reserved", "wmx.harq_map.reserved", FT_UINT24, BASE_HEX, NULL, WIMAX_HARQ_MAP_RESERVED_MASK, NULL, HFILL} + }, + { + &hf_harq_map_msg_length, + {"Map Message Length", "wmx.harq_map.msg_length", FT_UINT24, BASE_DEC, NULL, WIMAX_HARQ_MAP_MSG_LENGTH_MASK, NULL, HFILL} + }, + { + &hf_harq_dl_ie_count, + {"DL IE Count", "wmx.harq_map.dl_ie_count", FT_UINT24, BASE_DEC, NULL, WIMAX_HARQ_MAP_DL_IE_COUNT_MASK, NULL, HFILL} + }, + { + &hf_harq_map_msg_crc, + {"HARQ MAP Message CRC", "wmx.harq_map.msg_crc", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_harq_map_msg_crc_status, + {"HARQ MAP Message CRC Status", "wmx.harq_map.msg_crc.status", FT_UINT8, BASE_NONE, VALS(plugin_proto_checksum_vals), 0x0, NULL, HFILL} + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_wimax_harq_map_decoder, + }; + + static ei_register_info ei[] = { + { &ei_harq_map_msg_crc, { "wmx.harq_map.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }}, + }; + + expert_module_t* expert_harq_map; + + proto_wimax_harq_map_decoder = proto_wimax; + + proto_register_subtree_array(ett, array_length(ett)); + proto_register_field_array(proto_wimax_harq_map_decoder, hf_harq_map, array_length(hf_harq_map)); + expert_harq_map = expert_register_protocol(proto_wimax_harq_map_decoder); + expert_register_field_array(expert_harq_map, ei, array_length(ei)); + + register_dissector("wimax_harq_map_handler", dissector_wimax_harq_map_decoder, proto_wimax_harq_map_decoder); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_mac.h b/plugins/epan/wimax/wimax_mac.h new file mode 100644 index 00000000..ec4cfee7 --- /dev/null +++ b/plugins/epan/wimax/wimax_mac.h @@ -0,0 +1,689 @@ +/* wimax_mac.h + * WiMax MAC Definitions + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef WIMAX_MAC_H +#define WIMAX_MAC_H + +#define IP_HEADER_BYTE 0x45 + +/* WiMax MAC Header/Subheader Sizes */ +#define WIMAX_MAC_HEADER_SIZE 6 +#define WIMAX_MAC_SUBHEADER_MESH_SIZE 2 +#define WIMAX_MAC_SUBHEADER_FAST_FEEDBACK_SIZE 1 +#define WIMAX_MAC_SUBHEADER_GRANT_MGMT_SIZE 2 + +#define WIMAX_MAC_SUBHEADER_FRAG_SIZE(x) (((x) & (WIMAX_MAC_TYPE_EXTENDED | WIMAX_MAC_TYPE_ARQ)) ? 3 : 2) +#define WIMAX_MAC_SUBHEADER_PACK_SIZE(x) (((x) & (WIMAX_MAC_TYPE_EXTENDED | WIMAX_MAC_TYPE_ARQ)) ? 3 : 2) + +#define WIMAX_MAC_HEADER_GENERIC 0 +#define WIMAX_MAC_CID_PADDING 0xFFFE + +/* wimax mac arq */ +#define ARQ_CUMULATIVE_ACK_ENTRY 1 +#define ARQ_CUMULATIVE_ACK_BLOCK_SEQ 3 +#define ARQ_ACK_MAP_SIZE 2 + +/* WiMax MAC Header Sub-types (Table 6) */ +#define WIMAX_MAC_TYPE_MESH (1 << 5) +#define WIMAX_MAC_TYPE_ARQ (1 << 4) +#define WIMAX_MAC_TYPE_EXTENDED (1 << 3) +#define WIMAX_MAC_TYPE_FRAGMENTATION (1 << 2) +#define WIMAX_MAC_TYPE_PACKING (1 << 1) +#define WIMAX_MAC_TYPE_FAST_FEEDBACK (1 << 0) +#define WIMAX_MAC_TYPE_GRANT_MGMT (1 << 0) + +/* wimax mac management messages (Table 14) */ +#define MAC_MGMT_MSG_UCD 0 +#define MAC_MGMT_MSG_DCD 1 +#define MAC_MGMT_MSG_DL_MAP 2 +#define MAC_MGMT_MSG_UL_MAP 3 +#define MAC_MGMT_MSG_RNG_REQ 4 +#define MAC_MGMT_MSG_RNG_RSP 5 +#define MAC_MGMT_MSG_REG_REQ 6 +#define MAC_MGMT_MSG_REG_RSP 7 + +#define MAC_MGMT_MSG_PKM_REQ 9 +#define MAC_MGMT_MSG_PKM_RSP 10 +#define MAC_MGMT_MSG_DSA_REQ 11 +#define MAC_MGMT_MSG_DSA_RSP 12 +#define MAC_MGMT_MSG_DSA_ACK 13 +#define MAC_MGMT_MSG_DSC_REQ 14 +#define MAC_MGMT_MSG_DSC_RSP 15 +#define MAC_MGMT_MSG_DSC_ACK 16 +#define MAC_MGMT_MSG_DSD_REQ 17 +#define MAC_MGMT_MSG_DSD_RSP 18 + +#define MAC_MGMT_MSG_MCA_REQ 21 +#define MAC_MGMT_MSG_MCA_RSP 22 +#define MAC_MGMT_MSG_DBPC_REQ 23 +#define MAC_MGMT_MSG_DBPC_RSP 24 +#define MAC_MGMT_MSG_RES_CMD 25 +#define MAC_MGMT_MSG_SBC_REQ 26 +#define MAC_MGMT_MSG_SBC_RSP 27 +#define MAC_MGMT_MSG_CLK_CMP 28 +#define MAC_MGMT_MSG_DREG_CMD 29 +#define MAC_MGMT_MSG_DSX_RVD 30 +#define MAC_MGMT_MSG_TFTP_CPLT 31 +#define MAC_MGMT_MSG_TFTP_RSP 32 +#define MAC_MGMT_MSG_ARQ_FEEDBACK 33 +#define MAC_MGMT_MSG_ARQ_DISCARD 34 +#define MAC_MGMT_MSG_ARQ_RESET 35 +#define MAC_MGMT_MSG_REP_REQ 36 +#define MAC_MGMT_MSG_REP_RSP 37 +#define MAC_MGMT_MSG_FPC 38 +#define MAC_MGMT_MSG_MSH_NCFG 39 +#define MAC_MGMT_MSG_MSH_NENT 40 +#define MAC_MGMT_MSG_MSH_DSCH 41 +#define MAC_MGMT_MSG_MSH_CSCH 42 +#define MAC_MGMT_MSG_MSH_CSCF 43 +#define MAC_MGMT_MSG_AAS_FBCK_REQ 44 +#define MAC_MGMT_MSG_AAS_FBCK_RSP 45 +#define MAC_MGMT_MSG_AAS_BEAM_SELECT 46 +#define MAC_MGMT_MSG_AAS_BEAM_REQ 47 +#define MAC_MGMT_MSG_AAS_BEAM_RSP 48 +#define MAC_MGMT_MSG_DREG_REQ 49 + +#define MAC_MGMT_MSG_MOB_SLP_REQ 50 +#define MAC_MGMT_MSG_MOB_SLP_RSP 51 +#define MAC_MGMT_MSG_MOB_TRF_IND 52 +#define MAC_MGMT_MSG_MOB_NBR_ADV 53 +#define MAC_MGMT_MSG_MOB_SCN_REQ 54 +#define MAC_MGMT_MSG_MOB_SCN_RSP 55 +#define MAC_MGMT_MSG_MOB_BSHO_REQ 56 +#define MAC_MGMT_MSG_MOB_MSHO_REQ 57 +#define MAC_MGMT_MSG_MOB_BSHO_RSP 58 +#define MAC_MGMT_MSG_MOB_HO_IND 59 +#define MAC_MGMT_MSG_MOB_SCN_REP 60 +#define MAC_MGMT_MSG_MOB_PAG_ADV 61 +#define MAC_MGMT_MSG_MBS_MAP 62 +#define MAC_MGMT_MSG_PMC_REQ 63 +#define MAC_MGMT_MSG_PMC_RSP 64 +#define MAC_MGMT_MSG_PRC_LT_CTRL 65 +#define MAC_MGMT_MSG_MOB_ASC_REP 66 +#define MAC_MGMT_MSG_TYPE_MAX 67 + +/* DL-MAP types (Table 276) */ +#define DL_MAP_EXTENDED_2_DIUC 14 +#define DL_MAP_EXTENDED_IE 15 +/* DL-MAP Extended UIUC Code (table 277a) */ +#define DL_MAP_AAS_IE 2 +#define DL_MAP_EXTENDED_CID_SWITCH_IE 4 +#define DL_MAP_HARQ_IE 7 +/* DL-MAP Extended-2 UIUC Code (table 277c) */ +#define DL_MAP_EXTENDED_2_HARQ 7 + +/* UL-MAP types (Table 288) */ +#define UL_MAP_FAST_FEEDBACK_CHANNEL 0 +#define UL_MAP_CDMA_BR_RANGING_IE 12 +#define UL_MAP_PAPR_RECUCTION_ALLOC_SAFETY_ZONE 13 +#define UL_MAP_CDMA_ALLOCATION_IE 14 +#define UL_MAP_EXTENDED_IE 15 +/* UL-MAP Extended UIUC Code (table 290a) */ +#define UL_MAP_CQICH_ALLOCATION_IE 3 + +/* DCD types (Table 358)*/ +#define DCD_DOWNLINK_BURST_PROFILE 1 +#define DCD_BS_EIRP 2 +#define DCD_FRAME_DURATION 3 +#define DCD_PHY_TYPE 4 +#define DCD_POWER_ADJUSTMENT 5 +#define DCD_CHANNEL_NR 6 +#define DCD_TTG 7 +#define DCD_RTG 8 +#define DCD_RSS 9 +#define DCD_EIRXP 9 +#define DCD_CHANNEL_SWITCH_FRAME_NR 10 +#define DCD_FREQUENCY 12 +#define DCD_BS_ID 13 +#define DCD_FRAME_DURATION_CODE 14 +#define DCD_FRAME_NR 15 +#define DCD_SIZE_CQICH_ID 16 +#define DCD_H_ARQ_ACK_DELAY 17 +#define DCD_MAC_VERSION 148 + +#define DCD_RESTART_COUNT 154 + +#define DCD_BURST_FREQUENCY 1 +#define DCD_BURST_FEC_CODE_TYPE 150 +#define DCD_BURST_DIUC_EXIT_THRESHOLD 151 +#define DCD_BURST_DIUC_ENTRY_THRESHOLD 152 +#define DCD_BURST_TCS_ENABLE 153 +/*#define DCD_MAXIMUM_RETRANSMISSION 20*/ +/* TLV types */ +#define DCD_TLV_T_19_PERMUTATION_TYPE_FOR_BROADCAST_REGION_IN_HARQ_ZONE 19 +#define DCD_TLV_T_20_MAXIMUM_RETRANSMISSION 20 +#define DCD_TLV_T_21_DEFAULT_RSSI_AND_CINR_AVERAGING_PARAMETER 21 +#define DCD_TLV_T_22_DL_AMC_ALLOCATED_PHYSICAL_BANDS_BITMAP 22 +#define DCD_TLV_T_34_DL_REGION_DEFINITION 34 +#define DCD_TLV_T_50_HO_TYPE_SUPPORT 50 +#define DCD_TLV_T_31_H_ADD_THRESHOLD 31 +#define DCD_TLV_T_32_H_DELETE_THRESHOLD 32 +#define DCD_TLV_T_33_ASR 33 +#define DCD_TLV_T_34_DL_REGION_DEFINITION 34 +#define DCD_TLV_T_35_PAGING_GROUP_ID 35 +#define DCD_TLV_T_36_TUSC1_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP 36 +#define DCD_TLV_T_37_TUSC2_PERMUTATION_ACTIVE_SUBCHANNELS_BITMAP 37 +#define DCD_TLV_T_51_HYSTERSIS_MARGIN 51 +#define DCD_TLV_T_52_TIME_TO_TRIGGER_DURATION 52 +#define DCD_TLV_T_54_TRIGGER 54 +#define DCD_TLV_T_60_NOISE_AND_INTERFERENCE 60 +#define DCD_TLV_T_153_DOWNLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES 153 +#define DCD_TLV_T_22_DL_AMC_ALLOCATED_PHYSICAL_BANDS_BITMAP 22 +#define DCD_TLV_T_541_TYPE_FUNCTION_ACTION 1 +#define DCD_TLV_T542_TRIGGER_VALUE 2 +#define DCD_TLV_T_543_TRIGGER_AVERAGING_DURATION 3 +#define DCD_TLV_T_45_PAGING_INTERVAL_LENGTH 45 + +/* UCD types (Table 353) */ +#define UCD_UPLINK_BURST_PROFILE 1 +#define UCD_RESERVATION_TIMEOUT 2 +#define UCD_BW_REQ_SIZE 3 +#define UCD_RANGING_REQ_SIZE 4 +#define UCD_FREQUENCY 5 + +#define UCD_TLV_T_7_HO_RANGING_START 7 +#define UCD_TLV_T_8_RANGING_HO_END 8 +#define UCD_INITIAL_RANGING_CODES 150 +#define UCD_PERIODIC_RANGING_CODES 151 +#define UCD_BANDWIDTH_REQUEST_CODES 152 +#define UCD_PERIODIC_RANGING_BACKOFF_START 153 +#define UCD_PERIODIC_RANGING_BACKOFF_END 154 +#define UCD_START_OF_RANGING_CODES_GROUP 155 +#define UCD_PERMUTATION_BASE 156 +#define UCD_UL_ALLOCATED_SUBCHANNELS_BITMAP 157 +#define UCD_TLV_T_158_OPTIONAL_PERMUTATION_UL_ALLOCATED_SUBCHANNELS_BITMAP 158 +#define UCD_TLV_T_159_BAND_AMC_ALLOCATION_THRESHHOLD 159 +#define UCD_TLV_T_160_BAND_AMC_RELEASE_THRESHOLD 160 +#define UCD_TLV_T_161_BAND_AMC_ALLOCATION_TIMER 161 +#define UCD_TLV_T_162_BAND_AMC_RELEASE_TIMER 162 +#define UCD_TLV_T_163_BAND_STATUS_REPORT_MAX_PERIOD 163 +#define UCD_TLV_T_164_BAND_AMC_RETRY_TIMER 164 +#define UCD_TLV_T_170_SAFETY_CHANNEL_RETRY_TIMER 170 +#define UCD_TLV_T_171_HARQ_ACK_DELAY_FOR_DL_BURST 171 + +#define UCD_TLV_T_172_CQICH_BAND_AMC_TRANSITION_DELAY 172 +#define UCD_TLV_T_174_MAXIMUM_RETRANSMISSION 174 +#define UCD_TLV_T_176_SIZE_OF_CQICH_ID_FIELD 176 +#define UCD_TLV_T_177_NORMALIZED_CN_OVERRIDE_2 177 +#define UCD_TLV_T_186_UPPER_BOUND__AAS_PREAMBLE 186 +#define UCD_TLV_T_187_LOWER_BOUND_AAS_PREAMBLE 187 +#define UCD_TLV_T_188_ALLOW_AAS_BEAM_SELECT_MESSAGE 188 +#define UCD_TLV_T_189_USE_CQICH_INDICATION_FLAG 189 +#define UCD_TLV_T_190_MS_SPECIFIC_UP_POWER_OFFSET_ADJUSTMENT_STEP 190 +#define UCD_TLV_T_191_MS_SPECIFIC_DOWN_POWER_OFSET_ADJUSTMENT_STEP 191 +#define UCD_TLV_T_192_MIN_LEVEL_POWER_OFFSET_ADJUSTMENT 192 +#define UCD_TLV_T_193_MAX_LEVEL_POWER_OFFSETR_ADJUSTMENT 193 +#define UCD_TLV_T_194_HANDOVER_RANGING_CODES 194 +#define UCD_TLV_T_195_INITIAL_RANGING_INTERVAL 195 +#define UCD_TLV_T_196_TX_POWER_REPORT 196 +#define UCD_TLV_T_197_NORMALIZED_CN_FOR_CHANNEL_SOUNDING 197 +#define UCD_TLV_T_198_INTIAL_RANGING_BACKOFF_START 198 +#define UCD_TLV_T_199_INITIAL_RANGING_BACKOFF_END 199 +#define UCD_TLV_T_200_BANDWIDTH_REQUESET_BACKOFF_START 200 +#define UCD_TLV_T_201_BANDWIDTH_REQUEST_BACKOFF_END 201 +#define UCD_TLV_T_202_UPLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES 202 +#define UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION 203 +#define UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST 205 +#define UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG 206 +#define UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING 207 +#define UCD_TLV_T_210_FAST_FEEDBACK_REGION 210 +#define UCD_TLV_T_211_HARQ_ACK_REGION 211 +#define UCD_TLV_T_212_RANGING_REGION 212 +#define UCD_TLV_T_213_SOUNDING_REGION 213 + +/* Table 357 */ +#define UCD_BURST_FEC 150 +#define UCD_BURST_RANGING_DATA_RATIO 151 +/*#define UCD_BURST_POWER_BOOST 151*/ +/*#define UCD_BURST_TCS_ENABLE 152*/ + +/* RNG-REQ types (Table 364) */ +/* Sorted these values */ +#define RNG_REQ_DL_BURST_PROFILE 1 +#define RNG_REQ_SS_MAC_ADDRESS 2 +#define RNG_REQ_RANGING_ANOMALIES 3 +#define RNG_REQ_AAS_BROADCAST 4 +#define RNG_REQ_SERVING_BS_ID 5 +#define RNG_REQ_RANGING_PURPOSE_INDICATION 6 +#define RNG_REQ_HO_ID 7 +#define RNG_REQ_POWER_DOWN_INDICATOR 8 +#define RNG_REQ_PAGING_CONTROLLER_ID 9 +#define RNG_REQ_MAC_HASH_SKIP_THRESHOLD 10 +#define RNG_REQ_ENABLED_ACTION_TRIGGERED 11 +#define RNG_REQ_REQUESTED_DNLK_REP_CODING_LEVEL 12 +#define RNG_REQ_CMAC_KEY_COUNT 13 +#define RNG_REQ_POWER_SAVING_CLASS_PARAMETERS 21 + +/* RNG-REQ/RSP Power Saving Class Parameter TLV's (Table 364a) */ +#define RNG_POWER_SAVING_CLASS_FLAGS 1 +#define RNG_POWER_SAVING_CLASS_ID 2 +#define RNG_POWER_SAVING_CLASS_TYPE 3 +#define RNG_START_FRAME_NUMBER 4 +#define RNG_INITIAL_SLEEP_WINDOW 5 +#define RNG_LISTENING_WINDOW 6 +#define RNG_FINAL_SLEEP_WINDOW_BASE 7 +#define RNG_FINAL_SLEEP_WINDOW_EXPONENT 8 +#define RNG_SLPID 9 +#define RNG_CID 10 +#define RNG_DIRECTION 11 + +/* RNG-RSP types (Table 367) */ +#define RNG_RSP_TIMING_ADJUST 1 +#define RNG_RSP_POWER_LEVEL_ADJUST 2 +#define RNG_RSP_OFFSET_FREQ_ADJUST 3 +#define RNG_RSP_RANGING_STATUS 4 +#define RNG_RSP_DL_FREQ_OVERRIDE 5 +#define RNG_RSP_UL_CHANNEL_ID_OVERRIDE 6 +#define RNG_RSP_DL_OPERATIONAL_BURST_PROFILE 7 +#define RNG_RSP_SS_MAC_ADDRESS 8 +#define RNG_RSP_BASIC_CID 9 +#define RNG_RSP_PRIMARY_MGMT_CID 10 +#define RNG_RSP_AAS_BROADCAST_PERMISSION 11 +#define RNG_RSP_FRAME_NUMBER 12 +#define RNG_RSP_OPPORTUNITY_NUMBER 13 +#define RNG_RSP_SERVICE_LEVEL_PREDICTION 17 +#define RNG_RSP_GLOBAL_SERVICE_CLASS_NAME 18 +#define RNG_RSP_RESOURCE_RETAIN_FLAG 20 +#define RNG_RSP_HO_PROCESS_OPTIMIZATION 21 +/* Sorted the following values (for readability) */ +#define RNG_RSP_HO_ID 22 +#define RNG_RSP_LOCATION_UPDATE_RESPONSE 23 +#define RNG_RSP_PAGING_INFORMATION 24 +#define RNG_RSP_PAGING_CONTROLLER_ID 25 +#define RNG_RSP_NEXT_PERIODIC_RANGING 26 +#define RNG_RSP_POWER_SAVING_CLASS_PARAMETERS 27 +#define RNG_RSP_MAC_HASH_SKIP_THRESHOLD 28 +#define RNG_RSP_SBC_RSP_ENCODINGS 29 +#define RNG_RSP_REG_RSP_ENCODINGS 30 +#define RNG_RSP_SA_CHALLENGE_TUPLE 31 +#define RNG_RSP_ENABLED_ACTION_TRIGGERED 32 +#define RNG_RSP_DL_OP_BURST_PROFILE_OFDMA 33 +#define RNG_RSP_RANGING_CODE_ATTRIBUTES 150 +#define RNG_RSP_SA_CHALLENGE_BS_RANDOM 1 +#define RNG_RSP_SA_CHALLENGE_AKID 2 + +/* SBC types (section 11.8) */ +#define SBC_BW_ALLOC_SUPPORT 1 +#define SBC_TRANSITION_GAPS 2 +#define SBC_REQ_MAX_TRANSMIT_POWER 3 +#define SBC_MAC_PDU 4 +#define SBC_PKM_FLOW_CONTROL 15 +#define SBC_AUTH_POLICY_SUPPORT 16 +#define SBC_MAX_SECURITY_ASSOCIATIONS 17 +#define SBC_REQ_CURR_TRANSMITTED_POWER 147 +#define SBC_SS_FFT_SIZES 150 +#define SBC_SS_DEMODULATOR 151 +#define SBC_SS_MODULATOR 152 +#define SBC_SS_NUM_UL_ARQ_ACK_CHANNEL 153 +#define SBC_SS_PERMUTATION_SUPPORT 154 +#define SBC_SS_DEMODULATOR_MIMO_SUPPORT 156 +#define SBC_SS_MIMO_UPLINK_SUPPORT 157 +#define SBC_SS_OFDMA_AAS_PRIVATE_MAP_SUPPORT 158 +#define SBC_SS_OFDMA_AAS_CAPABILITIES 159 +#define SBC_SS_CINR_MEASUREMENT_CAPABILITY 160 +#define SBC_SS_NUM_DL_ARQ_ACK_CHANNEL 161 + +#define SBC_TLV_T_26_POWER_SAVE_CLASS_TYPES_CAPABILITY 26 +#define SBC_TLV_T_28_HO_TRIGGER_METRIC_SUPPORT 28 +#define SBC_TLV_T_27_EXTENSION_CAPABILITY 27 + +#define SBC_TLV_T_162_HARQ_INCREMENTAL_REDUNDANCY_BUFFER_CAPABILITY 162 +#define SBC_TLV_T_163_HARQ_CHASE_COMBINING_AND_CC_IR_BUFFER_CAPABILITY 163 +#define SBC_TLV_T_167_ASSOCIATION_SUPPORT 167 +#define SBC_TLV_T_170_UPLINK_POWER_CONTROL_SUPPORT 170 +#define SBC_TLV_T_171_MINIMUM_NUM_OF_FRAMES 171 +#define SBC_TLV_T_172 172 +#define SBC_TLV_T_173_UL_CONTROL_CHANNEL_SUPPORT 173 +#define SBC_TLV_T_174_OFDMA_MS_CSIT_CAPABILITY 174 +#define SBC_TLV_T_175_MAX_NUM_BST_PER_FRM_CAPABILITY_HARQ 175 +#define SBC_TLV_T_176 176 +#define SBC_TLV_T_177_OFDMA_SS_MODULATOR_FOR_MIMO_SUPPORT 177 +#define SBC_TLV_T_178_SDMA_PILOT_CAPABILITY 178 +#define SBC_TLV_T_179_OFDMA_MULTIPLE_DL_BURST_PROFILE_CAPABILITY 179 +#define SBC_TLV_T_204_OFDMA_PARAMETERS_SETS 204 + +/* DREG-REQ DREG-CMD types (Sections 6.3.2.3.42 and 6.3.2.3.26) */ +#define DREG_PAGING_INFO 1 +#define DREG_REQ_DURATION 2 +#define DREG_PAGING_CONTROLLER_ID 3 +#define DREG_IDLE_MODE_RETAIN_INFO 4 +#define DREG_MAC_HASH_SKIP_THRESHOLD 5 +#define DREG_PAGING_CYCLE_REQUEST 52 + +/* REP-REQ types (Sections 11.11) */ +#define REP_REQ_REPORT_REQUEST 1 +/* REP-REQ report request subtypes */ +#define REP_REQ_REPORT_TYPE 1 +#define REP_REQ_CHANNEL_NUMBER 2 +#define REP_REQ_CHANNEL_TYPE 3 +#define REP_REQ_ZONE_SPEC_PHY_CINR_REQ 4 +#define REP_REQ_PREAMBLE_PHY_CINR_REQ 5 +#define REP_REQ_ZONE_SPEC_EFF_CINR_REQ 6 +#define REP_REQ_PREAMBLE_EFF_CINR_REQ 7 +#define REP_REQ_CHANNEL_SELECTIVITY_REPORT 8 + +/* REP-RSP types (Sections 11.12) */ +#define REP_RSP_REPORT_TYPE 1 +#define REP_RSP_CHANNEL_TYPE 2 +#define REP_RSP_ZONE_SPECIFIC_PHY_CINR 3 +#define REP_RSP_PREAMBLE_PHY_CINR 4 +#define REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR 5 +#define REP_RSP_PREAMBLE_EFFECTIVE_CINR 6 +/* REP-RSP report subtypes */ +#define REP_RSP_REPORT_CHANNEL_NUMBER 1 +#define REP_RSP_REPORT_START_FRAME 2 +#define REP_RSP_REPORT_DURATION 3 +#define REP_RSP_REPORT_BASIC_REPORT 4 +#define REP_RSP_REPORT_CINR_REPORT 5 +#define REP_RSP_REPORT_RSSI_REPORT 6 +/* REP-RSP channel type report subtypes */ +#define REP_RSP_CHANNEL_TYPE_SUBCHANNEL 1 +#define REP_RSP_CHANNEL_TYPE_BAND_AMC 2 +#define REP_RSP_CHANNEL_TYPE_SAFETY_CHANNEL 3 +#define REP_RSP_CHANNEL_TYPE_ENHANCED_BAND_AMC 4 +#define REP_RSP_CHANNEL_TYPE_SOUNDING 5 +/* REP-RSP zone-specific physical CINR report subtypes */ +#define REP_RSP_ZONE_SPECIFIC_PHY_CINR_PUSC_SC0 1 +#define REP_RSP_ZONE_SPECIFIC_PHY_CINR_PUSC_SC1 2 +#define REP_RSP_ZONE_SPECIFIC_PHY_CINR_FUSC 3 +#define REP_RSP_ZONE_SPECIFIC_PHY_CINR_OPTIONAL_FUSC 4 +#define REP_RSP_ZONE_SPECIFIC_PHY_CINR_SAFETY_CHANNEL 5 +#define REP_RSP_ZONE_SPECIFIC_PHY_CINR_AMC 6 +/* REP-RSP preamble physical CINR report subtypes */ +#define REP_RSP_PREAMBLE_PHY_CINR_CONFIGURATION1 1 +#define REP_RSP_PREAMBLE_PHY_CINR_CONFIGURATION3 2 +#define REP_RSP_PREAMBLE_PHY_CINR_BAND_AMC 3 +/* REP-RSP zone-specific effective CINR report subtypes */ +#define REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_PUSC_SC0 1 +#define REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_PUSC_SC1 2 +#define REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_FUSC 3 +#define REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_OPTIONAL_FUSC 4 +#define REP_RSP_ZONE_SPECIFIC_EFFECTIVE_CINR_AMC_AAS 5 +/* REP-RSP preamble effective CINR report subtypes */ +#define REP_RSP_PREAMBLE_EFFECTIVE_CINR_CONFIGURATION1 1 +#define REP_RSP_PREAMBLE_EFFECTIVE_CINR_CONFIGURATION3 2 +#define REP_RSP_CHANNEL_SELECTIVITY 3 +/* REP-RSP channel selectivity report subtypes */ +#define FREQUENCY_SELECTIVITY_REPORT 1 + +/* REG types (Section 11.7) */ +#define REG_ARQ_PARAMETERS 1 +#define REG_SS_MGMT_SUPPORT 2 +#define REG_IP_MGMT_MODE 3 +#define REG_IP_VERSION 4 +#define REG_REQ_SECONDARY_MGMT_CID 5 +#define REG_RSP_SECONDARY_MGMT_CID 5 +#define REG_UL_TRANSPORT_CIDS_SUPPORTED 6 +#define REG_IP_PHS_SDU_ENCAP 7 +#define REG_MAX_CLASSIFIERS_SUPPORTED 8 +#define REG_PHS_SUPPORT 9 +#define REG_ARQ_SUPPORT 10 +#define REG_DSX_FLOW_CONTROL 11 +#define REG_MAC_CRC_SUPPORT 12 +#define REG_MCA_FLOW_CONTROL 13 +#define REG_MCAST_POLLING_CIDS 14 +#define REG_NUM_DL_TRANS_CID 15 +#if 0 /* WIMAX_16E_2005 changes this to SBC scope */ +#define REG_PKM_FLOW_CONTROL 15 +#define REG_AUTH_POLICY_SUPPORT 16 +#define REG_MAX_SECURITY_ASSOCIATIONS 17 +#endif +#if 0 /* TODO: scope has been changed to SBC scope */ +#define REG_DL_TRANSPORT_CIDS_SUPPORTED 15 +#endif +#define REG_MAC_ADDRESS 18 + +#define REG_TLV_T_20_MAX_MAC_DATA_PER_FRAME_SUPPORT 20 +#define REG_TLV_T_20_1_MAX_MAC_LEVEL_DATA_PER_DL_FRAME 1 +#define REG_TLV_T_20_2_MAX_MAC_LEVEL_DATA_PER_UL_FRAME 2 +#define REG_TLV_T_21_PACKING_SUPPORT 21 +#define REG_TLV_T_22_MAC_EXTENDED_RTPS_SUPPORT 22 +#define REG_TLV_T_23_MAX_NUM_BURSTS_TRANSMITTED_CONCURRENTLY_TO_THE_MS 23 +#define REG_RSP_TLV_T_24_CID_UPDATE_ENCODINGS 24 +#define REG_RSP_TLV_T_24_1_CID_UPDATE_ENCODINGS_NEW_CID 1 +#define REG_RSP_TLV_T_24_2_CID_UPDATE_ENCODINGS_SFID 2 +#define REG_RSP_TLV_T_24_3_CID_UPDATE_ENCODINGS_CONNECTION_INFO 3 +#define REG_RSP_TLV_T_25_COMPRESSED_CID_UPDATE_ENCODINGS 25 +#define REG_TLV_T_26_METHOD_FOR_ALLOCATING_IP_ADDR_SECONDARY_MGMNT_CONNECTION 26 +#define REG_TLV_T_27_HANDOVER_SUPPORTED 27 +#define REG_RSP_TLV_T_28_HO_SYSTEM_RESOURCE_RETAIN_TIME 28 +#define REG_TLV_T_29_HO_PROCESS_OPTIMIZATION_MS_TIMER 29 +#define REG_RSP_TLV_T_30_MS_HANDOVER_RETRANSMISSION_TIMER 30 +#define REG_TLV_T_31_MOBILITY_FEATURES_SUPPORTED 31 +#define REG_REQ_TLV_T_32_SLEEP_MODE_RECOVERY_TIME 32 +#define REG_REQ_TLV_T_33_MS_PREV_IP_ADDR 33 +#define REG_RSP_TLV_T_34_SKIP_ADDR_ACQUISITION 34 +#define REG_RSP_TLV_T_35_SAID_UPDATE_ENCODINGS 35 +#define REG_RSP_TLV_T_35_1_NEW_SAID 1 +#define REG_RSP_TLV_T_35_2_OLD_SAID 2 +#define REG_RSP_TLV_T_36_TOTAL_PROVISIONED_SERVICE_FLOW_DSAs 36 +#define REG_TLV_T_37_IDLE_MODE_TIMEOUT 37 +#define REG_RSP_TLV_T_38_SA_TEK_UPDATE 38 +#define REG_RSP_TLV_T_38_1_SA_TEK_UPDATE_TYPE 1 +#define REG_RSP_TLV_T_38_2_NEW_SAID 2 +#define REG_RSP_TLV_T_38_3_OLD_SAID 3 +#define REG_RSP_TLV_T_38_4_OLD_TEK_PARAMETERS 4 +#define REG_RSP_TLV_T_38_5_NEW_TEK_GTEK_PARAMETERS 5 +#define REG_RSP_TLV_T_38_6_GKEK_PARAMETERS 6 +#define REG_RSP_TLV_T_39_GKEK_PARAMETERS 39 +#define REG_TLV_T_40_ARQ_ACK_TYPE 40 +#define REG_TLV_T_41_MS_HO_CONNECTIONS_PARAM_PROCESSING_TIME 41 +#define REG_TLV_T_42_MS_HO_TEK_PROCESSING_TIME 42 +#define REG_TLV_T_43_MAC_HEADER_AND_EXTENDED_SUBHEADER_SUPPORT 43 +#define REG_RSP_TLV_T_44_SN_REPORTING_BASE 44 +#define REG_REQ_TLV_T_45_MS_PERIODIC_RANGING_TIMER_INFO 45 +#define REG_HANDOVER_INDICATION_READINESS_TIMER 46 +#define REG_REQ_BS_SWITCHING_TIMER 47 +#define REG_POWER_SAVING_CLASS_CAPABILITY 48 + + + +/* PKM types (Table 370) */ +#define PKM_ATTR_DISPLAY_STRING 6 +#define PKM_ATTR_AUTH_KEY 7 +#define PKM_ATTR_TEK 8 +#define PKM_ATTR_KEY_LIFE_TIME 9 +#define PKM_ATTR_KEY_SEQ_NUM 10 +#define PKM_ATTR_HMAC_DIGEST 11 +#define PKM_ATTR_SAID 12 +#define PKM_ATTR_TEK_PARAM 13 +#define PKM_ATTR_CBC_IV 15 +#define PKM_ATTR_ERROR_CODE 16 +#define PKM_ATTR_CA_CERTIFICATE 17 +#define PKM_ATTR_SS_CERTIFICATE 18 +#define PKM_ATTR_SECURITY_CAPABILITIES 19 +#define PKM_ATTR_CRYPTO_SUITE 20 +#define PKM_ATTR_CRYPTO_LIST 21 +#define PKM_ATTR_VERSION 22 +#define PKM_ATTR_SA_DESCRIPTOR 23 +#define PKM_ATTR_SA_TYPE 24 +#define PKM_ATTR_SECURITY_NEGOTIATION_PARAMETERS 25 +#define PKM_ATTR_PKM_CONFIG_SETTINGS 27 +#define PKM_ATTR_PKM_EAP_PAYLOAD 28 +#define PKM_ATTR_PKM_NONCE 29 +#define PKM_ATTR_AUTH_RESULT_CODE 30 +#define PKM_ATTR_SA_SERVICE_TYPE 31 +#define PKM_ATTR_FRAME_NUMBER 32 +#define PKM_ATTR_SS_RANDOM 33 +#define PKM_ATTR_BS_RANDOM 34 +#define PKM_ATTR_PRE_PAK 35 +#define PKM_ATTR_PAK_AK_SEQ_NUMBER 36 +#define PKM_ATTR_BS_CERTIFICATE 37 +#define PKM_ATTR_SIG_BS 38 +#define PKM_ATTR_MS_MAC_ADDRESS 39 +#define PKM_ATTR_CMAC_DIGEST 40 +#define PKM_ATTR_KEY_PUSH_MODES 41 +#define PKM_ATTR_KEY_PUSH_COUNTER 42 +#define PKM_ATTR_GKEK 43 +#define PKM_ATTR_SIG_SS 44 +#define PKM_ATTR_AKID 45 +#define PKM_ATTR_ASSOCIATED_GKEK_SEQ_NUM 46 +#define PKM_ATTR_GKEK_PARAMETERS 47 + +#define PKM_ATTR_PKM_CONFIG_SETTINGS_AUTHORIZE_WAIT_TIMEOUT 1 +#define PKM_ATTR_PKM_CONFIG_SETTINGS_REAUTHORIZE_WAIT_TIMEOUT 2 +#define PKM_ATTR_PKM_CONFIG_SETTINGS_AUTHORIZATION_GRACE_TIME 3 +#define PKM_ATTR_PKM_CONFIG_SETTINGS_OPERATIONAL_WAIT_TIMEOUT 4 +#define PKM_ATTR_PKM_CONFIG_SETTINGS_REKEY_WAIT_TIMEOUT 5 +#define PKM_ATTR_PKM_CONFIG_SETTINGS_TEK_GRACE_TIME 6 +#define PKM_ATTR_PKM_CONFIG_SETTINGS_AUTHORIZE_REJECT_WAIT_TIMEOUT 7 + +#define PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_PKM_VERSION_SUPPORT 1 +#define PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_AUTHORIZATION_POLICY_SUPPORT 2 +#define PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_MESSAGE_AUTHENTICATION_CODE 3 +#define PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_PN_WINDOW_SIZE 4 +#define PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_PKM_FLOW_CONTROL 5 +#define PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_MAX_SUPPT_SECURITY_ASSNS 6 + +/* Common TLV Encoding types (Table 346) */ +#define SHORT_HMAC_TUPLE_COR2 140 +#define CMAC_TUPLE 141 +#define VENDOR_SPECIFIC_INFO 143 +#define VENDOR_ID_ENCODING 144 +#define DSx_UPLINK_FLOW 145 +#define DSx_DOWNLINK_FLOW 146 +#define CURRENT_TX_POWER 147 +#define MAC_VERSION_ENCODING 148 +#define HMAC_TUPLE 149 +#define SHORT_HMAC_TUPLE 150 + +/* Section 11.13.18 */ +#define ARQ_ENABLE 18 +#define ARQ_WINDOW_SIZE 19 +#define ARQ_TRANSMITTER_DELAY 20 +#define ARQ_RECEIVER_DELAY 21 +#define ARQ_BLOCK_LIFETIME 22 +#define ARQ_SYNC_LOSS_TIMEOUT 23 +#define ARQ_DELIVER_IN_ORDER 24 +#define ARQ_RX_PURGE_TIMEOUT 25 +#define ARQ_BLOCK_SIZE 26 + +/* Section 6.2.3.2.26 */ + +/* Service Flow Encodings (SFE) (Table 383) */ +#define SFE_SF_ID 1 +#define SFE_CID 2 +#define SFE_SERVICE_CLASS_NAME 3 +#define SFE_MBS_SERVICE 4 +#define SFE_QOS_PARAMS_SET 5 +#define SFE_TRAFFIC_PRIORITY 6 +#define SFE_MAX_STR 7 +#define SFE_MAX_TRAFFIC_BURST 8 +#define SFE_MIN_RTR 9 +#define SFE_RESERVED_10 10 +#define SFE_UL_SCHEDULING 11 +#define SFE_TX_POLICY 12 +#define SFE_TOLERATED_JITTER 13 +#define SFE_MAX_LATENCY 14 +#define SFE_FIXED_LEN_SDU 15 +#define SFE_SDU_SIZE 16 +#define SFE_TARGET_SAID 17 +#define SFE_ARQ_ENABLE 18 +#define SFE_ARQ_WINDOW_SIZE 19 +#define SFE_ARQ_TRANSMITTER_DELAY 20 +#define SFE_ARQ_RECEIVER_DELAY 21 +#define SFE_ARQ_BLOCK_LIFETIME 22 +#define SFE_ARQ_SYNC_LOSS_TIMEOUT 23 +#define SFE_ARQ_DELIVER_IN_ORDER 24 +#define SFE_ARQ_RX_PURGE_TIMEOUT 25 +#define SFE_ARQ_BLOCK_SIZE 26 +#define SFE_RESERVED_27 27 +#define SFE_CS_SPECIFICATION 28 +#define SFE_TYPE_OF_DATA_DELIVERY_SERVICES 29 +#define SFE_SDU_INTER_ARRIVAL_INTERVAL 30 +#define SFE_TIME_BASE 31 +#define SFE_PAGING_PREFERENCE 32 +#define SFE_MBS_ZONE_IDENTIFIER_ASSIGNMENT 33 +#define SFE_RESERVED_34 34 +#define SFE_GLOBAL_SERVICE_CLASS_NAME 35 +#define SFE_RESERVED_36 36 +#define SFE_SN_FEEDBACK_ENABLED 37 +#define SFE_FSN_SIZE 38 +#define SFE_CID_ALLOCATION_FOR_ACTIVE_BS 39 +#define SFE_UNSOLICITED_GRANT_INTERVAL 40 +#define SFE_UNSOLOCITED_POLLING_INTERVAL 41 +#define SFE_PDU_SN_EXT_SUBHEADER_HARQ_REORDER 42 +#define SFE_MBS_CONTENTS_ID 43 +#define SFE_HARQ_SERVICE_FLOWS 44 +#define SFE_AUTHORIZATION_TOKEN 45 +#define SFE_HARQ_CHANNEL_MAPPING 46 + +/* Convergence Servicerameter Encoding Rules (Section 11.13.19.2) */ +#define SFE_CSPER_ATM 99 +#define SFE_CSPER_PACKET_IPV4 100 +#define SFE_CSPER_PACKET_IPV6 101 +#define SFE_CSPER_PACKET_802_3 102 +#define SFE_CSPER_PACKET_802_1Q 103 +#define SFE_CSPER_PACKET_IPV4_802_3 104 +#define SFE_CSPER_PACKET_IPV6_802_3 105 +#define SFE_CSPER_PACKET_IPV4_802_1Q 106 +#define SFE_CSPER_PACKET_IPV6_802_1Q 107 +#define SFE_CSPER_PACKET_IP_ROCH_COMPRESSION 108 +#define SFE_CSPER_PACKET_IP_ECRTP_COMPRESSION 109 +#define SFE_CSPER_PACKET_IP_802_3_ROCH_COMPRESSION 110 +#define SFE_CSPER_PACKET_IP_802_3_ECRTP_COMPRESSION 111 + +/* Section 11.13.19.3 */ +#define CST_CLASSIFIER_ACTION 1 +#define CST_CLASSIFIER_ERROR_PARAM_SET 2 +#define CST_PACKET_CLASSIFICATION_RULE 3 +#define CST_PHS_DSC_ACTION 4 +#define CST_PHS_ERROR_PARAM_SET 5 +#define CST_PHS_RULE 6 + +/* Section 11.13.19.3.3 */ +#define CST_ERROR_SET_ERRORED_PARAM 1 +#define CST_ERROR_SET_ERROR_CODE 2 +#define CST_ERROR_SET_ERROR_MSG 3 + +/* Section 11.13.19.4 */ +#define CST_ATM_SWITCHING 1 +#define CST_ATM_CLASSIFIER 2 +#define CST_ATM_CLASSIFIER_DSC_ACTION 3 +#define CST_ATM_CLASSIFIER_ERROR_PARAMETER_SET 4 + +#define ATM_VPI_CLASSIFIER 1 +#define ATM_VCI_CLASSIFIER 2 +#define ATM_CLASSIFIER_ID 3 + +/* Section 11.13.19.3.4 */ +#define CST_PKT_CLASS_RULE_PRIORITY 1 +#define CST_PKT_CLASS_RULE_RANGE_MASK 2 +#define CST_PKT_CLASS_RULE_PROTOCOL 3 +#define CST_PKT_CLASS_RULE_SRC_IP 4 +#define CST_PKT_CLASS_RULE_DST_IP 5 +#define CST_PKT_CLASS_RULE_SRCPORT_RANGE 6 +#define CST_PKT_CLASS_RULE_DSTPORT_RANGE 7 +#define CST_PKT_CLASS_RULE_DST_MAC 8 +#define CST_PKT_CLASS_RULE_SRC_MAC 9 +#define CST_PKT_CLASS_RULE_ETHERTYPE 10 +#define CST_PKT_CLASS_RULE_USER_PRIORITY 11 +#define CST_PKT_CLASS_RULE_VLAN_ID 12 +#define CST_PKT_CLASS_RULE_PHSI 13 +#define CST_PKT_CLASS_RULE_INDEX 14 +#define CST_PKT_CLASS_RULE_IPv6_FLOW_LABEL 15 +#define CST_PKT_CLASS_RULE_LARGE_CONTEXT_ID 16 +#define CST_PKT_CLASS_RULE_SHORT_FORMAT_CONTEXT_ID 18 +#define CST_CLASSIFIER_ACTION_RULE 19 +#define CST_PKT_CLASS_RULE_VENDOR_SPEC 143 + +/* Section 11.13.19.3.7 */ +#define CST_PHS_PHSI 1 +#define CST_PHS_PHSF 2 +#define CST_PHS_PHSM 3 +#define CST_PHS_PHSS 4 +#define CST_PHS_PHSV 5 +#define CST_PHS_VENDOR_SPEC 143 + +#endif /* WIMAX_MAC_H */ diff --git a/plugins/epan/wimax/wimax_pdu_decoder.c b/plugins/epan/wimax/wimax_pdu_decoder.c new file mode 100644 index 00000000..a7e7eaf2 --- /dev/null +++ b/plugins/epan/wimax/wimax_pdu_decoder.c @@ -0,0 +1,255 @@ +/* wimax_pdu_decoder.c + * WiMax PDU Burst decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "crc.h" +#include "wimax-int.h" +#include "wimax_utils.h" + +extern gint proto_wimax; + +void proto_reg_handoff_wimax_pdu(void); + +static dissector_handle_t mac_generic_decoder_handle = NULL; +static dissector_handle_t mac_header_type1_handle = NULL; +static dissector_handle_t mac_header_type2_handle = NULL; +static dissector_handle_t wimax_harq_map_handle = NULL; + +#define WIMAX_PDU_PADDING_MASK 0xFF +#define WIMAX_INVALID_PDU_MASK 0xF0 +#define WIMAX_MAP_TYPE_MASK 0xE0 /* 0b111 */ +#define WIMAX_HARQ_MAP_MSG_IND 0xE0 /* 0b111 */ +#define WIMAX_COMPRESSED_DL_MAP_IND 0xC0 /* 0b110 */ +#define REDUCED_PRIVATE_MAP_MASK 0x0C /* 0b11 */ + +#define WIMAX_MAC_HEADER_SIZE 6 +#define WIMAX_MAC_HEADER_INFO_FIELDS 5 +#define WIMAX_MAC_HEADER_HT_FIELD 0x80 +#define WIMAX_MAC_HEADER_EC_FIELD 0x40 +#define WIMAX_MAC_HEADER_LENGTH_MSB_MASK 0x07 + +#define WIMAX_HARQ_MAP_MSG_LENGTH_MASK1 0x07FC +/* Global Variables. */ +gboolean first_gmh; + +static gint proto_wimax_pdu_decoder = -1; +static gint ett_wimax_pdu_decoder = -1; + +static int hf_wimax_value_bytes = -1; + +static int dissect_wimax_pdu_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset; + guint mac_ht, mac_ec; + guint first_byte, length; + guint mac_hcs, mac_hcs_calculated; + proto_item *pdu_item = NULL; + proto_tree *pdu_tree = NULL; + +#ifndef STATIC_DATA + /* generate the table of CRC32 remainders for all possible bytes */ + wimax_mac_gen_crc32_table(); + /* generate the table of CRC8 remainders for all possible bytes */ + wimax_mac_gen_crc8_table(); +#endif + + /* parsing the PDU burst */ + for(offset = 0; offset < tvb_reported_length(tvb); ) + { + if (offset == 0) + { + first_gmh = TRUE; + } + else + { + first_gmh = FALSE; + } + /* get the length of the remainder */ + length = tvb_reported_length_remaining(tvb, offset); + /* get the first byte at offset */ + first_byte = tvb_get_guint8(tvb, offset); + /* check for padding */ + if(first_byte == WIMAX_PDU_PADDING_MASK) + { /* Padding */ + /* display message */ + pdu_item = proto_tree_add_protocol_format(tree, proto_wimax_pdu_decoder, tvb, offset, length, "Padding (%u bytes)", length); + /* add subtree */ + pdu_tree = proto_item_add_subtree(pdu_item, ett_wimax_pdu_decoder); + /* display the padding in Hex */ + proto_tree_add_item(pdu_tree, hf_wimax_value_bytes, tvb, offset, length, ENC_NA); + break; + } + else if((first_byte & WIMAX_MAP_TYPE_MASK) == WIMAX_HARQ_MAP_MSG_IND) + { /* HARQ MAP message (no mac header) */ + /* get the HARQ MAp Message Length */ + length = ((tvb_get_ntohs(tvb, offset) & WIMAX_HARQ_MAP_MSG_LENGTH_MASK1) >> 2); + if (length == 0) + { + length = 3; /* At least 3 bytes. This prevents endless loop */ + } + call_dissector(wimax_harq_map_handle, tvb_new_subset_length(tvb,offset,length), pinfo, tree); + offset += length; + continue; + } + else if((first_byte & WIMAX_MAP_TYPE_MASK) == WIMAX_COMPRESSED_DL_MAP_IND) + { + if(is_down_link(pinfo)) + { /* decode compressed dl-map without mac header */ + if ((first_byte & REDUCED_PRIVATE_MAP_MASK) == REDUCED_PRIVATE_MAP_MASK) + { + length = wimax_decode_dlmap_reduced_aas(tvb, pinfo, tree); + } + else + { + length = wimax_decode_dlmapc(tvb, pinfo, tree); + } + offset += length; + continue; + } + } + else if((first_byte & WIMAX_INVALID_PDU_MASK) == WIMAX_INVALID_PDU_MASK) + { /* Invalid PDU */ + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid PDU"); + /* display message */ + pdu_item = proto_tree_add_protocol_format(tree, proto_wimax_pdu_decoder, tvb, offset, length, "Invalid PDU (%u bytes)", length); + /* add subtree */ + pdu_tree = proto_item_add_subtree(pdu_item, ett_wimax_pdu_decoder); + /* display the invalid MAC Header in Hex */ + proto_tree_add_item(pdu_tree, hf_wimax_value_bytes, tvb, offset, length, ENC_NA); + break; + } + /* calculate the MAC header HCS */ + mac_hcs_calculated = wimax_mac_calc_crc8(tvb_get_ptr(tvb, offset, WIMAX_MAC_HEADER_INFO_FIELDS), WIMAX_MAC_HEADER_INFO_FIELDS); + /* get the Header Check Sequence (HCS) in the header */ + mac_hcs = tvb_get_guint8(tvb, offset + WIMAX_MAC_HEADER_SIZE - 1); + /* verify the HCS */ + if(mac_hcs != mac_hcs_calculated) + { + /* update the info column */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "MAC Header CRC error"); + /* display message */ + pdu_item = proto_tree_add_protocol_format(tree, proto_wimax_pdu_decoder, tvb, offset, WIMAX_MAC_HEADER_SIZE, "MAC Header CRC error %X (in header) and %X (calculated)", mac_hcs, mac_hcs_calculated); + /* add subtree */ + pdu_tree = proto_item_add_subtree(pdu_item, ett_wimax_pdu_decoder); + /* display the bad MAC Header in Hex */ + proto_tree_add_item(pdu_tree, hf_wimax_value_bytes, tvb, offset, length, ENC_NA); + break; + } + /* get the Header Type (HT) */ + mac_ht = ((first_byte & WIMAX_MAC_HEADER_HT_FIELD)?1:0); + /* get the Encryption Control (EC) */ + mac_ec = ((first_byte & WIMAX_MAC_HEADER_EC_FIELD)?1:0); + /* update the MAC length for Generic MAC frame */ + if(!mac_ht) + { /* Generic MAC Header with payload */ + /* get the MAC length */ + length = (tvb_get_guint8(tvb, offset+1) & WIMAX_MAC_HEADER_LENGTH_MSB_MASK); + length = ((length<<8) | tvb_get_guint8(tvb, offset+2)); + } + else /* MAC signaling Headers or Bandwidth Request Headers */ + { /* set the mac length */ + length = WIMAX_MAC_HEADER_SIZE; + } + /* display PDU frame info */ + /* + pdu_item = proto_tree_add_protocol_format(tree, proto_wimax_pdu_decoder, tvb, offset, length, "PDU Frame (%u bytes)", length); + */ + pdu_item = proto_tree_add_protocol_format(tree, proto_wimax_pdu_decoder, tvb, offset, length, "PDU (%u bytes)", length); + /* add PDU subtree */ + pdu_tree = proto_item_add_subtree(pdu_item, ett_wimax_pdu_decoder); + if (length == 0) { + offset += 6; /* Add header size. */ + /* Must skip the code below or tvb_new_subset_length() + * keeps allocating memory until it runs out. */ + continue; + } + /* process the valid MAC header */ + if(mac_ht) + { /* MAC signaling Headers or Bandwidth Request Headers */ + /* check the header type */ + if(mac_ec) + { /* MAC Signaling Header Type II Header */ + proto_item_append_text(pdu_item, " - Mac Type II Header: "); + call_dissector(mac_header_type2_handle, tvb_new_subset_length(tvb,offset,length), pinfo, pdu_tree); + } + else + { /* MAC Signaling Header Type I Header */ + proto_item_append_text(pdu_item, " - Mac Type I Header: "); + call_dissector(mac_header_type1_handle, tvb_new_subset_length(tvb,offset,length), pinfo, pdu_tree); + } + } + else /* Generic MAC Header with payload */ + { + call_dissector(mac_generic_decoder_handle, tvb_new_subset_length(tvb,offset,length), pinfo, pdu_tree); + } + offset += length; + } + return tvb_captured_length(tvb); +} + +/* Register Wimax PDU Burst Protocol */ +void wimax_proto_register_wimax_pdu(void) +{ + /* PDU display */ + static hf_register_info hf[] = + { + { + &hf_wimax_value_bytes, + { + "Values", "wmx.pdu.value", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL + } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_wimax_pdu_decoder, + }; + + proto_wimax_pdu_decoder = proto_wimax; + + register_dissector("wimax_pdu_burst_handler", dissect_wimax_pdu_decoder, proto_wimax_pdu_decoder); + proto_register_field_array(proto_wimax_pdu_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + +void +wimax_proto_reg_handoff_wimax_pdu(void) +{ + mac_generic_decoder_handle = find_dissector("mac_header_generic_handler"); + mac_header_type1_handle = find_dissector("mac_header_type_1_handler"); + mac_header_type2_handle = find_dissector("mac_header_type_2_handler"); + wimax_harq_map_handle = find_dissector("wimax_harq_map_handler"); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_phy_attributes_decoder.c b/plugins/epan/wimax/wimax_phy_attributes_decoder.c new file mode 100644 index 00000000..25572401 --- /dev/null +++ b/plugins/epan/wimax/wimax_phy_attributes_decoder.c @@ -0,0 +1,178 @@ +/* wimax_phy_attributes_decoder.c + * WiMax PDU Burst Physical Attributes decoder + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* Include files */ + +#include "config.h" + +#include +#include "wimax-int.h" + +extern gint proto_wimax; + +static gint proto_wimax_phy_attributes_decoder = -1; +static gint ett_wimax_phy_attributes_decoder = -1; + +static const value_string vals_subchannel_types[] = +{ + { 0, "DL PUSC"}, + { 1, "DL FUSC"}, + {16, "UL PUSC"}, + {0, NULL} +}; + +static const value_string vals_modulation_rates[] = +{ + {0, "BPSK R=1/2"}, + {1, "QPSK R=1/2"}, + {2, "QPSK R=3/4"}, + {3, "16-QAM R=1/2"}, + {4, "16-QAM R=3/4"}, + {5, "64-QAM R=1/2"}, + {6, "64-QAM R=2/3"}, + {7, "64-QAM R=3/4"}, + {8, "64-QAM R=5/6"}, + {0, NULL} +}; + +static const value_string vals_encoding_types[] = +{ + {0, "Tail biting convolutional coding (CCTB)"}, + {1, "Convolutional turbo coding (CTC)"}, + {0, NULL} +}; + +static gint hf_phy_attributes_subchannelization_type = -1; +static gint hf_phy_attributes_permbase = -1; +static gint hf_phy_attributes_modulation_rate = -1; +static gint hf_phy_attributes_encoding_type = -1; +static gint hf_phy_attributes_num_repeat = -1; +static gint hf_phy_attributes_symbol_offset = -1; +static gint hf_phy_attributes_num_of_slots = -1; +static gint hf_phy_attributes_subchannel = -1; + + + +static int dissect_wimax_phy_attributes_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + guint offset = 0; + guint tvb_len; +/* guint num_of_slots;*/ + proto_item *phy_item = NULL; + proto_tree *phy_tree = NULL; + + /* update the info column */ + /*col_append_str(pinfo->cinfo, COL_INFO, "PDU Burst Physical Attributes:");*/ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "PHY-attr"); + if (tree) + { /* we are being asked for details */ + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* display PDU Burst Physical Attributes dissector info */ + phy_item = proto_tree_add_protocol_format(tree, proto_wimax_phy_attributes_decoder, tvb, offset, tvb_len, "PDU Burst Physical Attributes (%u bytes)", tvb_len); + /* add PDU Burst Physical Attributes subtree */ + phy_tree = proto_item_add_subtree(phy_item, ett_wimax_phy_attributes_decoder); + /* display the subchannelization type */ + proto_tree_add_item(phy_tree, hf_phy_attributes_subchannelization_type, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the permbase */ + proto_tree_add_item(phy_tree, hf_phy_attributes_permbase, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the modulation rate */ + proto_tree_add_item(phy_tree, hf_phy_attributes_modulation_rate, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the encoding type */ + proto_tree_add_item(phy_tree, hf_phy_attributes_encoding_type, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the numRepeat */ + proto_tree_add_item(phy_tree, hf_phy_attributes_num_repeat, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the symbol offset */ + proto_tree_add_item(phy_tree, hf_phy_attributes_symbol_offset, tvb, offset++, 1, ENC_BIG_ENDIAN); + /* display the number of slots */ + proto_tree_add_item(phy_tree, hf_phy_attributes_num_of_slots, tvb, offset, 2, ENC_BIG_ENDIAN); + /* get the number of slots */ +/* num_of_slots = tvb_get_guint16(tvb, offset);*/ + /* move to next field */ + offset += 2; + /* display the physical subchannel list */ + while(offset < tvb_len) + { + proto_tree_add_item(phy_tree, hf_phy_attributes_subchannel, tvb, offset++, 1, ENC_BIG_ENDIAN); + } + } + return tvb_captured_length(tvb); +} + +/* Register Wimax PDU Burst Physical Attributes Protocol */ +void wimax_proto_register_wimax_phy_attributes(void) +{ + /* Physical Attributes display */ + static hf_register_info hf[] = + { + { + &hf_phy_attributes_subchannelization_type, + {"Subchannelization Type", "wmx.phy_attributes.subchannelization_type", FT_UINT8, BASE_DEC, VALS(vals_subchannel_types), 0x0, NULL, HFILL} + }, + { + &hf_phy_attributes_permbase, + {"Permbase", "wmx.phy_attributes.permbase", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_phy_attributes_modulation_rate, + {"Modulation Rate", "wmx.phy_attributes.modulation_rate", FT_UINT8, BASE_DEC, VALS(vals_modulation_rates), 0x0, NULL, HFILL} + }, + { + &hf_phy_attributes_encoding_type, + {"Encoding Type", "wmx.phy_attributes.encoding_type", FT_UINT8, BASE_DEC, VALS(vals_encoding_types), 0x0, NULL, HFILL} + }, + { + &hf_phy_attributes_num_repeat, + {"numRepeat", "wmx.phy_attributes.num_repeat", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_phy_attributes_symbol_offset, + {"Symbol Offset", "wmx.phy_attributes.symbol_offset", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_phy_attributes_num_of_slots, + {"Number Of Slots", "wmx.phy_attributes.num_of_slots", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_phy_attributes_subchannel, + {"Subchannel", "wmx.phy_attributes.subchannel", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + } + }; + + /* Setup protocol subtree array */ + static gint *ett[] = + { + &ett_wimax_phy_attributes_decoder + }; + + proto_wimax_phy_attributes_decoder = proto_wimax; + + register_dissector("wimax_phy_attributes_burst_handler", dissect_wimax_phy_attributes_decoder, proto_wimax_phy_attributes_decoder); + + proto_register_field_array(proto_wimax_phy_attributes_decoder, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_tlv.c b/plugins/epan/wimax/wimax_tlv.c new file mode 100644 index 00000000..fe06728b --- /dev/null +++ b/plugins/epan/wimax/wimax_tlv.c @@ -0,0 +1,175 @@ +/* wimax_tlv.c + * WiMax TLV handling functions + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include "wimax_tlv.h" + +/*************************************************************/ +/* init_tlv_info() */ +/* retrive the tlv information from specified tvb and offset */ +/* parameter: */ +/* info - pointer of a tlv information data structure */ +/* return: */ +/* 0-success */ +/* !=0-the invalid size of the TLV length (failed) */ +/*************************************************************/ +gint init_tlv_info(tlv_info_t *info, tvbuff_t *tvb, gint offset) +{ + guint tlv_len; + + /* get TLV type */ + info->type = (guint8)tvb_get_guint8( tvb, offset ); + /* get TLV length */ + tlv_len = (guint)tvb_get_guint8( tvb, (offset + 1) ); + /* set the TLV value offset */ + info->value_offset = 2; + /* adjust for multiple-byte TLV length */ + if((tlv_len & WIMAX_TLV_EXTENDED_LENGTH_MASK) != 0) + { /* multiple bytes TLV length */ + info->length_type = 1; + /* get the size of the TLV length */ + tlv_len = (tlv_len & WIMAX_TLV_LENGTH_MASK); + info->size_of_length = tlv_len; + /* update the TLV value offset */ + info->value_offset += tlv_len; + switch (tlv_len) + { + case 0: + info->length = 0; /* no length */ + break; + case 1: + info->length = (gint32)tvb_get_guint8( tvb, (offset + 2) ); /* 8 bit */ + break; + case 2: + info->length = (gint32)tvb_get_ntohs( tvb, (offset + 2) ); /* 16 bit */ + break; + case 3: + info->length = (gint32)tvb_get_ntoh24( tvb, (offset + 2) ); /* 24 bit */ + break; + case 4: + info->length = (gint32)tvb_get_ntohl( tvb, (offset + 2) ); /* 32 bit */ + break; + default: + /* mark invalid tlv */ + info->valid = 0; + /* failed, return the invalid size of the tlv length */ + return (gint)tlv_len; + break; + } + } + else /* single byte length */ + { + info->length_type = 0; + info->size_of_length = 0; + info->length = (gint32)tlv_len; + } + /* mark valid tlv */ + info->valid = 1; + /* success */ + return 0; +} + +/*************************************************************/ +/* get_tlv_type() */ +/* get the tlv type of the specified tlv information */ +/* parameter: */ +/* info - pointer of a tlv information data structure */ +/* return: */ +/* >=0 - TLV type */ +/* =-1 - invalid tlv info */ +/*************************************************************/ +gint get_tlv_type(tlv_info_t *info) +{ + if(info->valid) + return (gint)info->type; + return -1; +} + +/**************************************************************/ +/* get_tlv_size_of_length() */ +/* get the size of tlv length of the specified tlv information*/ +/* parameter: */ +/* info - pointer of a tlv information data structure */ +/* return: */ +/* >=0 - the size of TLV length */ +/* =-1 - invalid tlv info */ +/**************************************************************/ +gint get_tlv_size_of_length(tlv_info_t *info) +{ + if(info->valid) + return (gint)info->size_of_length; + return -1; +} + +/*************************************************************/ +/* get_tlv_length() */ +/* get the tlv length of the specified tlv information */ +/* parameter: */ +/* info - pointer of a tlv information data structure */ +/* return: */ +/* >=0 - TLV length */ +/* =-1 - invalid tlv info */ +/*************************************************************/ +gint32 get_tlv_length(tlv_info_t *info) +{ + if(info->valid) + return (gint32)info->length; + return -1; +} + +/*************************************************************/ +/* get_tlv_value_offset() */ +/* get the tlv value offset of the specified tlv information */ +/* parameter: */ +/* info - pointer of a tlv information data structure */ +/* return: */ +/* >0 - TLV value offset in byte */ +/* =-1 - invalid tlv info */ +/*************************************************************/ +gint get_tlv_value_offset(tlv_info_t *info) +{ + if(info->valid) + return (gint)info->value_offset; + return -1; +} + +/*************************************************************/ +/* get_tlv_length_type() */ +/* get the tlv length type of the specified tlv information */ +/* parameter: */ +/* info - pointer of a tlv information data structure */ +/* return: */ +/* 0 - single byte TLV length */ +/* 1 - multiple bytes TLV length */ +/*************************************************************/ +gint get_tlv_length_type(tlv_info_t *info) +{ + if(info->valid) + return (gint)info->length_type; + return -1; +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_tlv.h b/plugins/epan/wimax/wimax_tlv.h new file mode 100644 index 00000000..0011c563 --- /dev/null +++ b/plugins/epan/wimax/wimax_tlv.h @@ -0,0 +1,45 @@ +/* wimax_tlv.h + * WiMax TLV handling function header file + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef _WIMAX_TLV_H_ +#define _WIMAX_TLV_H_ + +#include + +#define WIMAX_TLV_EXTENDED_LENGTH_MASK 0x80 +#define WIMAX_TLV_LENGTH_MASK 0x7F + +#define MAX_TLV_LEN 64000 + +typedef struct +{ + guint8 valid; /* TLV info status: 0=invalid; 1=valid */ + guint8 type; /* TLV type */ + guint8 length_type; /* length type: 0=single byte; 1=multiple bytes */ + guint8 size_of_length; /* size of the TLV length */ + guint value_offset; /* the offset of TLV value field */ + gint32 length; /* length of TLV value field */ +} tlv_info_t; + +gint init_tlv_info(tlv_info_t *info, tvbuff_t *tvb, gint offset); +gint valid_tlv_info(tlv_info_t *info); +gint get_tlv_type(tlv_info_t *info); +gint get_tlv_length_type(tlv_info_t *info); +gint get_tlv_size_of_length(tlv_info_t *info); +gint get_tlv_value_offset(tlv_info_t *info); +gint32 get_tlv_length(tlv_info_t *info); +proto_item *add_tlv_subtree(tlv_info_t *info, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, const guint encoding); +proto_tree *add_tlv_subtree_no_item(tlv_info_t *info, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start); +proto_tree *add_protocol_subtree(tlv_info_t *info, gint idx, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length, const char *label); + +#endif /* WIMAX_TLV_H */ diff --git a/plugins/epan/wimax/wimax_utils.c b/plugins/epan/wimax/wimax_utils.c new file mode 100644 index 00000000..226c536a --- /dev/null +++ b/plugins/epan/wimax/wimax_utils.c @@ -0,0 +1,3385 @@ +/* wimax_utils.c + * WiMax Utility Decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* +#define DEBUG +*/ + +#include "config.h" + +#include +#include +#include "wimax-int.h" +#include "wimax_tlv.h" +#include "wimax_mac.h" + +#include "wimax_utils.h" + +extern gint proto_mac_mgmt_msg_rng_req_decoder; +extern gint proto_mac_mgmt_msg_reg_req_decoder; + +extern gint mac_sdu_length; /* declared in packet-wmx.c */ +extern gboolean include_cor2_changes; + +static gint proto_wimax_utility_decoders = -1; +static gint ett_wimax_service_flow_encodings = -1; +static gint ett_wimax_cst_encoding_rules = -1; +static gint ett_wimax_error_parameter_set = -1; +static gint ett_wimax_hmac_tuple = -1; +static gint ett_wimax_cmac_tuple = -1; +static gint ett_wimax_short_hmac_tuple = -1; +static gint ett_security_negotiation_parameters = -1; +static gint ett_pkm_tlv_encoded_attributes_decoder = -1; +static gint ett_sa_descriptor_decoder = -1; +static gint ett_cryptographic_suite_list_decoder = -1; +static gint ett_security_capabilities_decoder = -1; +static gint ett_vendor_specific_info_decoder = -1; +static gint ett_vendor_id_encoding_decoder = -1; +static gint ett_ul_service_flow_decoder = -1; +static gint ett_dl_service_flow_decoder = -1; + +static dissector_handle_t eap_handle = NULL; + +const unit_name_string wimax_units_byte_bytes = { " byte", " bytes" }; +const unit_name_string wimax_units_bit_sec = { "bits/s", NULL }; +const unit_name_string wimax_units_db = { "dB", NULL }; +const unit_name_string wimax_units_dbm = { "dBm", NULL }; +const unit_name_string wimax_units_frame_frames = { " frame", " frames" }; +const unit_name_string wimax_units_frame_offset = { " frame offset", NULL }; +const unit_name_string wimax_units_hz = { "Hz", NULL }; +const unit_name_string wimax_units_khz = { "kHz", NULL }; +const unit_name_string wimax_units_ms = { "ms", NULL }; +const unit_name_string wimax_units_ps = { "PS", NULL }; + + +/* The following two variables save the Scheduling Service type for + the Grant Management subheader dissector and track whether or not + one has been seen. + */ +static guint scheduling_service_type = -1; +gint seen_a_service_type = 0; + +/* The following two functions set and access the variables above */ +guint get_service_type( void ) +{ + return scheduling_service_type; +} + +static void set_service_type( guint set_to ) +{ + if( seen_a_service_type == 0 ){ + scheduling_service_type = set_to; + seen_a_service_type = 1; + } +} + +/* Setup protocol subtree array */ +static gint *ett[] = +{ + &ett_wimax_service_flow_encodings, + &ett_wimax_cst_encoding_rules, + &ett_wimax_error_parameter_set, + &ett_wimax_hmac_tuple, + &ett_wimax_cmac_tuple, + &ett_wimax_short_hmac_tuple, + &ett_security_negotiation_parameters, + &ett_pkm_tlv_encoded_attributes_decoder, + &ett_sa_descriptor_decoder, + &ett_cryptographic_suite_list_decoder, + &ett_security_capabilities_decoder, + &ett_vendor_specific_info_decoder, + &ett_vendor_id_encoding_decoder, + &ett_ul_service_flow_decoder, + &ett_dl_service_flow_decoder, +}; + +static const value_string vals_mbs_service[] = +{ + {0, "No available MBS"}, + {1, "Single-BS-MBS"}, + {2, "Multi-BS-MBS"}, + {0, NULL} +}; + +static const value_string vals_ul_grant_scheduling[] = +{ + {0, "Reserved"}, + {1, "Undefined (BS implementation-dependent)"}, + {2, "BE (default)"}, + {3, "nrtPS"}, + {4, "rtPS"}, + {5, "Extended rtPS"}, + {6, "UGS"}, + {0, NULL} +}; + +static const value_string vals_fixed_len_sdu[] = +{ + {0, "Variable-length SDUs (default)"}, + {1, "Fixed-length SDUs"}, + {0, NULL} +}; + +static const value_string vals_arq_enable[] = +{ + {0, "ARQ not requested/accepted"}, + {1, "ARQ requested/accepted"}, + {0, NULL} +}; +#if 0 +static const value_string vals_arq_block_lifetime[] = +{ + {0, "Infinite"}, + {0, NULL} +}; +#endif +static const value_string vals_arq_sync_loss_timeout[] = +{ + {0, "Infinite"}, + {0, NULL} +}; + +static const value_string vals_arq_deliver_in_order[] = +{ + {0, "Order of delivery is not preserved"}, + {1, "Order of delivery is preserved"}, + {0, NULL} +}; +static const value_string vals_arq_rx_purge_timeout[] = +{ + {0, "Infinite"}, + {0, NULL} +}; + +static const value_string vals_fsn_size[] = +{ + {0, "3-bit FSN"}, + {1, "11-bit FSN (default)"}, + {0, NULL} +}; + +static const value_string vals_sn_fb_enable[] = +{ + {0, "Is disabled (default)"}, + {1, "Is enabled"}, + {0, NULL} +}; + +static const value_string vals_harq[] = +{ + {0, "Non HARQ (default)"}, + {1, "HARQ connection" }, + {0, NULL} +}; + +static const value_string vals_cs_specification[] = +{ + { 0, "Reserved"}, + { 1, "Packet, IPv4"}, + { 2, "Packet, IPv6"}, + { 3, "Packet, IEEE 802.3/Ethernet"}, + { 4, "Packet, IEEE 802.1Q VLAN"}, + { 5, "Packet, IPv4 over IEEE 802.3/Ethernet"}, + { 6, "Packet, IPv6 over IEEE 802.3/Ethernet"}, + { 7, "Packet, IPv4 over IEEE 802.1Q VLAN"}, + { 8, "Packet, IPv6 over IEEE 802.1Q VLAN"}, + { 9, "ATM"}, + {10, "Packet, IEEE 802.3/Ethernet with ROCH header compression"}, + {11, "Packet, IEEE 802.3/Ethernet with ECRTP header compression"}, + {12, "Packet, IP2 with ROCH header compression"}, + {13, "Packet, IP2 with ECRTP header compression"}, + {0, NULL} +}; + +static const value_string vals_type_of_data_delivery_services[] = +{ + {0, "Continuing grant service"}, + {1, "Real time variable rate service"}, + {2, "Non-real time variable rate service"}, + {3, "Best-efforts service"}, + {4, "Extended real-time variable rate service"}, + {0, NULL} +}; + +static const value_string vals_paging_preference[] = +{ + {0, "No paging generation"}, + {1, "Paging generation"}, + {0, NULL} +}; +static const value_string vals_pdu_sn_ext_subheader[] = +{ + {0, "No support for PDU SN in this connection (default)"}, + {1, "PDU SN (short) extended Subheader"}, + {2, "PDU SN (long) extended Subheader"}, + {0, NULL} +}; + +static const value_string vals_cst_classifier_action[] = +{ + {0, "DSC Add Classifier"}, + {1, "DSC Replace Classifier"}, + {2, "DSC Delete Classifier"}, + {0, NULL} +}; + +static const value_string vals_cst_phs_dsc_action[] = +{ + {0, "Add PHS rule"}, + {1, "Set PHS rule"}, + {2, "Delete PHS rule"}, + {3, "Delete all PHS rules"}, + {0, NULL} +}; + +static const value_string vals_verify[] = +{ + {0, "Verify"}, + {1, "Don't verify"}, + {0, NULL} +}; + +static const value_string vals_atm_switching_encodings[] = +{ + {0, "No switching methodology applied"}, + {1, "VP switching"}, + {2, "VC switching"}, + {0, NULL} +}; + +static const value_string vals_cc[] = +{ + { 0, "OK/success"}, + { 1, "Reject-other"}, + { 2, "Reject-unrecognized-configuration-setting"}, + { 3, "Reject-temporary / reject-resource"}, + { 4, "Reject-permanent / reject-admin"}, + { 5, "Reject-not-owner"}, + { 6, "Reject-service-flow-not-found"}, + { 7, "Reject-service-flow-exists"}, + { 8, "Reject-required-parameter-not-present"}, + { 9, "Reject-header-suppression"}, + {10, "Reject-unknown-transaction-id"}, + {11, "Reject-authentication-failure"}, + {12, "Reject-add-aborted"}, + {13, "Reject-exceeded-dynamic-service-limit"}, + {14, "Reject-not-authorized-for-the-request-SAID"}, + {15, "Reject-fail-to-establish-the-requested-SA"}, + {16, "Reject-not-supported-parameter"}, + {17, "Reject-not-supported-parameter-value"}, + {0, NULL} +}; + +static const value_string vals_classification_action_rule[] = +{ + {0, "None"}, + {1, "Discarded packet"}, + {0, NULL} +}; + +static const true_false_string tfs_supported = +{ + "supported", + "not supported" +}; + +#if 0 +static const true_false_string disabled_enabled = +{ + "enabled", + "disabled" +}; +#endif + +#if 0 +static const true_false_string default_enabled = +{ + "enabled", + "use default action" +}; +#endif + +static const value_string vals_pkm_attr_error_codes[] = +{ /* table 373 */ + {0, "All (no information)"}, + {1, "Auth Reject Auth Invalid (unauthorized SS)"}, + {2, "Auth Reject, Key Reject (unauthorized SAID)"}, + {3, "Auth Invalid (unsolicited)"}, + {4, "Auth Invalid, TEK Invalid (invalid key sequence number)"}, + {5, "Auth Invalid (message (key request) authorization failure)"}, + {6, "Auth Reject (permanent authorization failure)"}, + {0, NULL} +}; + +static const value_string vs_sa_type[] = +{ + {0, "Primary"}, + {1, "Static"}, + {2, "Dynamic"}, + {0, NULL} +}; + +static const value_string va_key_push_modes[] = +{ + {0, "GKEK update mode"}, + {1, "GTEK update mode"}, + {0, NULL} +}; + +#if 0 +static const value_string vals_pkm_version[] = +{ + {0, "Reserved"}, + {1, "PKM (Initial standard release"}, + {0, NULL} +}; +#endif + +static const value_string vs_success_reject[] = +{ + {0, "Success"}, + {1, "Reject"}, + {0, NULL} +}; + +static const value_string vs_sa_service_type[] = +{ + {0, "Unicast service"}, + {1, "Group multicast service"}, + {2, "MBS service"}, + {0, NULL} +}; + +static const value_string vals_data_encryption_ids[] = +{ /* table 375 */ + {0, "No data encryption"}, + {1, "CBC-Mode, 56-bit DES"}, + {2, "CCM-Mode, 128-bit AES"}, + {3, "CBC-Mode, 128-bit AES"}, + {128, "CTR-Mode, 128-bit AES for MBS with 8 bit ROC"}, + {0, NULL} +}; + +static const value_string vals_data_authentication_ids[] = +{ /* table 376 */ + {0, "No data authentication"}, + {1, "CCM-Mode, 128-bit AES"}, + {0, NULL} +}; + +static const value_string vals_tek_encryption_ids[] = +{ /* table 377 */ + {0, "No TEK encryption"}, + {1, "3-DES EDE with 128-bit key"}, + {2, "RSA with 1024-bit key"}, + {3, "ECB mode AES with 128-bit key"}, + {4, "AES key wrap with 128-bit key"}, + {0, NULL} +}; + +static const value_string vals_dcd_mac_version[] = +{ + {1, "Conformance with IEEE Std 802.16-2001"}, + {2, "Conformance with IEEE Std 802.16c-2002 and its predecessors"}, + {3, "Conformance with IEEE Std 802.16a-2003 and its predecessors"}, + {4, "Conformance with IEEE Std 802.16-2004"}, + {5, "Conformance with IEEE Std 802.16-2004 and IEEE Std 802.16e-2005"}, + {6, "reserved"}, + {0, NULL} +}; + +/* fix fields */ +static gint hf_sfe_unknown_type = -1; +static gint hf_sfe_sf_id = -1; +static gint hf_sfe_cid = -1; +static gint hf_sfe_service_class_name = -1; +static gint hf_sfe_mbs_service = -1; +static gint hf_sfe_qos_params_set = -1; +static gint hf_sfe_set_provisioned = -1; +static gint hf_sfe_set_admitted = -1; +static gint hf_sfe_set_active = -1; +static gint hf_sfe_set_rsvd = -1; +static gint hf_sfe_traffic_priority = -1; +static gint hf_sfe_max_str = -1; +static gint hf_sfe_max_traffic_burst = -1; +static gint hf_sfe_min_rtr = -1; +static gint hf_sfe_reserved_10 = -1; +static gint hf_sfe_ul_grant_scheduling = -1; +static gint hf_sfe_req_tx_policy = -1; +static gint hf_sfe_policy_broadcast_bwr = -1; +static gint hf_sfe_policy_multicast_bwr = -1; +static gint hf_sfe_policy_piggyback = -1; +static gint hf_sfe_policy_fragment = -1; +static gint hf_sfe_policy_headers = -1; +static gint hf_sfe_policy_packing = -1; +static gint hf_sfe_policy_crc = -1; +static gint hf_sfe_policy_rsvd1 = -1; +static gint hf_sfe_jitter = -1; +static gint hf_sfe_max_latency = -1; +static gint hf_sfe_fixed_len_sdu = -1; +static gint hf_sfe_sdu_size = -1; +static gint hf_sfe_target_said = -1; +static gint hf_sfe_cs_specification = -1; +static gint hf_sfe_type_of_data_delivery_services = -1; +static gint hf_sfe_sdu_inter_arrival_interval = -1; +static gint hf_sfe_time_base = -1; +static gint hf_sfe_paging_preference = -1; +static gint hf_sfe_mbs_zone_identifier_assignment = -1; +static gint hf_sfe_sn_feedback_enabled = -1; +static gint hf_sfe_harq_service_flows = -1; +static gint hf_sfe_harq_channel_mapping_index = -1; +static gint hf_sfe_fsn_size = -1; +static gint hf_sfe_unsolicited_grant_interval = -1; +static gint hf_sfe_unsolicited_polling_interval = -1; +/* static gint hf_sfe_harq_channel_mapping = -1; */ +static gint hf_sfe_global_service_class_name = -1; +static gint hf_sfe_reserved_36 = -1; +static gint hf_sfe_reserved_34 = -1; + +static gint hf_sfe_arq_enable = -1; +static gint hf_sfe_arq_transmitter_delay = -1; +static gint hf_sfe_arq_receiver_delay = -1; +static gint hf_sfe_arq_block_lifetime = -1; +static gint hf_sfe_arq_sync_loss_timeout = -1; +static gint hf_sfe_arq_transmitter_delay_cor2 = -1; +static gint hf_sfe_arq_receiver_delay_cor2 = -1; +static gint hf_sfe_arq_block_lifetime_cor2 = -1; +static gint hf_sfe_arq_sync_loss_timeout_cor2 = -1; +static gint hf_sfe_arq_deliver_in_order = -1; +static gint hf_sfe_arq_rx_purge_timeout = -1; +static gint hf_sfe_arq_window_size = -1; +static gint hf_sfe_arq_block_size = -1; +static gint hf_sfe_arq_block_size_cor2 = -1; +static gint hf_sfe_arq_min_block_size = -1; +static gint hf_sfe_arq_max_block_size = -1; + +/* static gint hf_sfe_cid_alloc_for_active_bs = -1; */ +static gint hf_sfe_cid_alloc_for_active_bs_cid = -1; +static gint hf_sfe_pdu_sn_ext_subheader_reorder = -1; +static gint hf_sfe_mbs_contents_ids = -1; +static gint hf_sfe_mbs_contents_ids_id = -1; +static gint hf_sfe_authorization_token = -1; + +static gint hf_cst_classifier_dsc_action = -1; +static gint hf_cst_error_set_errored_param = -1; +static gint hf_cst_error_set_error_code = -1; +static gint hf_cst_error_set_error_msg = -1; + +static gint hf_cst_pkt_class_rule = -1; + +static gint hf_cst_pkt_class_rule_priority = -1; +static gint hf_cst_pkt_class_rule_range_mask = -1; +static gint hf_cst_pkt_class_rule_tos_low = -1; +static gint hf_cst_pkt_class_rule_tos_high = -1; +static gint hf_cst_pkt_class_rule_tos_mask = -1; +static gint hf_cst_pkt_class_rule_protocol = -1; +/*static gint hf_cst_pkt_class_rule_protocol_number = -1;*/ +static gint hf_cst_pkt_class_rule_ip_masked_src_address = -1; +static gint hf_cst_pkt_class_rule_ip_masked_dest_address = -1; +static gint hf_cst_pkt_class_rule_src_ipv4 = -1; +static gint hf_cst_pkt_class_rule_dest_ipv4 = -1; +static gint hf_cst_pkt_class_rule_mask_ipv4 = -1; +static gint hf_cst_pkt_class_rule_src_ipv6 = -1; +static gint hf_cst_pkt_class_rule_dest_ipv6 = -1; +static gint hf_cst_pkt_class_rule_mask_ipv6 = -1; +static gint hf_cst_pkt_class_rule_prot_src_port_range = -1; +static gint hf_cst_pkt_class_rule_src_port_low = -1; +static gint hf_cst_pkt_class_rule_src_port_high = -1; +static gint hf_cst_pkt_class_rule_prot_dest_port_range = -1; +static gint hf_cst_pkt_class_rule_dest_port_low = -1; +static gint hf_cst_pkt_class_rule_dest_port_high = -1; +static gint hf_cst_pkt_class_rule_dest_mac_address = -1; +static gint hf_cst_pkt_class_rule_dest_mac = -1; +static gint hf_cst_pkt_class_rule_src_mac_address = -1; +static gint hf_cst_pkt_class_rule_src_mac = -1; +static gint hf_cst_pkt_class_rule_mask_mac = -1; +static gint hf_cst_pkt_class_rule_ethertype = -1; +static gint hf_cst_pkt_class_rule_etype = -1; +static gint hf_cst_pkt_class_rule_eprot1 = -1; +static gint hf_cst_pkt_class_rule_eprot2 = -1; +static gint hf_cst_pkt_class_rule_user_priority = -1; +static gint hf_cst_pkt_class_rule_pri_low = -1; +static gint hf_cst_pkt_class_rule_pri_high = -1; +static gint hf_cst_pkt_class_rule_vlan_id = -1; +static gint hf_cst_pkt_class_rule_vlan_id1 = -1; +static gint hf_cst_pkt_class_rule_vlan_id2 = -1; +static gint hf_cst_pkt_class_rule_phsi = -1; +static gint hf_cst_pkt_class_rule_index = -1; +static gint hf_cst_pkt_class_rule_ipv6_flow_label = -1; +static gint hf_cst_pkt_class_rule_vendor_spec = -1; +static gint hf_cst_pkt_class_rule_classifier_action_rule = -1; +static gint hf_cst_pkt_class_rule_classifier_action_rule_bit0 = -1; +static gint hf_cst_pkt_class_rule_classifier_action_rule_bit1 = -1; + +static gint hf_cst_large_context_id = -1; +static gint hf_cst_short_format_context_id = -1; + +static gint hf_cst_phs_dsc_action = -1; +static gint hf_cst_phs_rule = -1; +static gint hf_cst_phs_phsi = -1; +static gint hf_cst_phs_phsf = -1; +static gint hf_cst_phs_phsm = -1; +static gint hf_cst_phs_phss = -1; +static gint hf_cst_phs_phsv = -1; +static gint hf_cst_phs_vendor_spec = -1; +static gint hf_cst_invalid_tlv = -1; + +static gint hf_csper_atm_switching_encoding = -1; +static gint hf_csper_atm_classifier = -1; +static gint hf_csper_atm_classifier_vpi = -1; +static gint hf_csper_atm_classifier_vci = -1; +static gint hf_csper_atm_classifier_id = -1; +/*static gint hf_csper_atm_classifier_dsc_action = -1;*/ +static gint hf_csper_unknown_type = -1; + +static gint hf_xmac_tuple_rsvd = -1; +static gint hf_xmac_tuple_key_seq_num = -1; +static gint hf_hmac_tuple_hmac_digest = -1; +static gint hf_packet_number_counter = -1; +static gint hf_cmac_tuple_cmac_value = -1; +static gint hf_cmac_tuple_bsid = -1; + +/* bit masks */ +/* 11.13.4 */ +#define SFE_QOS_PARAMS_SET_PROVISIONED_SET 0x01 +#define SFE_QOS_PARAMS_SET_ADMITTED_SET 0x02 +#define SFE_QOS_PARAMS_SET_ACTIVE_SET 0x04 +#define SFE_QOS_PARAMS_SET_RESERVED 0xF8 +/* 11.13.12 */ +#define SFE_REQ_TX_POLICY_BROADCAST_BWR 0x01 +#define SFE_REQ_TX_POLICY_MULTICAST_BWR 0x02 +#define SFE_REQ_TX_POLICY_PIGGYBACK 0x04 +#define SFE_REQ_TX_POLICY_FRAGMENT_DATA 0x08 +#define SFE_REQ_TX_POLICY_PAYLOAD_HEADER 0x10 +#define SFE_REQ_TX_POLICY_PACKINGS 0x20 +#define SFE_REQ_TX_POLICY_CRC 0x40 +#define SFE_REQ_TX_POLICY_RESERVED 0x80 + +/* bit masks */ +/* 11.13.19.3.4.17 */ +#define CST_PKT_CLASS_RULE_CLASSIFIER_ACTION_RULE_BIT0 0x80 +#define CST_PKT_CLASS_RULE_CLASSIFIER_ACTION_RULE_RSV 0x7F + +/* bit masks */ +/* 11.1.2 (table 348) */ +#define XMAC_TUPLE_RESERVED 0xF0 +#define XMAC_TUPLE_KEY_SEQ_NUM 0x0F + +/* WiMax Security Negotiation Parameters display */ +static gint hf_snp_pkm_version_support = -1; +static gint hf_snp_pkm_version_support_bit0 = -1; +static gint hf_snp_pkm_version_support_bit1 = -1; +static gint hf_snp_pkm_version_support_reserved = -1; +static gint hf_snp_auth_policy_support = -1; +static gint hf_snp_auth_policy_support_bit0 = -1; +static gint hf_snp_auth_policy_support_bit1 = -1; +static gint hf_snp_auth_policy_support_bit2 = -1; +static gint hf_snp_auth_policy_support_bit3 = -1; +static gint hf_snp_auth_policy_support_bit4 = -1; +static gint hf_snp_auth_policy_support_bit5 = -1; +static gint hf_snp_auth_policy_support_bit6 = -1; +static gint hf_snp_auth_policy_support_bit7 = -1; +static gint hf_snp_mac_mode = -1; +static gint hf_snp_mac_mode_bit0 = -1; +static gint hf_snp_mac_mode_bit1 = -1; +static gint hf_snp_mac_mode_bit1_rsvd = -1; +static gint hf_snp_mac_mode_bit2 = -1; +static gint hf_snp_mac_mode_bit3 = -1; +static gint hf_snp_mac_mode_bit4 = -1; +static gint hf_snp_mac_mode_bit5 = -1; +static gint hf_snp_mac_mode_reserved = -1; +static gint hf_snp_mac_mode_reserved1 = -1; +static gint hf_snp_pn_window_size = -1; +static gint hf_snp_max_conc_transactions = -1; +static gint hf_snp_max_suppt_sec_assns = -1; +static gint hf_snp_unknown_type = -1; + +/* bit masks */ +/* 11.8.4.1 */ +#define SNP_PKM_VERSION_SUPPORT_BIT0 0x01 +#define SNP_PKM_VERSION_SUPPORT_BIT1 0x02 +#define SNP_PKM_VERSION_SUPPORT_RSV 0xFC +/* 11.8.4.2 */ +#define SNP_AUTH_POLICY_SUPPORT_BIT0 0x01 +#define SNP_AUTH_POLICY_SUPPORT_BIT1 0x02 +#define SNP_AUTH_POLICY_SUPPORT_BIT2 0x04 +#define SNP_AUTH_POLICY_SUPPORT_BIT3 0x08 +#define SNP_AUTH_POLICY_SUPPORT_BIT4 0x10 +#define SNP_AUTH_POLICY_SUPPORT_BIT5 0x20 +#define SNP_AUTH_POLICY_SUPPORT_BIT6 0x40 +#define SNP_AUTH_POLICY_SUPPORT_BIT7 0x80 +/* 11.8.4.3 */ +#define SNP_MAC_MODE_BIT0 0x01 +#define SNP_MAC_MODE_BIT1 0x02 +#define SNP_MAC_MODE_BIT2 0x04 +#define SNP_MAC_MODE_BIT3 0x08 +#define SNP_MAC_MODE_BIT4 0x10 +#define SNP_MAC_MODE_BIT5 0x20 +#define SNP_MAC_MODE_RSV 0xE0 +#define SNP_MAC_MODE_RSV1 0xC0 + +/* PKM display */ +static gint hf_pkm_msg_unknown_type = -1; +static gint hf_pkm_msg_attr_display = -1; +static gint hf_pkm_config_settings_authorize_waitout = -1; +static gint hf_pkm_config_settings_reauthorize_waitout = -1; +static gint hf_pkm_config_settings_grace_time = -1; +static gint hf_pkm_config_settings_operational_waittime = -1; +static gint hf_pkm_msg_attr_auth_key = -1; +static gint hf_pkm_msg_attr_tek = -1; +static gint hf_pkm_msg_attr_key_life_time = -1; +static gint hf_pkm_msg_attr_key_seq_num = -1; +static gint hf_pkm_msg_attr_hmac_digest = -1; +static gint hf_pkm_msg_attr_said = -1; +static gint hf_pkm_msg_attr_cbc_iv = -1; +static gint hf_pkm_msg_attr_error_code = -1; +static gint hf_pkm_msg_attr_ca_certificate = -1; +static gint hf_pkm_msg_attr_ss_certificate = -1; +static gint hf_pkm_attr_auth_result_code = -1; +static gint hf_pkm_attr_sa_service_type = -1; +static gint hf_pkm_attr_frame_number = -1; +static gint hf_pkm_attr_ss_random = -1; +static gint hf_pkm_attr_bs_random = -1; +static gint hf_pkm_attr_pre_pak = -1; +static gint hf_pkm_attr_bs_certificate = -1; +static gint hf_pkm_attr_sig_bs = -1; +static gint hf_pkm_attr_ms_mac_address = -1; +static gint hf_pkm_attr_cmac_digest = -1; +static gint hf_pkm_attr_cmac_digest_pn = -1; +static gint hf_pkm_attr_cmac_digest_value = -1; +static gint hf_pkm_attr_eap_payload = -1; +static gint hf_pkm_attr_nonce = -1; +static gint hf_pkm_sa_type = -1; +static gint hf_pkm_msg_crypto_suite = -1; +static gint hf_pkm_msg_crypto_suite_msb = -1; +static gint hf_pkm_msg_crypto_suite_middle = -1; +static gint hf_pkm_msg_crypto_suite_lsb = -1; +/*static gint hf_pkm_msg_version = -1;*/ +static gint hf_pkm_attr_push_modes = -1; +static gint hf_pkm_attr_key_push_counter = -1; +static gint hf_pkm_attr_gkek = -1; +static gint hf_pkm_attr_sig_ss = -1; +static gint hf_pkm_attr_akid = -1; +static gint hf_pkm_config_settings_rekey_wait_timeout = -1; +static gint hf_pkm_config_settings_tek_grace_time = -1; +static gint hf_pkm_config_settings_authorize_reject_wait_timeout = -1; + +/* static gint hf_pkm_attr_pak_ak_seq_number = -1; */ +static gint hf_pkm_attr_associated_gkek_seq_number = -1; +/* static gint hf_pkm_attr_gkek_params = -1; */ + +/* static gint hf_common_tlv_unknown_type = -1; */ +static gint hf_common_tlv_mac_version = -1; +static gint hf_common_tlv_vendor_id = -1; +static gint hf_common_tlv_vendor_specific_type = -1; +static gint hf_common_tlv_vendor_specific_length = -1; +static gint hf_common_tlv_vendor_specific_length_size = -1; +static gint hf_common_tlv_vendor_specific_value = -1; +static gint hf_common_current_transmitted_power = -1; + +static expert_field ei_common_tlv_info = EI_INIT; + +/* Register WiMax Utility Routines */ +void wimax_proto_register_wimax_utility_decoders(void) +{ + /* WiMax Service Flow Encodings display */ + static hf_register_info hf_sfe[] = + { + { /* 1 Service Flow ID */ + &hf_sfe_sf_id, + {"Service Flow ID", "wmx.sfe.sf_id", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* 2 CID */ + &hf_sfe_cid, + {"CID", "wmx.sfe.cid", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 3 Service Class Name */ + &hf_sfe_service_class_name, + {"Service Class Name", "wmx.sfe.service_class_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 4 MBS Service */ + &hf_sfe_mbs_service, + {"MBS Service", "wmx.sfe.mbs_service", FT_UINT8, BASE_DEC, VALS(vals_mbs_service), 0x0, NULL, HFILL} + }, + { /* 5 QoS Parameter Set Type */ + &hf_sfe_qos_params_set, + {"QoS Parameter Set Type", "wmx.sfe.qos_params_set", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* 5.1 */ + &hf_sfe_set_provisioned, + {"Provisioned Set", "wmx.sfe.qos_params_set.provisioned", FT_BOOLEAN, 8, NULL, SFE_QOS_PARAMS_SET_PROVISIONED_SET, NULL, HFILL} + }, + { /* 5.2 */ + &hf_sfe_set_admitted, + {"Admitted Set", "wmx.sfe.qos_params_set.admitted", FT_BOOLEAN, 8, NULL, SFE_QOS_PARAMS_SET_ADMITTED_SET, NULL, HFILL} + }, + { /* 5.3 */ + &hf_sfe_set_active, + {"Active Set", "wmx.sfe.qos_params_set.active", FT_BOOLEAN, 8, NULL, SFE_QOS_PARAMS_SET_ACTIVE_SET, NULL, HFILL} + }, + { /* 5.4 */ + &hf_sfe_set_rsvd, + {"Reserved", "wmx.sfe.qos_params_set.rsvd", FT_UINT8, BASE_HEX, NULL, SFE_QOS_PARAMS_SET_RESERVED, NULL, HFILL} + }, + { /* 6 Traffic Priority */ + &hf_sfe_traffic_priority, + {"Traffic Priority", "wmx.sfe.traffic_priority", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 7 Maximum Sustained Traffic Rate */ + &hf_sfe_max_str, + {"Maximum Sustained Traffic Rate", "wmx.sfe.msr", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_bit_sec, 0x0, NULL, HFILL} + }, + { /* 8 Maximum Traffic Burst */ + &hf_sfe_max_traffic_burst, + {"Maximum Traffic Burst", "wmx.sfe.max_traffic_burst", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_byte_bytes, 0x0, NULL, HFILL} + }, + { /* 9 Minimum Reserved Traffic Rate */ + &hf_sfe_min_rtr, + {"Minimum Reserved Traffic Rate", "wmx.sfe.mrr", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_bit_sec, 0x0, NULL, HFILL} + }, + { + /* 10 Reserved */ + &hf_sfe_reserved_10, + {"Reserved", "wmx.sfe.reserved_10", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, +#if 0 + { /* 10 reserved by 16E */ + &hf_sfe_mtr, + {"Minimum tolerable traffic rate", "wmx.sfe.mtr", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif + { /* 11 Service Flow Scheduling Type */ + &hf_sfe_ul_grant_scheduling, + {"Uplink Grant Scheduling Type", "wmx.sfe.uplink_grant_scheduling", FT_UINT8, BASE_DEC, VALS(vals_ul_grant_scheduling), 0x0, NULL, HFILL} + }, + { /* 12 Request/Transmission Policy */ + &hf_sfe_req_tx_policy, + {"Request/Transmission Policy", "wmx.sfe.req_tx_policy", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* 12.1 */ + &hf_sfe_policy_broadcast_bwr, + {"The Service Flow Shall Not Use Broadcast Bandwidth Request Opportunities", "wmx.sfe.policy.broadcast_bwr", FT_BOOLEAN, 8, NULL, SFE_REQ_TX_POLICY_BROADCAST_BWR, NULL, HFILL} + }, + { /* 12.2 */ + &hf_sfe_policy_multicast_bwr, + {"The Service Flow Shall Not Use Multicast Bandwidth Request Opportunities", "wmx.sfe.policy.bit1", FT_BOOLEAN, 8, NULL, SFE_REQ_TX_POLICY_MULTICAST_BWR, NULL, HFILL} + }, + { /* 12.3 */ + &hf_sfe_policy_piggyback, + {"The Service Flow Shall Not Piggyback Requests With Data", "wmx.sfe.policy.piggyback", FT_BOOLEAN, 8, NULL, SFE_REQ_TX_POLICY_PIGGYBACK, NULL, HFILL} + }, + { /* 12.4 */ + &hf_sfe_policy_fragment, + {"The Service Flow Shall Not Fragment Data", "wmx.sfe.policy.fragment", FT_BOOLEAN, 8, NULL, SFE_REQ_TX_POLICY_FRAGMENT_DATA, NULL, HFILL} + }, + { /* 12.5 */ + &hf_sfe_policy_headers, + {"The Service Flow Shall Not Suppress Payload Headers", "wmx.sfe.policy.headers", FT_BOOLEAN, 8, NULL, SFE_REQ_TX_POLICY_PAYLOAD_HEADER, NULL, HFILL} + }, + { /* 12.6 */ + &hf_sfe_policy_packing, + {"The Service Flow Shall Not Pack Multiple SDUs (Or Fragments) Into Single MAC PDUs", "wmx.sfe.policy.packing", FT_BOOLEAN, 8, NULL, SFE_REQ_TX_POLICY_PACKINGS, NULL, HFILL} + }, + { /* 12.7 */ + &hf_sfe_policy_crc, + {"The Service Flow Shall Not Include CRC In The MAC PDU", "wmx.sfe.policy.crc", FT_BOOLEAN, 8, NULL, SFE_REQ_TX_POLICY_CRC, NULL, HFILL} + }, + { /* 12.8 */ + &hf_sfe_policy_rsvd1, + {"Reserved", "wmx.sfe.policy.rsvd1", FT_UINT8, BASE_HEX, NULL, SFE_REQ_TX_POLICY_RESERVED, NULL, HFILL} + }, + { /* 13 Tolerated Jitter */ + &hf_sfe_jitter, + {"Tolerated Jitter", "wmx.sfe.jitter", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_ms, 0x0, NULL, HFILL} + }, + { /* 14 Maximum Latency */ + &hf_sfe_max_latency, + {"Maximum Latency", "wmx.sfe.max_latency", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &wimax_units_ms, 0x0, NULL, HFILL} + }, + { /* 15 Fixed/Variable Length SDU */ + &hf_sfe_fixed_len_sdu, + {"Fixed/Variable Length SDU", "wmx.sfe.fixed_len_sdu", FT_UINT8, BASE_DEC, VALS(vals_fixed_len_sdu), 0x0, NULL, HFILL} + }, + { /* 16 SDU Size */ + &hf_sfe_sdu_size, + {"SDU Size", "wmx.sfe.sdu_size", FT_UINT8, BASE_DEC|BASE_UNIT_STRING, &wimax_units_byte_bytes, 0x0, NULL, HFILL} + }, + { /* 17 SAID Onto Which SF Is Mapped */ + &hf_sfe_target_said, + {"SAID Onto Which SF Is Mapped", "wmx.sfe.target_said", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* 18 ARQ Enable */ + &hf_sfe_arq_enable, + {"ARQ Enable", "wmx.arq.enable", FT_UINT8, BASE_DEC, VALS(vals_arq_enable), 0x0, NULL, HFILL} + }, + { /* 19 ARQ Window Size */ + &hf_sfe_arq_window_size, + {"ARQ Window Size", "wmx.arq.window_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 20 ARQ Transmitter Delay */ + &hf_sfe_arq_transmitter_delay, + {"ARQ Transmitter Delay (10us granularity)", "wmx.arq.transmitter_delay", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 21 ARQ Receiver Delay */ + &hf_sfe_arq_receiver_delay, + {"ARQ Receiver Delay (10us granularity)", "wmx.arq.receiver_delay", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 22 ARQ Block Lifetime */ + &hf_sfe_arq_block_lifetime, + {"ARQ Block Lifetime (10us granularity)", "wmx.arq.block_lifetime", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 23 ARQ Sync Loss Timeout */ + &hf_sfe_arq_sync_loss_timeout, + {"ARQ Sync Loss Timeout (10us granularity)", "wmx.arq.sync_loss_timeout", FT_UINT16, BASE_DEC, VALS(vals_arq_sync_loss_timeout), 0x0, NULL, HFILL} + }, + { /* 20 ARQ Transmitter Delay */ + &hf_sfe_arq_transmitter_delay_cor2, + {"ARQ Transmitter Delay (100us granularity)", "wmx.arq.transmitter_delay", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 21 ARQ Receiver Delay */ + &hf_sfe_arq_receiver_delay_cor2, + {"ARQ Receiver Delay (100us granularity)", "wmx.arq.receiver_delay", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 22 ARQ Block Lifetime */ + &hf_sfe_arq_block_lifetime_cor2, + {"ARQ Block Lifetime (100us granularity)", "wmx.arq.block_lifetime", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 23 ARQ Sync Loss Timeout */ + &hf_sfe_arq_sync_loss_timeout_cor2, + {"ARQ Sync Loss Timeout (100us granularity)", "wmx.arq.sync_loss_timeout", FT_UINT16, BASE_DEC, VALS(vals_arq_sync_loss_timeout), 0x0, NULL, HFILL} + }, + { /* 24 ARQ Deliver In Order */ + &hf_sfe_arq_deliver_in_order, + {"ARQ Deliver In Order", "wmx.arq.deliver_in_order", FT_UINT8, BASE_DEC, VALS(vals_arq_deliver_in_order), 0x0, NULL, HFILL} + }, + { /* 25 ARQ Purge Timeout */ + &hf_sfe_arq_rx_purge_timeout, + {"ARQ RX Purge Timeout (100us granularity)", "wmx.arq.rx_purge_timeout", FT_UINT16, BASE_DEC, VALS(vals_arq_rx_purge_timeout), 0x0, NULL, HFILL} + }, + { /* 26 ARQ Block Size */ + &hf_sfe_arq_block_size, + {"ARQ Block Size", "wmx.arq.block_size", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 26 ARQ Block Size */ + &hf_sfe_arq_block_size_cor2, + {"ARQ Block Size", "wmx.arq.block_size", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* 26 ARQ Block Size for Corrigendum 2 */ + &hf_sfe_arq_min_block_size, + {"ARQ Minimum Block Size", "wmx.arq.min_block_size", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL} + }, + { /* 26 ARQ Block Size for Corrigendum 2 */ + &hf_sfe_arq_max_block_size, + {"ARQ Maximum Block Size", "wmx.arq.max_block_size", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL} + }, + /* 27 reserved */ + { /* 28 CS Specification */ + &hf_sfe_cs_specification, + {"CS Specification", "wmx.sfe.cs_specification", FT_UINT8, BASE_DEC, VALS(vals_cs_specification), 0x0, NULL, HFILL} + }, + { /* 29 Type of Data Delivery Services */ + &hf_sfe_type_of_data_delivery_services, + {"Type of Data Delivery Services", "wmx.sfe.type_of_data_delivery_services", FT_UINT8, BASE_DEC, VALS(vals_type_of_data_delivery_services), 0x0, NULL, HFILL} + }, + { /* 30 SDU Inter-Arrival Interval */ + &hf_sfe_sdu_inter_arrival_interval, + {"SDU Inter-Arrival Interval (in the resolution of 0.5 ms)", "wmx.sfe.sdu_inter_arrival_interval", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 31 Time Base */ + &hf_sfe_time_base, + {"Time Base", "wmx.sfe.time_base", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &wimax_units_ms, 0x0, NULL, HFILL} + }, + { /* 32 Paging Preference */ + &hf_sfe_paging_preference, + {"Paging Preference", "wmx.sfe.paging_preference", FT_UINT8, BASE_DEC, VALS(vals_paging_preference), 0x0, NULL, HFILL} + }, + { /* 33 MBS Zone Identifier */ + &hf_sfe_mbs_zone_identifier_assignment, + {"MBS Zone Identifier", "wmx.sfe.mbs_zone_identifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 34 Traffic Indication Preference */ + &hf_sfe_reserved_34, + {"Reserved", "wmx.sfe.reserved_34", FT_UINT8, BASE_DEC, NULL /*VALS(vals_traffic_indication_preference)*/, 0x0, NULL, HFILL} + }, + { /* 35 Global Service Class Name */ + &hf_sfe_global_service_class_name, + {"Global Service Class Name", "wmx.sfe.global_service_class_name", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + /* 36 reserved by 16E */ + /* 36 Reserved */ + { + &hf_sfe_reserved_36, + {"Reserved", "wmx.sfe.reserved_36", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 37 SN Feedback Enable */ + &hf_sfe_sn_feedback_enabled, + {"SN Feedback", "wmx.sfe.sn_feedback_enabled", FT_UINT8, BASE_DEC, VALS(vals_sn_fb_enable), 0x0, NULL, HFILL} + }, + { /* 38 FSN Size */ + &hf_sfe_fsn_size, + {"FSN Size", "wmx.sfe.fsn_size", FT_UINT8, BASE_DEC, VALS(vals_fsn_size), 0x0, NULL, HFILL} + }, +#if 0 + { /* 39 CID allocation for Active BSs */ + &hf_sfe_cid_alloc_for_active_bs, + {"CID Allocation For Active BSs", "wmx.sfe.cid_alloc_for_active_bs", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#endif + { /* 39.1 */ + &hf_sfe_cid_alloc_for_active_bs_cid, + {"CID", "wmx.sfe.cid_alloc_for_active_bs_cid", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 40 Unsolicited Grant Interval */ + &hf_sfe_unsolicited_grant_interval, + {"Unsolicited Grant Interval", "wmx.sfe.unsolicited_grant_interval", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &wimax_units_ms, 0x0, NULL, HFILL} + }, + { /* 41 Unsolicited Polling Interval */ + &hf_sfe_unsolicited_polling_interval, + {"Unsolicited Polling Interval", "wmx.sfe.unsolicited_polling_interval", FT_UINT16, BASE_DEC|BASE_UNIT_STRING, &wimax_units_ms, 0x0, NULL, HFILL} + }, + { /* 42 PDU SN extended subheader for HARQ reordering */ + &hf_sfe_pdu_sn_ext_subheader_reorder, + {"PDU SN Extended Subheader For HARQ Reordering", "wmx.sfe.pdu_sn_ext_subheader_reorder", FT_UINT8, BASE_DEC, VALS(vals_pdu_sn_ext_subheader), 0x0, NULL, HFILL} + }, + { /* 43 MBS contents ID */ + &hf_sfe_mbs_contents_ids, + {"MBS contents IDs", "wmx.sfe.mbs_contents_ids", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 43.1 */ + &hf_sfe_mbs_contents_ids_id, + {"MBS Contents ID", "wmx.sfe.mbs_contents_ids_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 44 HARQ Service Flows */ + &hf_sfe_harq_service_flows, + {"HARQ Service Flows", "wmx.sfe.harq_service_flows", FT_UINT8, BASE_DEC, VALS(vals_harq), 0x0, NULL, HFILL} + }, + { /* 45 Authorization Token */ + &hf_sfe_authorization_token, + {"Authorization Token", "wmx.sfe.authorization_token", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#if 0 + { /* 46 HARQ Channel Mapping */ + &hf_sfe_harq_channel_mapping, + {"HARQ Channel Mapping", "wmx.sfe.harq_channel_mapping", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#endif + { /* 46.1 HARQ Channel Index*/ + &hf_sfe_harq_channel_mapping_index, + {"HARQ Channel Index", "wmx.sfe.harq_channel_mapping.index", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + /* unknown types */ + { /* unknown SFE types */ + &hf_sfe_unknown_type, + {"Unknown SFE TLV type", "wmx.sfe.unknown_type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + } + }; + + /* WiMax Convergence Service Parameter Encoding Rules display */ + static hf_register_info hf_csper[] = + { /* 99 - 111 CS parameter encoding rules */ + { /* Classifier DSC Action */ + &hf_cst_classifier_dsc_action, + {"Classifier DSC Action", "wmx.cst.classifier_action", FT_UINT8, BASE_DEC, VALS(vals_cst_classifier_action), 0x0, NULL, HFILL} + }, + { /* Errored Parameter */ + &hf_cst_error_set_errored_param, + {"Errored Parameter", "wmx.cst.error_set.errored_param", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Error Code */ + &hf_cst_error_set_error_code, + {"Error Code", "wmx.cst.error_set.error_code", FT_UINT8, BASE_HEX, VALS(vals_cc), 0x0, NULL, HFILL} + }, + { /* Error Message */ + &hf_cst_error_set_error_msg, + {"Error Message", "wmx.cst.error_set.error_msg", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Packet Classification Rule */ + &hf_cst_pkt_class_rule, + {"Packet Classification Rule", "wmx.cst.pkt_class_rule", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Classification Rule Priority */ + &hf_cst_pkt_class_rule_priority, + {"Classification Rule Priority", "wmx.cst.pkt_class_rule.priority", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* ToS/Differentiated Services Codepoint (DSCP) Range And Mask */ + &hf_cst_pkt_class_rule_range_mask, + {"ToS/Differentiated Services Codepoint (DSCP) Range And Mask", "wmx.cst.pkt_class_rule.range_mask", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* ToS-Low */ + &hf_cst_pkt_class_rule_tos_low, + {"ToS-Low", "wmx.cst.pkt_class_rule.tos-low", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* ToS-High */ + &hf_cst_pkt_class_rule_tos_high, + {"ToS-High", "wmx.cst.pkt_class_rule.tos-high", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* ToS-Mask */ + &hf_cst_pkt_class_rule_tos_mask, + {"ToS-Mask", "wmx.cst.pkt_class_rule.tos-mask", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* Protocol */ + &hf_cst_pkt_class_rule_protocol, + {"Protocol", "wmx.cst.pkt_class_rule.protocol", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, +#if 0 /* Removed by the changes of 802.16E 2005 */ + { /* Protocol Number */ + &hf_cst_pkt_class_rule_protocol_number, + {"Protocol Number", "wmx.cst.pkt_class_rule.protocol.number", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL} + }, +#endif + { /* IP Masked Source Address */ + &hf_cst_pkt_class_rule_ip_masked_src_address, + {"IP Masked Source Address", "wmx.cst.pkt_class_rule.ip_masked_src_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* IP Masked Destination Address */ + &hf_cst_pkt_class_rule_ip_masked_dest_address, + {"IP Masked Destination Address", "wmx.cst.pkt_class_rule.ip_masked_dest_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* IPv4 Source Address */ + &hf_cst_pkt_class_rule_src_ipv4, + {"IPv4 Source Address", "wmx.cst.pkt_class_rule.src_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* IPv4 Destination Address */ + &hf_cst_pkt_class_rule_dest_ipv4, + {"IPv4 Destination Address", "wmx.cst.pkt_class_rule.dst_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* IPv4 Mask */ + &hf_cst_pkt_class_rule_mask_ipv4, + {"IPv4 Mask", "wmx.cst.pkt_class_rule.mask_ipv4", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* IPv6 Source Address */ + &hf_cst_pkt_class_rule_src_ipv6, + {"IPv6 Source Address", "wmx.cst.pkt_class_rule.src_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* IPv6 Destination Address */ + &hf_cst_pkt_class_rule_dest_ipv6, + {"IPv6 Destination Address", "wmx.cst.pkt_class_rule.dst_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* IPv6 Mask */ + &hf_cst_pkt_class_rule_mask_ipv6, + {"IPv6 Mask", "wmx.cst.pkt_class_rule.mask_ipv6", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Protocol Source Port Range */ + &hf_cst_pkt_class_rule_prot_src_port_range, + {"Protocol Source Port Range", "wmx.cst.pkt_class_rule.prot_src_port_range", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Src-Port Low */ + &hf_cst_pkt_class_rule_src_port_low, + {"Src-Port Low", "wmx.cst.pkt_class_rule.src_port_low", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* Src-Port High */ + &hf_cst_pkt_class_rule_src_port_high, + {"Src-Port High", "wmx.cst.pkt_class_rule.src_port_high", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* Protocol Destination Port Range */ + &hf_cst_pkt_class_rule_prot_dest_port_range, + {"Protocol Destination Port Range", "wmx.cst.pkt_class_rule.prot_dest_port_range", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Dst-Port Low */ + &hf_cst_pkt_class_rule_dest_port_low, + {"Dst-Port Low", "wmx.cst.pkt_class_rule.dst_port_low", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* Dst-Port High */ + &hf_cst_pkt_class_rule_dest_port_high, + {"Dst-Port High", "wmx.cst.pkt_class_rule.dst_port_high", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 802.3/Ethernet Destination MAC Address */ + &hf_cst_pkt_class_rule_dest_mac_address, + {"802.3/Ethernet Destination MAC Address", "wmx.cst.pkt_class_rule.dest_mac_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Destination MAC Address */ + &hf_cst_pkt_class_rule_dest_mac, + {"Destination MAC Address", "wmx.cst.pkt_class_rule.dst_mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 802.3/Ethernet Source MAC Address */ + &hf_cst_pkt_class_rule_src_mac_address, + {"802.3/Ethernet Source MAC Address", "wmx.cst.pkt_class_rule.src_mac_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Source MAC Address */ + &hf_cst_pkt_class_rule_src_mac, + {"Source MAC Address", "wmx.cst.pkt_class_rule.src_mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* MAC Address Mask */ + &hf_cst_pkt_class_rule_mask_mac, + {"MAC Address Mask", "wmx.cst.pkt_class_rule.mask_mac", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Ethertype/IEEE Std 802.2-1998 SAP */ + &hf_cst_pkt_class_rule_ethertype, + {"Ethertype/IEEE Std 802.2-1998 SAP", "wmx.cst.pkt_class_rule.ethertype", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Ethertype */ + &hf_cst_pkt_class_rule_etype, + {"Ethertype", "wmx.cst.pkt_class_rule.etype", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* Eprot1 */ + &hf_cst_pkt_class_rule_eprot1, + {"Eprot1", "wmx.cst.pkt_class_rule.eprot1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* Eprot2 */ + &hf_cst_pkt_class_rule_eprot2, + {"Eprot2", "wmx.cst.pkt_class_rule.eprot2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* IEEE Std 802.1D-1998 User_Priority */ + &hf_cst_pkt_class_rule_user_priority, + {"IEEE Std 802.1D-1998 User_Priority", "wmx.cst.pkt_class_rule.user_priority", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cst_pkt_class_rule_pri_low, + {"Pri-Low", "wmx.cst.pkt_class_rule.pri-low", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cst_pkt_class_rule_pri_high, + {"Pri-High", "wmx.cst.pkt_class_rule.pri-high", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* IEEE Std 802.1Q-1998 VLAN_ID */ + &hf_cst_pkt_class_rule_vlan_id, + {"IEEE Std 802.1Q-1998 VLAN_ID", "wmx.cst.pkt_class_rule.vlan_id", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Vlan_Id1 */ + &hf_cst_pkt_class_rule_vlan_id1, + {"Vlan_Id1", "wmx.cst.pkt_class_rule.vlan_id1", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* Vlan_Id2 */ + &hf_cst_pkt_class_rule_vlan_id2, + {"Vlan_Id2", "wmx.cst.pkt_class_rule.vlan_id2", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* Associated PHSI */ + &hf_cst_pkt_class_rule_phsi, + {"Associated PHSI", "wmx.cst.pkt_class_rule.phsi", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* Packet Classifier Rule Index */ + &hf_cst_pkt_class_rule_index, + {"Packet Classifier Rule Index (PCRI)", "wmx.cst.pkt_class_rule.index", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* Large Context ID for ROHC/ECRTP Compressed Packet or ROHC Feedback Packet */ + &hf_cst_large_context_id, + {"Large Context ID", "wmx.cst.large_context_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* Short-Format Context ID for ROHC/ECRTP Compressed Packet or ROHC Feedback Packet */ + &hf_cst_short_format_context_id, + {"Short-Format Context ID", "wmx.cst.short_format_context_id", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* Vendor-Specific Classifier Parameters */ + &hf_cst_pkt_class_rule_vendor_spec, + {"Vendor-Specific Classifier Parameters", "wmx.cst.pkt_class_rule.vendor_spec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* Classifier Action Rule */ + &hf_cst_pkt_class_rule_classifier_action_rule, + {"Classifier Action Rule", "wmx.cst.pkt_class_rule.classifier.action.rule", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cst_pkt_class_rule_classifier_action_rule_bit0, + {"Bit #0", "wmx.cst.pkt_class_rule.classifier.action.rule.bit0", FT_UINT8, BASE_HEX, VALS(vals_classification_action_rule), CST_PKT_CLASS_RULE_CLASSIFIER_ACTION_RULE_BIT0, NULL, HFILL} + }, + { + &hf_cst_pkt_class_rule_classifier_action_rule_bit1, + {"Reserved", "wmx.cst.pkt_class_rule.classifier.action.rule.reserved", FT_UINT8, BASE_HEX, NULL, CST_PKT_CLASS_RULE_CLASSIFIER_ACTION_RULE_RSV, NULL, HFILL} + }, + { /* PHS DSC action */ + &hf_cst_phs_dsc_action, + {"PHS DSC action", "wmx.cst.phs_dsc_action", FT_UINT8, BASE_DEC, VALS(vals_cst_phs_dsc_action), 0x0, NULL, HFILL} + }, + { /* PHS Rule */ + &hf_cst_phs_rule, + {"PHS Rule", "wmx.cst.phs_rule", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* PHS Rule 1 */ + &hf_cst_phs_phsi, + {"PHSI", "wmx.cst.phs_rule.phsi", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* PHS Rule 2 */ + &hf_cst_phs_phsf, + {"PHSF", "wmx.cst.phs_rule.phsf", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* PHS Rule 3 */ + &hf_cst_phs_phsm, + {"PHSM (bit x: 0-don't suppress the (x+1) byte; 1-suppress the (x+1) byte)", "wmx.cst.phs_rule.phsm", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* PHS Rule 4 */ + &hf_cst_phs_phss, + {"PHSS", "wmx.cst.phs_rule.phss", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* PHS Rule 5 */ + &hf_cst_phs_phsv, + {"PHSV", "wmx.cst.phs_rule.phsv", FT_UINT8, BASE_DEC, VALS(vals_verify), 0x0, NULL, HFILL} + }, + { /* PHS Rule 143 */ + &hf_cst_phs_vendor_spec, + {"Vendor-Specific PHS Parameters", "wmx.cst.phs.vendor_spec", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* IPv6 Flow Label */ + &hf_cst_pkt_class_rule_ipv6_flow_label, + {"IPv6 Flow Label", "wmx.cst.pkt_class_rule.ipv6_flow_label", FT_UINT24, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* ATM Switching Encoding */ + &hf_csper_atm_switching_encoding, + {"ATM Switching Encoding", "wmx.csper.atm_switching_encoding", FT_UINT8, BASE_DEC, VALS(vals_atm_switching_encodings), 0x0, NULL, HFILL} + }, + { /* ATM Classifier TLV */ + &hf_csper_atm_classifier, + {"ATM Classifier TLV", "wmx.csper.atm_classifier", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* ATM VPI Classifier */ + &hf_csper_atm_classifier_vpi, + {"VPI Classifier", "wmx.csper.atm_classifier_vpi", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* ATM VCI Classifier */ + &hf_csper_atm_classifier_vci, + {"VCI Classifier", "wmx.csper.atm_classifier_vci", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* ATM Classifier ID */ + &hf_csper_atm_classifier_id, + {"Classifier ID", "wmx.csper.atm_classifier_tlv", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + /* unknown types */ + { /* unknown CSPER types */ + &hf_csper_unknown_type, + {"Unknown CSPER TLV type", "wmx.csper.unknown_type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cst_invalid_tlv, + {"Invalid TLV", "wmx.cst.invalid_tlv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + } + }; + + /* WiMax HMAC/CMAC/Short-HMAC Tuples display */ + static hf_register_info hf_xmac[] = + { + { + &hf_xmac_tuple_rsvd, + {"Reserved", "wmx.xmac_tuple.reserved", FT_UINT8, BASE_HEX, NULL, XMAC_TUPLE_RESERVED, NULL, HFILL} + }, + { + &hf_xmac_tuple_key_seq_num, + {"Key Sequence Number", "wmx.xmac_tuple.key_sn", FT_UINT8, BASE_DEC, NULL, XMAC_TUPLE_KEY_SEQ_NUM, NULL, HFILL} + }, + { + &hf_hmac_tuple_hmac_digest, + {"HMAC Digest", "wmx.xmac_tuple.hmac_digest", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cmac_tuple_bsid, + {"BSID", "wmx.cmac_tuple.bsid", FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_cmac_tuple_cmac_value, + {"CMAC Value", "wmx.cmac_tuple.cmac.value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_packet_number_counter, + {"Packet Number Counter", "wmx.xmac_tuple.packet_number_count", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + } + }; + + static hf_register_info hf_snp[] = + { + { /* 11.8.4.1 */ + &hf_snp_pkm_version_support, + {"PKM Version Support", "wmx.security_negotiation_parameters.pkm_version_support",FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_snp_pkm_version_support_bit0, + {"PKM version 1", "wmx.security_negotiation_parameters.pkm_version_support.bit0",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_PKM_VERSION_SUPPORT_BIT0, NULL, HFILL} + }, + { + &hf_snp_pkm_version_support_bit1, + {"PKM version 2", "wmx.security_negotiation_parameters.pkm_version_support.bit1",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_PKM_VERSION_SUPPORT_BIT1, NULL, HFILL} + }, + { + &hf_snp_pkm_version_support_reserved, + {"Reserved", "wmx.security_negotiation_parameters.pkm_version_support.reserved",FT_UINT8, BASE_HEX, NULL, SNP_PKM_VERSION_SUPPORT_RSV, NULL, HFILL} + }, + { /* 11.8.4.2 */ + &hf_snp_auth_policy_support, + {"Authorization Policy Support", "wmx.security_negotiation_parameters.auth_policy_support",FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_snp_auth_policy_support_bit0, + {"RSA-based Authorization At The Initial Network Entry", "wmx.security_negotiation_parameters.auth_policy_support.bit0",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_AUTH_POLICY_SUPPORT_BIT0, NULL, HFILL} + }, + { + &hf_snp_auth_policy_support_bit1, + {"EAP-based Authorization At The Initial Network Entry", "wmx.security_negotiation_parameters.auth_policy_support.bit1",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_AUTH_POLICY_SUPPORT_BIT1, NULL, HFILL} + }, + { + &hf_snp_auth_policy_support_bit2, + {"Authenticated EAP-based Authorization At The Initial Network Entry", "wmx.security_negotiation_parameters.auth_policy_support.bit2",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_AUTH_POLICY_SUPPORT_BIT2, NULL, HFILL} + }, + { + &hf_snp_auth_policy_support_bit3, + {"Reserved", "wmx.security_negotiation_parameters.auth_policy_support.bit3",FT_UINT8, BASE_HEX, NULL, SNP_AUTH_POLICY_SUPPORT_BIT3, NULL, HFILL} + }, + { + &hf_snp_auth_policy_support_bit4, + {"RSA-based Authorization At Re-entry", "wmx.security_negotiation_parameters.auth_policy_support.bit4",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_AUTH_POLICY_SUPPORT_BIT4, NULL, HFILL} + }, + { + &hf_snp_auth_policy_support_bit5, + {"EAP-based Authorization At Re-entry", "wmx.security_negotiation_parameters.auth_policy_support.bit5",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_AUTH_POLICY_SUPPORT_BIT5, NULL, HFILL} + }, + { + &hf_snp_auth_policy_support_bit6, + {"Authenticated EAP-based Authorization At Re-entry", "wmx.security_negotiation_parameters.auth_policy_support.bit6",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_AUTH_POLICY_SUPPORT_BIT6, NULL, HFILL} + }, + { + &hf_snp_auth_policy_support_bit7, + {"Reserved", "wmx.security_negotiation_parameters.auth_policy_support.bit7",FT_UINT8, BASE_HEX, NULL, SNP_AUTH_POLICY_SUPPORT_BIT7, NULL, HFILL} + }, + { /* 11.8.4.3 */ + &hf_snp_mac_mode, + {"MAC (Message Authentication Code) Mode", "wmx.security_negotiation_parameters.mac_mode",FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_snp_mac_mode_bit0, + {"HMAC", "wmx.security_negotiation_parameters.mac_mode.bit0",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_MAC_MODE_BIT0, NULL, HFILL} + }, + { + &hf_snp_mac_mode_bit1, + {"CMAC", "wmx.security_negotiation_parameters.mac_mode.bit1",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_MAC_MODE_BIT1, NULL, HFILL} + }, + { + &hf_snp_mac_mode_bit1_rsvd, + {"Reserved", "wmx.security_negotiation_parameters.mac_mode.bit1_rsvd",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_MAC_MODE_BIT1, NULL, HFILL} + }, + { + &hf_snp_mac_mode_bit2, + {"64-bit Short-HMAC", "wmx.security_negotiation_parameters.mac_mode.bit2",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_MAC_MODE_BIT2, NULL, HFILL} + }, + { + &hf_snp_mac_mode_bit3, + {"80-bit Short-HMAC", "wmx.security_negotiation_parameters.mac_mode.bit3",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_MAC_MODE_BIT3, NULL, HFILL} + }, + { + &hf_snp_mac_mode_bit4, + {"96-bit Short-HMAC", "wmx.security_negotiation_parameters.mac_mode.bit4",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_MAC_MODE_BIT4, NULL, HFILL} + }, + { + &hf_snp_mac_mode_bit5, + {"CMAC", "wmx.security_negotiation_parameters.mac_mode.bit5",FT_BOOLEAN, 8, TFS(&tfs_supported), SNP_MAC_MODE_BIT5, NULL, HFILL} + }, + { + &hf_snp_mac_mode_reserved, + {"Reserved", "wmx.security_negotiation_parameters.mac_mode.reserved",FT_UINT8, BASE_HEX, NULL, SNP_MAC_MODE_RSV, NULL, HFILL} + }, + { + &hf_snp_mac_mode_reserved1, + {"Reserved", "wmx.security_negotiation_parameters.mac_mode.reserved",FT_UINT8, BASE_HEX, NULL, SNP_MAC_MODE_RSV1, NULL, HFILL} + }, + { /* 11.8.4.4 */ + &hf_snp_pn_window_size, + {"PN Window Size", "wmx.security_negotiation_parameters.pn_window_size",FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.8.4.5 */ + &hf_snp_max_conc_transactions, + {"Maximum concurrent transactions (0 indicates no limit)", "wmx.security_negotiation_parameters.max_conc_transactions",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.8.4.6 */ + &hf_snp_max_suppt_sec_assns, + {"Maximum number of security associations supported by the SS", "wmx.security_negotiation_parameters.max_suppt_sec_assns",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_snp_unknown_type, + {"Unknown Security Negotiation Parameter type", "wmx.security_negotiation_parameters.unknown.type",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + } + }; + + static hf_register_info hf_pkm[] = + { + { /* 11.9.1 - type 6 */ + &hf_pkm_msg_attr_display, + {"Display String", "wmx.pkm_msg.pkm_attr.display_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.2 - type 7 */ + &hf_pkm_msg_attr_auth_key, + {"Auth Key", "wmx.pkm_msg.pkm_attr.auth_key", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.3 - type 8 */ + &hf_pkm_msg_attr_tek, + {"TEK", "wmx.pkm_msg.pkm_attr.tek", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.4 - type 9 */ + &hf_pkm_msg_attr_key_life_time, + {"Key Lifetime", "wmx.pkm_msg.pkm_attr.key_life_time", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.5 - type 10 */ + &hf_pkm_msg_attr_key_seq_num, + {"Key Sequence Number", "wmx.pkm_msg.pkm_attr.key_seq_num", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.6 - type 11 */ + &hf_pkm_msg_attr_hmac_digest, + {"HMAC-Digest", "wmx.pkm_msg.pkm_attr.hmac_digest", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.7 - type 12 */ + &hf_pkm_msg_attr_said, + {"SAID", "wmx.pkm_msg.pkm_attr.said", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, +#if 0 /* not been used */ + { /* 11.9.8 - type 13 */ + &hf_pkm_msg_attr_tek_param, + {"TEK Parameters", "wmx.pkm_msg.pkm_attr.tek_parameters", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif + { /* 11.9.9 - type 15 */ + &hf_pkm_msg_attr_cbc_iv, + {"CBC IV", "wmx.pkm_msg.pkm_attr.cbc_iv", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.10 - type 16 */ + &hf_pkm_msg_attr_error_code, + {"Error Code", "wmx.pkm_msg.pkm_attr.error_code", FT_UINT8, BASE_DEC, VALS(vals_pkm_attr_error_codes), 0x0, NULL, HFILL} + }, + { /* 11.9.11 - type 17 */ + &hf_pkm_msg_attr_ca_certificate, + {"CA Certificate", "wmx.pkm_msg.pkm_attr.ca_certificate", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.12 - type 18 */ + &hf_pkm_msg_attr_ss_certificate, + {"SS Certificate", "wmx.pkm_msg.pkm_attr.ss_certificate", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#if 0 /* not been used */ + { /* 11.9.13 - type 19 */ + &hf_pkm_msg_attr_security_capabilities, + {"Security Capabilities", "wmx.pkm_msg.pkm_attr.security_capabilities", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif + { /* 11.9.14 - type 20 */ + &hf_pkm_msg_crypto_suite, + {"Cryptography", "wmx.pkm_msg.pkm_attr.crypto_suite", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_pkm_msg_crypto_suite_msb, + {"Data Encryption Algorithm Identifiers", "wmx.pkm_msg.pkm_attr.crypto_suite.msb", FT_UINT8, BASE_DEC, VALS(vals_data_encryption_ids), 0x0, NULL, HFILL} + }, + { + &hf_pkm_msg_crypto_suite_middle, + {"Data Authentication Algorithm Identifiers", "wmx.pkm_msg.pkm_attr.crypto_suite.middle", FT_UINT8, BASE_DEC, VALS(vals_data_authentication_ids), 0x0, NULL, HFILL} + }, + { + &hf_pkm_msg_crypto_suite_lsb, + {"TEK Encryption Algorithm Identifiers", "wmx.pkm_msg.pkm_attr.crypto_suite.lsb", FT_UINT8, BASE_DEC, VALS(vals_tek_encryption_ids), 0x0, NULL, HFILL} + }, +#if 0 /* not been used */ + { /* 11.9.15 - type 21 */ + &hf_pkm_msg_crypto_list, + {"Cryptographic-Suite List", "wmx.pkm_msg.pkm_attr.crypto_suite_list", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif +#if 0 /* deleted by 802.16E */ + { /* 11.9.16 - type 22 */ + &hf_pkm_msg_version, + {"Reserved ", "wmx.pkm_msg.pkm_attr.version", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif +#if 0 /* not been used */ + { /* 11.9.17 - type 23 */ + &hf_pkm_msg_sa_descriptor, + {"SA Descriptor", "wmx.pkm_msg.pkm_attr.sa_descriptor", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif + { /* 11.9.18 - type 24 */ + &hf_pkm_sa_type, + {"SA Type", "wmx.pkm_msg.pkm_attr.sa_type", FT_UINT8, BASE_DEC, VALS(vs_sa_type), 0x0, NULL, HFILL} + }, +#if 0 /* not been used */ + { /* 11.9.?? - type 25 */ + &hf_pkm_attr_security_negotiation_parameters, + {"Security Negotiation Parameters", "wmx.pkm_msg.pkm_attr.security_negotiation_parameters", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif +#if 0 /* not been used */ + { /* 11.9.19 - type 27 */ + &hf_pkm_attr_config_settings, + {"PKM Configuration Settings", "wmx.pkm_msg.pkm_attr.config_settings", FT_BYTES, BASE_HEX, NULL, 0x0, "", HFILL} + }, +#endif + { /* 11.9.19.1 */ + &hf_pkm_config_settings_authorize_waitout, + {"Authorize Wait Timeout (in seconds)", "wmx.pkm_msg.pkm_attr.config_settings.authorize_waitout", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.19.2 */ + &hf_pkm_config_settings_reauthorize_waitout, + {"Reauthorize Wait Timeout (in seconds)", "wmx.pkm_msg.pkm_attr.config_settings.reauthorize_waitout", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.19.3 */ + &hf_pkm_config_settings_grace_time, + {"Authorization Grace Time (in seconds)", "wmx.pkm_msg.pkm_attr.config_settings.grace_time", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.19.4 */ + &hf_pkm_config_settings_operational_waittime, + {"Operational Wait Timeout (in seconds)", "wmx.pkm_msg.pkm_attr.config_settings.operational_wait_timeout", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.19.5 */ + &hf_pkm_config_settings_rekey_wait_timeout, + {"Rekey Wait Timeout (in seconds)", "wmx.pkm_msg.pkm_attr.config_settings.rekey_wait_timeout", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.19.6 */ + &hf_pkm_config_settings_tek_grace_time, + {"TEK Grace Time (in seconds)", "wmx.pkm_msg.pkm_attr.config_settings.tek_grace_time", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.19.7 */ + &hf_pkm_config_settings_authorize_reject_wait_timeout, + {"Authorize Reject Wait Timeout(in seconds)", "wmx.pkm_msg.pkm_attr.config_settings.authorize_reject_wait_timeout", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.20 - type 29 */ + &hf_pkm_attr_nonce, + {"Nonce", "wmx.pkm_msg.pkm_attr.nonce", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.21 - type 33 */ + &hf_pkm_attr_ss_random, + {"SS_RANDOM", "wmx.pkm_msg.pkm_attr.ss_random", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.22 - type 34 */ + &hf_pkm_attr_bs_random, + {"BS_RANDOM", "wmx.pkm_msg.pkm_attr.bs_random", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.23 - type 35 */ + &hf_pkm_attr_pre_pak, + {"Pre-PAK", "wmx.pkm_msg.pkm_attr.pre_pak", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#if 0 /* no definition */ + { /* 11.9.?? - type 36 */ + &hf_pkm_attr_pak_ak_seq_number, + {"PAK/AK Sequence Number", "wmx.pkm_msg.pkm_attr.pak_ak_seq_number", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#endif + { /* 11.9.24 - type 37 */ + &hf_pkm_attr_bs_certificate, + {"BS Certificate", "wmx.pkm_msg.pkm_attr.bs_certificate", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.25 - type 38 */ + &hf_pkm_attr_sig_bs, + {"SigBS", "wmx.pkm_msg.pkm_attr.sig_bs",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.26 - type 39 */ + &hf_pkm_attr_ms_mac_address, + {"MS-MAC Address", "wmx.pkm_msg.pkm_attr.ms_mac_address",FT_ETHER, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.27 - type 40 */ + &hf_pkm_attr_cmac_digest, + {"CMAC Digest", "wmx.pkm_msg.pkm_attr.cmac_digest",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_pkm_attr_cmac_digest_pn, + {"CMAC Packet Number counter, CMAC_PN_*", "wmx.pkm_msg.pkm_attr.cmac_digest.pn",FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_pkm_attr_cmac_digest_value, + {"CMAC Value", "wmx.pkm_msg.pkm_attr.cmac_digest.value",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.28 - type 41 */ + &hf_pkm_attr_push_modes, + {"Key Push Modes", "wmx.pkm_msg.pkm_attr.key_push_modes",FT_UINT8, BASE_DEC, VALS(va_key_push_modes), 0x0, NULL, HFILL} + }, + { /* 11.9.29 - type 42 */ + &hf_pkm_attr_key_push_counter, + {"Key Push Counter", "wmx.pkm_msg.pkm_attr.key_push_counter",FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.30 - type 43 */ + &hf_pkm_attr_gkek, + {"GKEK", "wmx.pkm_msg.pkm_attr.gkek",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.31 - type 44 */ + &hf_pkm_attr_sig_ss, + {"SigSS", "wmx.pkm_msg.pkm_attr.sig_ss",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.32 - type 45 */ + &hf_pkm_attr_akid, + {"AKID", "wmx.pkm_msg.pkm_attr.akid",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.33 - type 28 */ + &hf_pkm_attr_eap_payload, + {"EAP Payload", "wmx.pkm_msg.pkm_attr.eap_payload", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { /* 11.9.34 - type 30 */ + &hf_pkm_attr_auth_result_code, + {"Auth Result Code", "wmx.pkm_msg.pkm_attr.auth_result_code", FT_UINT8, BASE_DEC, VALS(vs_success_reject), 0x0, NULL, HFILL} + }, + { /* 11.9.35 - type 31 */ + &hf_pkm_attr_sa_service_type, + {"SA Service Type", "wmx.pkm_msg.pkm_attr.sa_service_type", FT_UINT8, BASE_DEC, VALS(vs_sa_service_type), 0x0, NULL, HFILL} + }, + { /* 11.9.37 - type 32 */ + &hf_pkm_attr_frame_number, + {"Frame Number", "wmx.pkm_msg.pkm_attr.frame_number", FT_UINT24, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, +#if 1 /* no definitions [??] */ + { /* 11.9.?? - type 46 */ + &hf_pkm_attr_associated_gkek_seq_number, + {"Associated GKEK Sequence Number", "wmx.pkm_msg.pkm_attr.associated_gkek_seq_number",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#endif +#if 0 + { /* 11.9.?? - type 47 */ + &hf_pkm_attr_gkek_params, + {"GKEK Parameters", "wmx.pkm_msg.pkm_attr.gkek_params",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#endif + { + &hf_pkm_msg_unknown_type, + {"Unknown Type", "wmx.pkm.unknown.type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + } + }; + + /* WiMax Common TLV Encoding display */ + static hf_register_info hf_common_tlv[] = + { + { + &hf_common_tlv_mac_version, + { "MAC Version", "wmx.common_tlv.mac_version", FT_UINT8, BASE_DEC, VALS(vals_dcd_mac_version), 0x0, NULL, HFILL} + }, + { + &hf_common_tlv_vendor_id, + { "Vendor ID Encoding", "wmx.common_tlv.vendor_id_encoding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_common_tlv_vendor_specific_type, + { "Vendor Specific Type", "wmx.common_tlv.vendor_specific_type", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL} + }, + { + &hf_common_tlv_vendor_specific_length_size, + { + "Vendor Specific Length Size", "wmx.common_tlv.vendor_specific_length_size", + FT_UINT8, BASE_HEX, NULL, 0x0, + NULL, HFILL + } + }, + { + &hf_common_tlv_vendor_specific_length, + { "Vendor Specific Length", "wmx.common_tlv.vendor_specific_length", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL} + }, + { + &hf_common_tlv_vendor_specific_value, + { "Vendor Specific Value", "wmx.common_tlv.vendor_specific_value", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, + { + &hf_common_current_transmitted_power, + { "Current Transmitted Power", "wmx.common_tlv.current_transmitted_power", FT_FLOAT, BASE_NONE, NULL, 0x0, NULL, HFILL} + }, +#if 0 + { + &hf_common_tlv_unknown_type, + {"Unknown Common TLV Type", "wmx.common_tlv.unknown_type", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL} + } +#endif + }; + + static ei_register_info ei[] = { + { &ei_common_tlv_info, { "wmx.common_tlv.invalid", PI_PROTOCOL, PI_WARN, "Invalid TLV info", EXPFILL }}, + }; + + expert_module_t* expert_wimax_utility; + + if(proto_wimax_utility_decoders == -1) + { + proto_wimax_utility_decoders = proto_register_protocol ( + "WiMax Sub-TLV Messages", + /* name */ + "WiMax Sub-TLV (sub)", /* short name */ + "wmx.sub" /* abbrev */ + ); + + proto_register_subtree_array(ett, array_length(ett)); + proto_register_field_array(proto_wimax_utility_decoders, hf_sfe, array_length(hf_sfe)); + proto_register_field_array(proto_wimax_utility_decoders, hf_csper, array_length(hf_csper)); + proto_register_field_array(proto_wimax_utility_decoders, hf_xmac, array_length(hf_xmac)); + proto_register_field_array(proto_wimax_utility_decoders, hf_snp, array_length(hf_snp)); + proto_register_field_array(proto_wimax_utility_decoders, hf_pkm, array_length(hf_pkm)); + proto_register_field_array(proto_wimax_utility_decoders, hf_common_tlv, array_length(hf_common_tlv)); + expert_wimax_utility = expert_register_protocol(proto_wimax_utility_decoders); + expert_register_field_array(expert_wimax_utility, ei, array_length(ei)); + + eap_handle = find_dissector("eap"); + } +} + +/**************************************************************/ +/* wimax_error_parameter_set_decoder() */ +/* decode and display the WiMax Error Parameter Set */ +/* parameter: */ +/* tvb - pointer of the tvb of error_parameter_set */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure*/ +/**************************************************************/ +void wimax_error_parameter_set_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len; + gint tlv_type; + proto_item *ceps_item = NULL; + proto_tree *ceps_tree = NULL; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + offset = 0; + /* display error parameter information */ + ceps_item = proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, tvb_len, "Error Parameter Set (%u bytes)", tvb_len); + /* add CS Parameter Encoding Rules subtree */ + ceps_tree = proto_item_add_subtree(ceps_item, ett_wimax_error_parameter_set); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid Error Parameter Set"); + return; + } + /* process the classifier error parameter set */ + while(offset < tvb_len) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "EPS TLV error"); + proto_tree_add_item(ceps_tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(ceps_tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len+2+get_tlv_size_of_length(&tlv_info)), "EPS TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len); +#endif + /* parse the Classifier Error Parameter Set */ + switch (tlv_type) + { + case CST_ERROR_SET_ERRORED_PARAM: + add_tlv_subtree(&tlv_info, ceps_tree, hf_cst_error_set_errored_param, tvb, offset, ENC_NA); + break; + case CST_ERROR_SET_ERROR_CODE: + add_tlv_subtree(&tlv_info, ceps_tree, hf_cst_error_set_error_code, tvb, offset, ENC_BIG_ENDIAN); + break; + case CST_ERROR_SET_ERROR_MSG: + add_tlv_subtree(&tlv_info, ceps_tree, hf_cst_error_set_error_msg, tvb, offset, ENC_ASCII|ENC_NA); + break; + } + offset += (tlv_len+get_tlv_value_offset(&tlv_info)); + } +} + +/****************************************************************/ +/* wimax_convengence_service_parameter_encoding_rules_decoder() */ +/* decode and display the WiMax Convergence Service Parameter */ +/* Encoding Rules */ +/* parameter: */ +/* sfe_type - Service Flow Encodings type */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/****************************************************************/ +/* CS Parameter Encoding Rules handling function */ +void wimax_convengence_service_parameter_encoding_rules_decoder(guint sfe_type, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset, tlv_offset; + guint tvb_len, tlv_len, length; + gint tlv_type; + proto_item *csper_item; + proto_tree *csper_tree; + proto_tree *tlv_tree, *ti_tree; + proto_item *tlv_item, *ti_item; + tlv_info_t tlv_info; + gboolean ipv6 = ((sfe_type == SFE_CSPER_PACKET_IPV6) || (sfe_type == SFE_CSPER_PACKET_IPV6_802_3) || (sfe_type == SFE_CSPER_PACKET_IPV6_802_1Q)); + + /* sanity check */ + if((sfe_type < SFE_CSPER_ATM) || (sfe_type > SFE_CSPER_PACKET_IP_802_3_ECRTP_COMPRESSION)) + return; /* invalid CS Parameter Encodings */ + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + offset = 0; + /* display SFE information */ + csper_item = proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, tvb_len, "Convergence Service Parameter Encoding Rules (%u bytes)", tvb_len); + /* add CS Parameter Encoding Rules subtree */ + csper_tree = proto_item_add_subtree(csper_item, ett_wimax_cst_encoding_rules); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid Convergence Service Parameter Encoding Rules"); + return; + } + /* process WiMax Service Flow Encodings */ + while(offset < tvb_len) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "CSPER TLV error"); + proto_tree_add_item(csper_tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(csper_tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len+2+get_tlv_size_of_length(&tlv_info)), "CSPER TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len); +#endif + /* update the offset */ + offset += get_tlv_value_offset(&tlv_info); + /* parse the CS parameter Encoding Rule TLV */ + if(sfe_type == SFE_CSPER_ATM) + { /* ATM CS Encodings */ + switch (tlv_type) + { + case CST_ATM_SWITCHING: + add_tlv_subtree(&tlv_info, csper_tree, hf_csper_atm_switching_encoding, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_ATM_CLASSIFIER: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, csper_tree, hf_csper_atm_classifier, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_cst_encoding_rules); + tlv_offset = offset; + while(tlv_offset < (tlv_len + offset)) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, tlv_offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "ATM Classifier TLV error"); + proto_tree_add_item(tlv_tree, hf_cst_invalid_tlv, tvb, offset, (tlv_len - tlv_offset), ENC_NA); + break; + } +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(csper_tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len+2+get_tlv_size_of_length(&tlv_info)), "ATM Classifier TLV Type: %u (%u bytes, offset=%u, tlv_len=%u)", tlv_type, length, offset, tlv_len); +#endif + switch (tlv_type) + { + case ATM_VPI_CLASSIFIER: + add_tlv_subtree(&tlv_info, tlv_tree, hf_csper_atm_classifier_vpi, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case ATM_VCI_CLASSIFIER: + add_tlv_subtree(&tlv_info, tlv_tree, hf_csper_atm_classifier_vci, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case ATM_CLASSIFIER_ID: + add_tlv_subtree(&tlv_info, tlv_tree, hf_csper_atm_classifier_id, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + default: + break; + } + tlv_offset += (length + get_tlv_value_offset(&tlv_info)); + } /* end of while loop */ + break; + case CST_ATM_CLASSIFIER_DSC_ACTION: + add_tlv_subtree(&tlv_info, csper_tree, hf_cst_classifier_dsc_action, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_ATM_CLASSIFIER_ERROR_PARAMETER_SET: + /* call the error parameter set function */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_wimax_cst_encoding_rules, csper_tree, proto_wimax_utility_decoders, tvb, offset-get_tlv_value_offset(&tlv_info), tlv_len, "Classifier Error Parameter Set"); + wimax_error_parameter_set_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + default: + /* display the unknown ATM CS encoding in hex */ + add_tlv_subtree(&tlv_info, csper_tree, hf_csper_unknown_type, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + } + } + else + { + switch (tlv_type) + { + case CST_CLASSIFIER_ACTION: + add_tlv_subtree(&tlv_info, csper_tree, hf_cst_classifier_dsc_action, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_CLASSIFIER_ERROR_PARAM_SET: + case CST_PHS_ERROR_PARAM_SET: + tlv_tree = add_protocol_subtree(&tlv_info, ett_wimax_cst_encoding_rules, csper_tree, proto_wimax_utility_decoders, tvb, offset-get_tlv_value_offset(&tlv_info), tlv_len, "Classifier Error Parameter Set"); + /* call the error parameter set function */ + wimax_error_parameter_set_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case CST_PACKET_CLASSIFICATION_RULE: + { + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, csper_tree, hf_cst_pkt_class_rule, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_cst_encoding_rules); + tlv_offset = offset; + while(tlv_offset < (tlv_len + offset)) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, tlv_offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Packet Classification Rule TLV error"); + proto_tree_add_item(tlv_tree, hf_cst_invalid_tlv, tvb, offset, (tlv_len - tlv_offset), ENC_NA); + break; + } +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(csper_tree, proto_wimax_utility_decoders, tvb, tlv_offset, (length + get_tlv_value_offset(&tlv_info)), "Packet Classification Rule TLV Type: %u (%u bytes, offset=%u, tlv_len=%u)", tlv_type, length, tlv_offset, tlv_len); +#endif + /* update the offset */ + tlv_offset += get_tlv_value_offset(&tlv_info); + switch (tlv_type) + { + case CST_PKT_CLASS_RULE_PRIORITY: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_priority, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_RANGE_MASK: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_range_mask, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_tos_low, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_tos_high, tvb, tlv_offset + 1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_tos_mask, tvb, tlv_offset + 2, 1, ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_PROTOCOL: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_protocol, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_SRC_IP: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_ip_masked_src_address, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + if(ipv6) + { + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_src_ipv6, tvb, tlv_offset, 16, ENC_NA); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_mask_ipv6, tvb, tlv_offset + 16, 16, ENC_NA); + } + else + { + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_src_ipv4, tvb, tlv_offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_mask_ipv4, tvb, tlv_offset + 4, 4, ENC_BIG_ENDIAN); + } + break; + case CST_PKT_CLASS_RULE_DST_IP: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_ip_masked_dest_address, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + if(ipv6) + { + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_dest_ipv6, tvb, tlv_offset, 16, ENC_NA); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_mask_ipv6, tvb, tlv_offset + 16, 16, ENC_NA); + } + else + { + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_dest_ipv4, tvb, tlv_offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_mask_ipv4, tvb, tlv_offset + 4, 4, ENC_BIG_ENDIAN); + } + break; + case CST_PKT_CLASS_RULE_SRCPORT_RANGE: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_prot_src_port_range, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_src_port_low, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_src_port_high, tvb, tlv_offset + 2, 2, ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_DSTPORT_RANGE: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_prot_dest_port_range, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_dest_port_low, tvb, tlv_offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_dest_port_high, tvb, tlv_offset + 2, 2, ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_DST_MAC: + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_dest_mac_address, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + /* add TLV subtree */ + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_dest_mac, tvb, tlv_offset, 6, ENC_NA); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_mask_mac, tvb, tlv_offset + 6, 6, ENC_NA); + break; + case CST_PKT_CLASS_RULE_SRC_MAC: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_src_mac_address, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_src_mac, tvb, tlv_offset, 6, ENC_NA); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_mask_mac, tvb, tlv_offset + 6, 6, ENC_NA); + break; + case CST_PKT_CLASS_RULE_ETHERTYPE: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_ethertype, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_etype, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_eprot1, tvb, tlv_offset + 1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_eprot2, tvb, tlv_offset + 2, 1, ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_USER_PRIORITY: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_user_priority, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_pri_low, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_pri_high, tvb, tlv_offset + 1, 1, ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_VLAN_ID: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_vlan_id, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_vlan_id1, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_vlan_id2, tvb, tlv_offset + 1, 1, ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_PHSI: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_phsi, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_INDEX: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_index, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_IPv6_FLOW_LABEL: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_ipv6_flow_label, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_VENDOR_SPEC: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_vendor_spec, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + case CST_CLASSIFIER_ACTION_RULE: + /* add TLV subtree */ + ti_item = add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_pkt_class_rule_classifier_action_rule, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + ti_tree = proto_item_add_subtree(ti_item, ett_wimax_cst_encoding_rules); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_classifier_action_rule_bit0, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(ti_tree, hf_cst_pkt_class_rule_classifier_action_rule_bit1, tvb, tlv_offset, 1, ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_LARGE_CONTEXT_ID: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_large_context_id, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_PKT_CLASS_RULE_SHORT_FORMAT_CONTEXT_ID: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_short_format_context_id, tvb, tlv_offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + default: + break; + } /* end of switch */ + tlv_offset += length; + } /* end of while loop */ + break; + } + case CST_PHS_DSC_ACTION: + add_tlv_subtree(&tlv_info, csper_tree, hf_cst_phs_dsc_action, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_BIG_ENDIAN); + break; + case CST_PHS_RULE: + { + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, csper_tree, hf_cst_phs_rule, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_cst_encoding_rules); + tlv_offset = offset; + while(tlv_offset < (tlv_len + offset)) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, tlv_offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + length = get_tlv_length(&tlv_info); + if(tlv_type == -1 || length > MAX_TLV_LEN || length < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "PHS n Rule TLV error"); + proto_tree_add_item(tlv_tree, hf_cst_invalid_tlv, tvb, offset, (tlv_len - tlv_offset), ENC_NA); + break; + } +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(csper_tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len+2+get_tlv_size_of_length(&tlv_info)), "PHS Rule TLV Type: %u (%u bytes, offset=%u, tlv_len=%u)", tlv_type, length, offset, tlv_len); +#endif + switch (tlv_type) + { + case CST_PHS_PHSI: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_phs_phsi, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case CST_PHS_PHSF: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_phs_phsf, tvb, tlv_offset, ENC_NA); + break; + case CST_PHS_PHSM: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_phs_phsm, tvb, tlv_offset, ENC_NA); + break; + case CST_PHS_PHSS: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_phs_phss, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case CST_PHS_PHSV: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_phs_phsv, tvb, tlv_offset, ENC_BIG_ENDIAN); + break; + case CST_PHS_VENDOR_SPEC: + add_tlv_subtree(&tlv_info, tlv_tree, hf_cst_phs_vendor_spec, tvb, tlv_offset, ENC_NA); + break; + } + tlv_offset += (length+get_tlv_value_offset(&tlv_info)); + } + break; + } + default: + /* display the unknown csper type in hex */ + add_tlv_subtree(&tlv_info, tree, hf_csper_unknown_type, tvb, offset-get_tlv_value_offset(&tlv_info), ENC_NA); + break; + } /* end of switch */ + } /* end of if */ + offset += tlv_len; + } /* end of while loop */ +} + +/**************************************************************/ +/* wimax_service_flow_encodings_decoder() */ +/* decode and display the WiMax Service Flow Encodings */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure*/ +/**************************************************************/ +void wimax_service_flow_encodings_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset, i; + guint tvb_len, tlv_len, tlv_value_offset, tlv_value; + gint tlv_type; + guint value; + proto_item *tlv_item = NULL; + proto_tree *tlv_tree = NULL; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); +#ifdef DEBUG /* for debug only */ + /* display dissector information */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, 0, tvb_len, "WiMax Service Flow Encodings (%u bytes)", tvb_len); +#endif + /* process WiMax Service Flow Encodings */ + offset = 0; + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid Service Flow Encodings"); + return; + } + while(offset < tvb_len) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Service Flow Encodings TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "Service Flow Encodings TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len); +#endif + /* update the offset */ + offset += tlv_value_offset; + /* parse the Service Flow Encodings TLV */ + switch (tlv_type) + { + case SFE_SF_ID: + add_tlv_subtree(&tlv_info, tree, hf_sfe_sf_id, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_CID: + add_tlv_subtree(&tlv_info, tree, hf_sfe_cid, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_SERVICE_CLASS_NAME: + add_tlv_subtree(&tlv_info, tree, hf_sfe_service_class_name, tvb, offset-tlv_value_offset, ENC_ASCII|ENC_NA); + break; + case SFE_MBS_SERVICE: + add_tlv_subtree(&tlv_info, tree, hf_sfe_mbs_service, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_QOS_PARAMS_SET: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_sfe_qos_params_set, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_service_flow_encodings); + proto_tree_add_item(tlv_tree, hf_sfe_set_provisioned, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_set_admitted, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_set_active, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_set_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SFE_TRAFFIC_PRIORITY: + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_sfe_traffic_priority, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + proto_item_append_text(tlv_item, " (allowed values are 0-7)"); + break; + case SFE_MAX_STR: + add_tlv_subtree(&tlv_info, tree, hf_sfe_max_str, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_MAX_TRAFFIC_BURST: + add_tlv_subtree(&tlv_info, tree, hf_sfe_max_traffic_burst, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_MIN_RTR: + add_tlv_subtree(&tlv_info, tree, hf_sfe_min_rtr, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_RESERVED_10: + add_tlv_subtree(&tlv_info, tree, hf_sfe_reserved_10, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_UL_SCHEDULING: + /* TODO: Find a way to get the correct service type from the TLV */ + tlv_value = tvb_get_guint8(tvb, offset); + set_service_type( tlv_value ); + add_tlv_subtree(&tlv_info, tree, hf_sfe_ul_grant_scheduling, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_TX_POLICY: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_sfe_req_tx_policy, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_service_flow_encodings); + proto_tree_add_item(tlv_tree, hf_sfe_policy_broadcast_bwr, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_policy_multicast_bwr, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_policy_piggyback, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_policy_fragment, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_policy_headers, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_policy_packing, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_policy_crc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_sfe_policy_rsvd1, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case SFE_TOLERATED_JITTER: + add_tlv_subtree(&tlv_info, tree, hf_sfe_jitter, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_MAX_LATENCY: + add_tlv_subtree(&tlv_info, tree, hf_sfe_max_latency, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_FIXED_LEN_SDU: + add_tlv_subtree(&tlv_info, tree, hf_sfe_fixed_len_sdu, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_SDU_SIZE: + /* save the SDU size */ + mac_sdu_length = tvb_get_guint8(tvb, offset); + add_tlv_subtree(&tlv_info, tree, hf_sfe_sdu_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_TARGET_SAID: + add_tlv_subtree(&tlv_info, tree, hf_sfe_target_said, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_ARQ_ENABLE: + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_enable, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_ARQ_WINDOW_SIZE: + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_window_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_ARQ_TRANSMITTER_DELAY: + if (include_cor2_changes) + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_transmitter_delay_cor2, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + else + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_transmitter_delay, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + break; + case SFE_ARQ_RECEIVER_DELAY: + if (include_cor2_changes) + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_receiver_delay_cor2, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + else + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_receiver_delay, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + break; + case SFE_ARQ_BLOCK_LIFETIME: + if (include_cor2_changes) + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_block_lifetime_cor2, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + else + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_block_lifetime, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + break; + case SFE_ARQ_SYNC_LOSS_TIMEOUT: + if (include_cor2_changes) + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_sync_loss_timeout_cor2, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + else + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_sync_loss_timeout, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + break; + case SFE_ARQ_DELIVER_IN_ORDER: + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_deliver_in_order, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_ARQ_RX_PURGE_TIMEOUT: + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_rx_purge_timeout, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_ARQ_BLOCK_SIZE: + if (include_cor2_changes) + { + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_block_size_cor2, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + /* add TLV subtree */ + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_service_flow_encodings); + value = tvb_get_guint8(tvb, offset); + tlv_item = proto_tree_add_item(tlv_tree, hf_sfe_arq_min_block_size, tvb, offset, 1, ENC_BIG_ENDIAN); + /* Size is 2^((value & 0x0F) + 4)) */ + proto_item_append_text(tlv_item, " ( %d bytes )", 0x10 << (value & 0x0F)); + tlv_item = proto_tree_add_item(tlv_tree, hf_sfe_arq_max_block_size, tvb, offset, 1, ENC_BIG_ENDIAN); + if (value & 0xF0) + /* Size is 2^(((value & 0xF0) >> 4) + 4)) */ + proto_item_append_text(tlv_item, " ( %d bytes )", 0x10 << ((value & 0xF0) >> 4)); + } + else + { + add_tlv_subtree(&tlv_info, tree, hf_sfe_arq_block_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + } + break; + case SFE_CS_SPECIFICATION: + add_tlv_subtree(&tlv_info, tree, hf_sfe_cs_specification, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_TYPE_OF_DATA_DELIVERY_SERVICES: + add_tlv_subtree(&tlv_info, tree, hf_sfe_type_of_data_delivery_services, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_SDU_INTER_ARRIVAL_INTERVAL: + add_tlv_subtree(&tlv_info, tree, hf_sfe_sdu_inter_arrival_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_TIME_BASE: + add_tlv_subtree(&tlv_info, tree, hf_sfe_time_base, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_PAGING_PREFERENCE: + add_tlv_subtree(&tlv_info, tree, hf_sfe_paging_preference, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_MBS_ZONE_IDENTIFIER_ASSIGNMENT: + add_tlv_subtree(&tlv_info, tree, hf_sfe_mbs_zone_identifier_assignment, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_RESERVED_34: + add_tlv_subtree(&tlv_info, tree, hf_sfe_reserved_34, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_GLOBAL_SERVICE_CLASS_NAME: + add_tlv_subtree(&tlv_info, tree, hf_sfe_global_service_class_name, tvb, offset-tlv_value_offset, ENC_ASCII|ENC_NA); + break; +/* 36 reserved */ + case SFE_RESERVED_36: + add_tlv_subtree(&tlv_info, tree, hf_sfe_reserved_36, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + + case SFE_SN_FEEDBACK_ENABLED: + add_tlv_subtree(&tlv_info, tree, hf_sfe_sn_feedback_enabled, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_FSN_SIZE: + add_tlv_subtree(&tlv_info, tree, hf_sfe_fsn_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_CID_ALLOCATION_FOR_ACTIVE_BS: + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_sfe_cid_alloc_for_active_bs_cid, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_service_flow_encodings); + for(i = 0; i < tlv_len; i+=2) + proto_tree_add_item(tlv_tree, hf_sfe_cid_alloc_for_active_bs_cid, tvb, (offset+i), 2, ENC_BIG_ENDIAN); + break; + case SFE_UNSOLICITED_GRANT_INTERVAL: + add_tlv_subtree(&tlv_info, tree, hf_sfe_unsolicited_grant_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_UNSOLOCITED_POLLING_INTERVAL: + add_tlv_subtree(&tlv_info, tree, hf_sfe_unsolicited_polling_interval, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_PDU_SN_EXT_SUBHEADER_HARQ_REORDER: + add_tlv_subtree(&tlv_info, tree, hf_sfe_pdu_sn_ext_subheader_reorder, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_MBS_CONTENTS_ID: + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_sfe_mbs_contents_ids, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_service_flow_encodings); + for(i = 0; i < tlv_len; i+=2) + proto_tree_add_item(tlv_tree, hf_sfe_mbs_contents_ids_id, tvb, (offset+i), 2, ENC_BIG_ENDIAN); + break; + case SFE_HARQ_SERVICE_FLOWS: + add_tlv_subtree(&tlv_info, tree, hf_sfe_harq_service_flows, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case SFE_AUTHORIZATION_TOKEN: + add_tlv_subtree(&tlv_info, tree, hf_sfe_authorization_token, tvb, offset-tlv_value_offset, ENC_NA); + break; + case SFE_HARQ_CHANNEL_MAPPING: + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_sfe_harq_channel_mapping_index, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_wimax_service_flow_encodings); + for(i = 0; i < tlv_len; i++) + proto_tree_add_item(tlv_tree, hf_sfe_harq_channel_mapping_index, tvb, (offset+i), 1, ENC_BIG_ENDIAN); + break; +/* 99 - 111 CS parameter encodings */ + case SFE_CSPER_ATM: + case SFE_CSPER_PACKET_IPV4: + case SFE_CSPER_PACKET_IPV6: + case SFE_CSPER_PACKET_802_3: + case SFE_CSPER_PACKET_802_1Q: + case SFE_CSPER_PACKET_IPV4_802_3: + case SFE_CSPER_PACKET_IPV6_802_3: + case SFE_CSPER_PACKET_IPV4_802_1Q: + case SFE_CSPER_PACKET_IPV6_802_1Q: + case SFE_CSPER_PACKET_IP_ROCH_COMPRESSION: + case SFE_CSPER_PACKET_IP_ECRTP_COMPRESSION: + case SFE_CSPER_PACKET_IP_802_3_ROCH_COMPRESSION: + case SFE_CSPER_PACKET_IP_802_3_ECRTP_COMPRESSION: + /* call CS Parameter Encoding Rules handling function */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_wimax_service_flow_encodings, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "CS Parameter Encoding Rules"); + wimax_convengence_service_parameter_encoding_rules_decoder(tlv_type, tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + default: + add_tlv_subtree(&tlv_info, tree, hf_sfe_unknown_type, tvb, offset-tlv_value_offset, ENC_NA); + break; + } /* end of switch */ + offset += tlv_len; + } /* end of while loop */ +} + +/**************************************************************/ +/* wimax_hmac_tuple_decoder() */ +/* decode and display the WiMax HMAC Tuple (Table 348) */ +/* parameter: */ +/* tree - pointer of Wireshark display tree */ +/* tvb - pointer of the tvb which contains the HMAC Tuple */ +/* offset - the HMAC Tuple offset in the tvb */ +/* length - length of the HMAC Tuple */ +/**************************************************************/ +void wimax_hmac_tuple_decoder(proto_tree *tree, tvbuff_t *tvb, guint offset, guint length) +{ + guint hmac_offset; + proto_item *hmac_item = NULL; + proto_tree *hmac_tree = NULL; + + /* display decoder info (length should be 21 bytes) */ + hmac_item = proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, length, "HMAC Tuple (%u bytes)", length); + /* add HMAC subtree */ + hmac_tree = proto_item_add_subtree(hmac_item, ett_wimax_hmac_tuple); + /* init the local offset */ + hmac_offset = offset; + /* decode and display HMAC Tuple */ + proto_tree_add_item(hmac_tree, hf_xmac_tuple_rsvd, tvb, hmac_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(hmac_tree, hf_xmac_tuple_key_seq_num, tvb, hmac_offset, 1, ENC_BIG_ENDIAN); + hmac_offset++; + proto_tree_add_item(hmac_tree, hf_hmac_tuple_hmac_digest, tvb, hmac_offset, (length-1), ENC_NA); +} + +/**************************************************************/ +/* wimax_cmac_tuple_decoder() */ +/* decode and display the WiMax CMAC Tuple (Table 348b) */ +/* parameter: */ +/* tree - pointer of Wireshark display tree */ +/* tvb - pointer of the tvb which contains the CMAC Tuple */ +/* offset - the CMAC Tuple offset in the tvb */ +/* length - length of the CMAC Tuple */ +/**************************************************************/ +void wimax_cmac_tuple_decoder(proto_tree *tree, tvbuff_t *tvb, guint offset, guint length) +{ + guint cmac_offset; + proto_item *cmac_item = NULL; + proto_tree *cmac_tree = NULL; + + /* display decoder info (length should be 13 or 19 bytes) */ + cmac_item = proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, length, "CMAC Tuple (%u bytes)", length); + /* add CMAC subtree */ + cmac_tree = proto_item_add_subtree(cmac_item, ett_wimax_cmac_tuple); + /* init the local offset */ + cmac_offset = offset; + /* decode and display CMAC Tuple */ + proto_tree_add_item(cmac_tree, hf_xmac_tuple_rsvd, tvb, cmac_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(cmac_tree, hf_xmac_tuple_key_seq_num, tvb, cmac_offset, 1, ENC_BIG_ENDIAN); + cmac_offset++; + if(length > 13) + { + proto_tree_add_item(cmac_tree, hf_cmac_tuple_bsid, tvb, cmac_offset, 6, ENC_NA); + cmac_offset += 6; + } + proto_tree_add_item(cmac_tree, hf_packet_number_counter, tvb, cmac_offset, 4, ENC_BIG_ENDIAN); + cmac_offset += 4; + proto_tree_add_item(cmac_tree, hf_cmac_tuple_cmac_value, tvb, cmac_offset, 8, ENC_NA); +} + +/******************************************************************/ +/* wimax_short_hmac_tuple_decoder() */ +/* decode and display the WiMax Short-HMAC Tuple (Table 348d) */ +/* parameter: */ +/* tree - pointer of Wireshark display tree */ +/* tvb - pointer of the tvb which contains the Short-HMAC Tuple */ +/* offset - the Short-HMAC Tuple offset in the tvb */ +/* length - length of the Short-HMAC Tuple */ +/******************************************************************/ +void wimax_short_hmac_tuple_decoder(proto_tree *tree, tvbuff_t *tvb, guint offset, guint length) +{ + guint hmac_offset; + proto_item *hmac_item = NULL; + proto_tree *hmac_tree = NULL; + + /* display decoder info (length should be at least 13 bytes ???) */ + hmac_item = proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, length, "Short-HMAC Tuple (%u bytes)", length); + /* add Short-HMAC subtree */ + hmac_tree = proto_item_add_subtree(hmac_item, ett_wimax_short_hmac_tuple); + /* init the local offset */ + hmac_offset = offset; + /* decode and display Short-HMAC Tuple */ + proto_tree_add_item(hmac_tree, hf_xmac_tuple_rsvd, tvb, hmac_offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(hmac_tree, hf_xmac_tuple_key_seq_num, tvb, hmac_offset, 1, ENC_BIG_ENDIAN); + hmac_offset++; + proto_tree_add_item(hmac_tree, hf_packet_number_counter, tvb, hmac_offset, 4, ENC_BIG_ENDIAN); + hmac_offset += 4; + proto_tree_add_item(hmac_tree, hf_hmac_tuple_hmac_digest, tvb, hmac_offset, length - offset - 3, ENC_NA); +} + +/******************************************************************/ +/* wimax_security_negotiation_parameters_decoder() */ +/* decode and display the WiMax Security Negotiation Parameters */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +void wimax_security_negotiation_parameters_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + proto_tree *tlv_tree; + proto_item *tlv_item; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid Security Negotiation Parameters"); + return; + } + /* process Security Negotiation Parameter TLVs */ + for(offset = 0; offset < tvb_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Security Negotiation Params TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "Security Negotiation Parameters Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* update the offset */ + offset += tlv_value_offset; + /* parse Security Negotiation Parameters TLVs */ + switch (tlv_type) + { + case PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_PKM_VERSION_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_snp_pkm_version_support, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_security_negotiation_parameters); + proto_tree_add_item(tlv_tree, hf_snp_pkm_version_support_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_pkm_version_support_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_pkm_version_support_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_AUTHORIZATION_POLICY_SUPPORT: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_snp_auth_policy_support, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_security_negotiation_parameters); + proto_tree_add_item(tlv_tree, hf_snp_auth_policy_support_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_auth_policy_support_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_auth_policy_support_bit2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_auth_policy_support_bit3, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_auth_policy_support_bit4, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_auth_policy_support_bit5, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_auth_policy_support_bit6, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_auth_policy_support_bit7, tvb, offset, 1, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_MESSAGE_AUTHENTICATION_CODE: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_snp_mac_mode, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_security_negotiation_parameters); + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + if (include_cor2_changes) + { + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_bit1_rsvd, tvb, offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + } + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_bit2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_bit3, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_bit4, tvb, offset, 1, ENC_BIG_ENDIAN); + if (include_cor2_changes) + { + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_bit5, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + } + else + { + proto_tree_add_item(tlv_tree, hf_snp_mac_mode_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); + } + break; + case PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_PN_WINDOW_SIZE: + add_tlv_subtree(&tlv_info, tree, hf_snp_pn_window_size, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_PKM_FLOW_CONTROL: + add_tlv_subtree(&tlv_info, tree, hf_snp_max_conc_transactions, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SECURITY_NEGOTIATION_PARAMETER_SUB_MAX_SUPPT_SECURITY_ASSNS: + add_tlv_subtree(&tlv_info, tree, hf_snp_max_suppt_sec_assns, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + default: + add_tlv_subtree(&tlv_info, tree, hf_snp_unknown_type, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + offset += tlv_len; + } +} + +/******************************************************************/ +/* wimax_cryptographic_suite_list_decoder() */ +/* decode and display the WiMax Cryptographic Suite List */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +void wimax_cryptographic_suite_list_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + proto_tree *tlv_tree; + proto_item *tlv_item; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid Crypto Suite List"); + return; + } + /* process Cryptographic Suite List (11.9.15) */ + for(offset = 0; offset < tvb_len; ) + { /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Crypto Suite List TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "Cryptographic Suite List TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* update the offset for the TLV value */ + offset += tlv_value_offset; + /* parse Cryptographic Suite List */ + switch (tlv_type) + { + case PKM_ATTR_CRYPTO_SUITE: + /* add subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_crypto_suite, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + tlv_tree = proto_item_add_subtree(tlv_item, ett_cryptographic_suite_list_decoder); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_msb, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_middle, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_lsb, tvb, offset+2, 1, ENC_BIG_ENDIAN); + break; + default: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_unknown_type, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + offset += tlv_len; + } /* end of TLV process while loop */ +} + +/******************************************************************/ +/* wimax_pkm_tlv_encoded_attributes_decoder() */ +/* decode and display the WiMax PKM message TLV Encoded Attributes*/ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +void wimax_pkm_tlv_encoded_attributes_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + proto_tree *tlv_tree; + proto_item *tlv_item; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid PKM TLV"); + return; + } + /* process PKM message TLV Encoded Attributes (11.9) */ + for(offset = 0; offset < tvb_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "PKM TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "PKM TLV Encoded Attributes TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* update the offset for the TLV value */ + offset += tlv_value_offset; + /* parse PKM TLV Encoded Attributes (table 370) */ + switch (tlv_type) + { + case PKM_ATTR_DISPLAY_STRING: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_display, tvb, offset-tlv_value_offset, ENC_ASCII|ENC_NA); + break; + case PKM_ATTR_AUTH_KEY: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_auth_key, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_TEK: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_tek, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_KEY_LIFE_TIME: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_key_life_time, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_KEY_SEQ_NUM: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_key_seq_num, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_HMAC_DIGEST: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_hmac_digest, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_SAID: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_said, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_TEK_PARAM: + tlv_tree = add_protocol_subtree(&tlv_info, ett_pkm_tlv_encoded_attributes_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "TEK Parameters"); + /* add subtree */ + wimax_tek_parameters_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case PKM_ATTR_CBC_IV: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_cbc_iv, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_ERROR_CODE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_error_code, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_CA_CERTIFICATE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_ca_certificate, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_SS_CERTIFICATE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_ss_certificate, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_SECURITY_CAPABILITIES: + tlv_tree = add_protocol_subtree(&tlv_info, ett_pkm_tlv_encoded_attributes_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "Security Capabilities"); + /* add subtree */ + wimax_security_capabilities_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case PKM_ATTR_CRYPTO_SUITE: + /* add subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_crypto_suite, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_pkm_tlv_encoded_attributes_decoder); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_msb, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_middle, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_lsb, tvb, offset+2, 1, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_CRYPTO_LIST: + tlv_tree = add_protocol_subtree(&tlv_info, ett_pkm_tlv_encoded_attributes_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "Cryptographic-Suite List"); + /* add subtree */ + wimax_cryptographic_suite_list_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; +#if 0 /* rserved by IEE 802.16E */ + case PKM_ATTR_VERSION: + proto_tree_add_item(tree, hf_pkm_msg_version, tvb, offset, tlv_len, ENC_BIG_ENDIAN); + break; +#endif + case PKM_ATTR_SA_DESCRIPTOR: + tlv_tree = add_protocol_subtree(&tlv_info, ett_pkm_tlv_encoded_attributes_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "SA-Descriptor"); + /* add subtree */ + wimax_sa_descriptor_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case PKM_ATTR_SA_TYPE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_sa_type, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SECURITY_NEGOTIATION_PARAMETERS: + tlv_tree = add_protocol_subtree(&tlv_info, ett_pkm_tlv_encoded_attributes_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "Security Negotiation Parameters"); + /* add subtree */ + wimax_security_negotiation_parameters_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case PKM_ATTR_PKM_CONFIG_SETTINGS: + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_pkm_tlv_encoded_attributes_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "PKM Configuration Settings"); + wimax_pkm_configuration_settings_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case PKM_ATTR_PKM_EAP_PAYLOAD: + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_eap_payload, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_pkm_tlv_encoded_attributes_decoder); + if (eap_handle) + call_dissector(eap_handle, tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case PKM_ATTR_PKM_NONCE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_nonce, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_AUTH_RESULT_CODE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_auth_result_code, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SA_SERVICE_TYPE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_sa_service_type, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_FRAME_NUMBER: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_frame_number, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SS_RANDOM: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_ss_random, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_BS_RANDOM: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_bs_random, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_PRE_PAK: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_pre_pak, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_BS_CERTIFICATE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_bs_certificate, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_SIG_BS: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_sig_bs, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_MS_MAC_ADDRESS: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_ms_mac_address, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_CMAC_DIGEST: + /* add TLV subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_cmac_digest, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_pkm_tlv_encoded_attributes_decoder); + proto_tree_add_item(tlv_tree, hf_pkm_attr_cmac_digest_pn, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_pkm_attr_cmac_digest_value, tvb, (offset + 4), 8, ENC_NA); + break; + case PKM_ATTR_KEY_PUSH_MODES: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_push_modes, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_KEY_PUSH_COUNTER: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_key_push_counter, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_GKEK: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_gkek, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_SIG_SS: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_sig_ss, tvb, offset-tlv_value_offset, ENC_NA); + break; + case PKM_ATTR_AKID: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_akid, tvb, offset-tlv_value_offset, ENC_NA); + break; + default: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_unknown_type, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + offset += tlv_len; + } /* end of TLV process while loop */ +} + +/******************************************************************/ +/* wimax_tek_parameters_decoder() */ +/* decode and display the WiMax TEK Parameters subattributes */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +void wimax_tek_parameters_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid TEK Params"); + return; + } + /* process PKM Message TEK Parameters (11.9.8) */ + for(offset = 0; offset < tvb_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "TEK Param TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "TEK Parameters Subattributes TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* parse TEK Parameters Subattributes (table 372) */ + switch (tlv_type) + { + case PKM_ATTR_TEK: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_tek, tvb, offset, ENC_NA); + break; + case PKM_ATTR_KEY_LIFE_TIME: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_key_life_time, tvb, offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_KEY_SEQ_NUM: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_key_seq_num, tvb, offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_CBC_IV: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_cbc_iv, tvb, offset, ENC_NA); + break; + case PKM_ATTR_ASSOCIATED_GKEK_SEQ_NUM: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_associated_gkek_seq_number, tvb, offset, ENC_NA); + break; + default: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_unknown_type, tvb, offset, ENC_NA); + break; + } + offset += (tlv_len+tlv_value_offset); + } /* end of TLV process while loop */ +} + +/******************************************************************/ +/* wimax_pkm_configuration_settings_decoder() */ +/* decode and display the WiMax PKM Configuration Settings */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +void wimax_pkm_configuration_settings_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid PKM Config Settings"); + return; + } + /* process PKM Configuration Settings (11.9.19) */ + for(offset = 0; offset < tvb_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "PKM Config Settings TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "PKM Configuration Settings TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* parse PKM Configuration Settings (11.9.19.1 - 11.9.19.7 */ + switch (tlv_type) + { + case PKM_ATTR_PKM_CONFIG_SETTINGS_AUTHORIZE_WAIT_TIMEOUT: + add_tlv_subtree(&tlv_info, tree, hf_pkm_config_settings_authorize_waitout, tvb, offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_PKM_CONFIG_SETTINGS_REAUTHORIZE_WAIT_TIMEOUT: + add_tlv_subtree(&tlv_info, tree, hf_pkm_config_settings_reauthorize_waitout, tvb, offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_PKM_CONFIG_SETTINGS_AUTHORIZATION_GRACE_TIME: + add_tlv_subtree(&tlv_info, tree, hf_pkm_config_settings_grace_time, tvb, offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_PKM_CONFIG_SETTINGS_OPERATIONAL_WAIT_TIMEOUT: + add_tlv_subtree(&tlv_info, tree, hf_pkm_config_settings_operational_waittime, tvb, offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_PKM_CONFIG_SETTINGS_REKEY_WAIT_TIMEOUT: + add_tlv_subtree(&tlv_info, tree, hf_pkm_config_settings_rekey_wait_timeout, tvb, offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_PKM_CONFIG_SETTINGS_TEK_GRACE_TIME: + add_tlv_subtree(&tlv_info, tree, hf_pkm_config_settings_tek_grace_time, tvb, offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_PKM_CONFIG_SETTINGS_AUTHORIZE_REJECT_WAIT_TIMEOUT: + add_tlv_subtree(&tlv_info, tree, hf_pkm_config_settings_authorize_reject_wait_timeout, tvb, offset, ENC_BIG_ENDIAN); + break; + default: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_unknown_type, tvb, offset, ENC_NA); + break; + } + offset += (tlv_len+tlv_value_offset); + } /* end of TLV process while loop */ +} + +/******************************************************************/ +/* wimax_sa_descriptor_decoder() */ +/* decode and display the WiMax PKM message SA-Descriptor */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +void wimax_sa_descriptor_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + proto_tree *tlv_tree; + proto_item *tlv_item; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid SA-Descriptor"); + return; + } + /* process SA-Descriptor (11.9.17) */ + for(offset = 0; offset < tvb_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "SA-Descriptor TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "SA-Descriptor TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* update the offset for the TLV value */ + offset += tlv_value_offset; + /* parse SA-Descriptor (table 380) */ + switch (tlv_type) + { + case PKM_ATTR_SAID: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_attr_said, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SA_TYPE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_sa_type, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_SA_SERVICE_TYPE: + add_tlv_subtree(&tlv_info, tree, hf_pkm_attr_sa_service_type, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case PKM_ATTR_CRYPTO_SUITE: + /* add subtree */ + tlv_item = add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_crypto_suite, tvb, offset-tlv_value_offset, ENC_NA); + tlv_tree = proto_item_add_subtree(tlv_item, ett_sa_descriptor_decoder); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_msb, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_middle, tvb, offset+1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_pkm_msg_crypto_suite_lsb, tvb, offset+2, 1, ENC_BIG_ENDIAN); + break; + default: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_unknown_type, tvb, offset-tlv_value_offset, ENC_NA); + break; + } + offset += tlv_len; + } /* end of TLV process while loop */ +} + +/******************************************************************/ +/* wimax_security_capabilities_decoder() */ +/* decode and display the WiMax Security Capabilities */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +void wimax_security_capabilities_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + proto_tree *tlv_tree = NULL; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid Security Capabilities"); + return; + } + /* process Security Capabilities (11.9.13) */ + for(offset = 0; offset < tvb_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Security Capabilities TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "Security Capabilities TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* parse Security Capabilities (table 374) */ + switch (tlv_type) + { + case PKM_ATTR_CRYPTO_LIST: + tlv_tree = add_protocol_subtree(&tlv_info, ett_security_capabilities_decoder, tree, proto_wimax_utility_decoders, tvb, offset, tlv_len, "Cryptographic-Suite List"); + /* add subtree */ + wimax_cryptographic_suite_list_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + default: + add_tlv_subtree(&tlv_info, tree, hf_pkm_msg_unknown_type, tvb, offset, ENC_NA); + break; + } + offset += (tlv_len+tlv_value_offset); + } /* end of TLV process while loop */ +} + +/******************************************************************/ +/* wimax_vendor_specific_information_decoder() */ +/* decode and display the WiMax Vendor-Specific Information */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +void wimax_vendor_specific_information_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + tlv_info_t tlv_info; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid Vendor Specific Info"); + proto_tree_add_expert(tree, pinfo, &ei_common_tlv_info, tvb, 0, tvb_len); + return; + } + /* process Vendor Specific Information (11.1.6) */ + for(offset = 0; offset < tvb_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Vendor Specific Info TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "Vendor Specific Info TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* parse Vendor Specific Information (11.1.6) */ + if(tlv_type == VENDOR_ID_ENCODING) + { + /* decode and display the Vendor ID Encoding */ + add_tlv_subtree(&tlv_info, tree, hf_common_tlv_vendor_id, tvb, offset, ENC_NA); + } + else + { + /* decode and display the Vendor Specific Info */ + proto_tree_add_item(tree, hf_common_tlv_vendor_specific_type, tvb, offset, 1, ENC_BIG_ENDIAN); + if(get_tlv_length_type(&tlv_info) == 0) + { /* single byte TLV length */ + proto_tree_add_item(tree, hf_common_tlv_vendor_specific_length, tvb, (offset + 1), 1, ENC_BIG_ENDIAN); + } + else + { /* multiple bytes TLV length */ + /* display the length of the TLV length with MSB */ + proto_tree_add_item(tree, hf_common_tlv_vendor_specific_length_size, tvb, (offset + 1), 1, ENC_BIG_ENDIAN); + if(get_tlv_size_of_length(&tlv_info)) + { /* display the multiple byte TLV length */ + proto_tree_add_uint(tree, hf_common_tlv_vendor_specific_length, tvb, (offset + 2), 1, get_tlv_size_of_length(&tlv_info)); + } + else + { /* length = 0 */ + continue; + } + } + proto_tree_add_item(tree, hf_common_tlv_vendor_specific_value, tvb, (offset + tlv_value_offset), tlv_len, ENC_NA); + } + /* update the offset */ + offset += tlv_value_offset + tlv_len; + } +} + +/******************************************************************/ +/* wimax_common_tlv_encoding_decoder() */ +/* decode and display the WiMax Common TLV Encoding (Table 346) */ +/* parameter: */ +/* tvb - pointer of the tvb of service flow encodings */ +/* tree - pointer of Wireshark display tree */ +/* pinfo - pointer of Wireshark packet information structure */ +/******************************************************************/ +guint wimax_common_tlv_encoding_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + guint offset, value; + guint tvb_len, tlv_len, tlv_value_offset; + gint tlv_type; + proto_tree *tlv_tree = NULL; + tlv_info_t tlv_info; + gfloat current_power; + + /* get the tvb reported length */ + tvb_len = tvb_reported_length(tvb); + /* do nothing if the TLV fields is not exist */ + if(!tvb_len) + return 0; + /* report error if the packet size is less than 2 bytes (type+length) */ + if(tvb_len < 2) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Invalid Common TLV encoding"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, 0, tvb_len, ENC_NA); + return 0; + } + /* process Common TLV Encoding (11.1) */ + for(offset = 0; offset < tvb_len; ) + { + /* get the TLV information */ + init_tlv_info(&tlv_info, tvb, offset); + /* get the TLV type */ + tlv_type = get_tlv_type(&tlv_info); + /* get the TLV length */ + tlv_len = get_tlv_length(&tlv_info); + if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1) + { /* invalid tlv info */ + col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Common TLV encoding TLV error"); + proto_tree_add_item(tree, hf_cst_invalid_tlv, tvb, offset, (tvb_len - offset), ENC_NA); + break; + } + /* get the TLV value offset */ + tlv_value_offset = get_tlv_value_offset(&tlv_info); +#ifdef DEBUG /* for debug only */ + proto_tree_add_protocol_format(tree, proto_wimax_utility_decoders, tvb, offset, (tlv_len + tlv_value_offset), "Common TLV Encoding TLV Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, (tlv_len + tlv_value_offset), offset, tvb_len); +#endif + /* update the offset for the TLV value */ + offset += tlv_value_offset; + /* parse Common TLV Encoding (table 346) */ + switch (tlv_type) + { + case VENDOR_SPECIFIC_INFO: + /* display Vendor-Specific Information */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_vendor_specific_info_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "Vendor-Specific Information"); + /* decode and display the Vendor-Specific Information */ + wimax_vendor_specific_information_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case VENDOR_ID_ENCODING: + add_tlv_subtree(&tlv_info, tree, hf_common_tlv_vendor_id, tvb, offset-tlv_value_offset, ENC_NA); + break; + case DSx_UPLINK_FLOW: + /* display Uplink Service Flow Encodings info */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_ul_service_flow_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "Uplink Service Flow Encodings"); + /* decode and display the UL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb, offset, tlv_len), pinfo, tlv_tree); + break; + case DSx_DOWNLINK_FLOW: + /* display Downlink Service Flow Encodings info */ + /* add subtree */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_dl_service_flow_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "Downlink Service Flow Encodings"); + /* decode and display the DL Service Flow Encodings */ + wimax_service_flow_encodings_decoder(tvb_new_subset_length(tvb,offset, tlv_len), pinfo, tlv_tree); + break; + case CURRENT_TX_POWER: + tlv_tree = add_tlv_subtree_no_item(&tlv_info, tree, hf_common_current_transmitted_power, tvb, offset-tlv_value_offset); + value = tvb_get_guint8(tvb, offset); + current_power = (gfloat)((value - 128) / 2.0); + proto_tree_add_float_format_value(tlv_tree, hf_common_current_transmitted_power, tvb, offset, tvb_len, current_power, "%.2f dBm (Value: 0x%x)", current_power, value); + break; + case MAC_VERSION_ENCODING: + add_tlv_subtree(&tlv_info, tree, hf_common_tlv_mac_version, tvb, offset-tlv_value_offset, ENC_BIG_ENDIAN); + break; + case HMAC_TUPLE: /* Table 348d */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_vendor_specific_info_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "HMAC Tuple"); + /* decode and display the HMAC Tuple */ + wimax_hmac_tuple_decoder(tlv_tree, tvb, offset, tlv_len); + break; + case CMAC_TUPLE: /* Table 348b */ + tlv_tree = add_protocol_subtree(&tlv_info, ett_vendor_specific_info_decoder, tree, proto_wimax_utility_decoders, tvb, offset-tlv_value_offset, tlv_len, "CMAC Tuple"); + /* decode and display the CMAC Tuple */ + wimax_cmac_tuple_decoder(tlv_tree, tvb, offset, tlv_len); + break; + default: + /* Back to calling routine to finish decoding. */ + return offset - tlv_value_offset; /* Ret amount decoded. */ + break; + } + offset += tlv_len; + } /* end of while loop */ + return offset; +} + +/* + * 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: + */ diff --git a/plugins/epan/wimax/wimax_utils.h b/plugins/epan/wimax/wimax_utils.h new file mode 100644 index 00000000..0a78e223 --- /dev/null +++ b/plugins/epan/wimax/wimax_utils.h @@ -0,0 +1,58 @@ +/* wimax_utils.h + * Header file of WiMax Utility Decoders + * + * Copyright (c) 2007 by Intel Corporation. + * + * Author: Lu Pan + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1999 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef WIMAX_UTILS_H +#define WIMAX_UTILS_H + +#include + +extern void dissect_extended_tlv(proto_tree *reg_req_tree, gint tlv_type, tvbuff_t *tvb, guint tlv_offset, guint tlv_len, packet_info *pinfo, guint offset, gint proto_registry); +extern void dissect_power_saving_class(proto_tree *rng_req_tree, gint tlv_type, tvbuff_t *tvb, guint compound_tlv_len, packet_info *pinfo, guint offset); +extern gint dissect_ulmap_ie(proto_tree *ie_tree, packet_info* pinfo, gint offset, gint length, tvbuff_t *tvb); +extern guint get_service_type(void); +extern void init_wimax_globals(void); /* defined in msg_ulmap.c */ +extern gboolean is_down_link(packet_info *pinfo); +extern gint RCID_IE(proto_tree *diuc_tree, gint offset, gint length, tvbuff_t *tvb, gint RCID_Type); +extern void wimax_service_flow_encodings_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_convengence_service_parameter_encoding_rules_decoder(guint sfe_type, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern gint wimax_decode_ulmapc(proto_tree *base_tree, packet_info* pinfo, gint offset, gint length, tvbuff_t *tvb); +extern gint wimax_decode_ulmap_reduced_aas(proto_tree *ie_tree, gint offset, gint length, tvbuff_t *tvb); +extern gint wimax_decode_dlmapc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pdu_tree); +extern gint wimax_decode_dlmap_reduced_aas(tvbuff_t *tvb, packet_info *pinfo, proto_tree *base_tree); +extern void wimax_error_parameter_set_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_hmac_tuple_decoder(proto_tree *tree, tvbuff_t *tvb, guint offset, guint length); +extern void wimax_cmac_tuple_decoder(proto_tree *tree, tvbuff_t *tvb, guint offset, guint length); +extern void wimax_short_hmac_tuple_decoder(proto_tree *tree, tvbuff_t *tvb, guint offset, guint length); +extern void wimax_security_negotiation_parameters_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_tek_parameters_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_pkm_configuration_settings_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_sa_descriptor_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_pkm_tlv_encoded_attributes_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_cryptographic_suite_list_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_security_capabilities_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern void wimax_vendor_specific_information_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); +extern guint wimax_common_tlv_encoding_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); + +//Windows can't handle plugins using globals from epan, so copies are necessary +extern const unit_name_string wimax_units_byte_bytes; +extern const unit_name_string wimax_units_bit_sec; +extern const unit_name_string wimax_units_db; +extern const unit_name_string wimax_units_dbm; +extern const unit_name_string wimax_units_frame_frames; +extern const unit_name_string wimax_units_frame_offset; +extern const unit_name_string wimax_units_hz; +extern const unit_name_string wimax_units_khz; +extern const unit_name_string wimax_units_ms; +extern const unit_name_string wimax_units_ps; + +#endif /* WIMAX_UTILS_H */ diff --git a/plugins/epan/wimaxasncp/AUTHORS b/plugins/epan/wimaxasncp/AUTHORS new file mode 100644 index 00000000..4a80a584 --- /dev/null +++ b/plugins/epan/wimaxasncp/AUTHORS @@ -0,0 +1,5 @@ +Authors : +Stephen Croll +Zhang Li +Wu Yanping +Terry Le diff --git a/plugins/epan/wimaxasncp/CMakeLists.txt b/plugins/epan/wimaxasncp/CMakeLists.txt new file mode 100644 index 00000000..4775ef98 --- /dev/null +++ b/plugins/epan/wimaxasncp/CMakeLists.txt @@ -0,0 +1,70 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(wimaxasncp 0 0 1 0) + +set(DISSECTOR_SRC + packet-wimaxasncp.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +add_lex_files(LEX_FILES PLUGIN_FILES + wimaxasncp_dict.l +) + +set_source_files_properties( + ${DISSECTOR_SRC} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_wireshark_plugin_library(wimaxasncp epan) + +target_link_libraries(wimaxasncp epan) + +install_plugin(wimaxasncp epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + wimaxasncp + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS} +# LEX files commented out due to use of malloc, free etc. +# ${LEX_FILES} +) + +# +# 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: +# diff --git a/plugins/epan/wimaxasncp/ChangeLog b/plugins/epan/wimaxasncp/ChangeLog new file mode 100644 index 00000000..dccc5305 --- /dev/null +++ b/plugins/epan/wimaxasncp/ChangeLog @@ -0,0 +1,16 @@ +2007-08-29 Stephen Croll + + * initial version + +2007-10-09 Stephen Croll + + * TLVs defined in XML files. + + * packet-wimaxasncp.c: fixed memory leak in function + wimaxasncp_dissect_tlv_value() + +2007-11-04 Zhang Li + + * Add EAP support. EAP payload is dessected by calling EAP dissector + * Add port preference. + diff --git a/plugins/epan/wimaxasncp/packet-wimaxasncp.c b/plugins/epan/wimaxasncp/packet-wimaxasncp.c new file mode 100644 index 00000000..082d9eae --- /dev/null +++ b/plugins/epan/wimaxasncp/packet-wimaxasncp.c @@ -0,0 +1,3468 @@ +/* packet-wimaxasncp.c + * + * Routines for WiMAX ASN Control Plane packet dissection dissection + * + * Copyright 2007, Mobile Metrics - http://www.mobilemetrics.net + * + * Author: Stephen Croll + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + + +#include "config.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wimaxasncp_dict.h" + +/* Forward declarations we need below */ +void proto_register_wimaxasncp(void); +void proto_reg_handoff_wimaxasncp(void); + +/* Initialize the protocol and registered fields */ +static int proto_wimaxasncp = -1; +static int hf_wimaxasncp_version = -1; +static int hf_wimaxasncp_flags = -1; +static int hf_wimaxasncp_function_type = -1; +static int hf_wimaxasncp_op_id = -1; +static int hf_wimaxasncp_message_type = -1; +/* static int hf_wimaxasncp_qos_msg = -1; */ +/* static int hf_wimaxasncp_ho_control_msg = -1; */ +/* static int hf_wimaxasncp_data_path_control_msg = -1; */ +/* static int hf_wimaxasncp_context_delivery_msg = -1; */ +/* static int hf_wimaxasncp_r3_mobility_msg = -1; */ +/* static int hf_wimaxasncp_paging_msg = -1; */ +/* static int hf_wimaxasncp_rrm_msg = -1; */ +/* static int hf_wimaxasncp_authentication_msg = -1; */ +/* static int hf_wimaxasncp_ms_state_msg = -1; */ +/* static int hf_wimaxasncp_reauthentication_msg = -1; */ +/* static int hf_wimaxasncp_session_msg = -1; */ +static int hf_wimaxasncp_length = -1; +static int hf_wimaxasncp_msid = -1; +static int hf_wimaxasncp_reserved1 = -1; +static int hf_wimaxasncp_transaction_id = -1; +static int hf_wimaxasncp_reserved2 = -1; +/* static int hf_wimaxasncp_tlv = -1; */ +static int hf_wimaxasncp_tlv_type = -1; +static int hf_wimaxasncp_tlv_length = -1; +static int hf_wimaxasncp_tlv_value_bytes = -1; +static int hf_wimaxasncp_tlv_value_bitflags8 = -1; +static int hf_wimaxasncp_tlv_value_bitflags16 = -1; +static int hf_wimaxasncp_tlv_value_bitflags32 = -1; +/* static int hf_wimaxasncp_tlv_value_protocol = -1; */ +/* static int hf_wimaxasncp_tlv_value_vendor_id = -1; */ + +/* Preferences */ +static gboolean show_transaction_id_d_bit = FALSE; +static gboolean debug_enabled = FALSE; + +/* Default WiMAX ASN control protocol port */ +#define WIMAXASNCP_DEF_UDP_PORT 2231 + + +/* Initialize the subtree pointers */ +static gint ett_wimaxasncp = -1; +static gint ett_wimaxasncp_flags = -1; +static gint ett_wimaxasncp_tlv = -1; +static gint ett_wimaxasncp_tlv_value_bitflags8 = -1; +static gint ett_wimaxasncp_tlv_value_bitflags16 = -1; +static gint ett_wimaxasncp_tlv_value_bitflags32 = -1; +static gint ett_wimaxasncp_tlv_protocol_list = -1; +static gint ett_wimaxasncp_tlv_port_range_list = -1; +static gint ett_wimaxasncp_tlv_ip_address_mask_list = -1; +static gint ett_wimaxasncp_tlv_ip_address_mask = -1; +static gint ett_wimaxasncp_tlv_eap = -1; +static gint ett_wimaxasncp_tlv_vendor_specific_information_field = -1; +static gint ett_wimaxasncp_port_range = -1; + +static expert_field ei_wimaxasncp_tlv_type = EI_INIT; +static expert_field ei_wimaxasncp_function_type = EI_INIT; +static expert_field ei_wimaxasncp_op_id = EI_INIT; +static expert_field ei_wimaxasncp_message_type = EI_INIT; +static expert_field ei_wimaxasncp_length_bad = EI_INIT; + +/* Header size, up to, but not including, the TLV fields. */ +#define WIMAXASNCP_HEADER_SIZE 20 + +/* Offset to end of the length field in the headder. */ +#define WIMAXASNCP_HEADER_LENGTH_END 6 + +#define WIMAXASNCP_BIT32(n) (1U << (31 - (n))) +#define WIMAXASNCP_BIT16(n) (1U << (15 - (n))) +#define WIMAXASNCP_BIT8(n) (1U << ( 7 - (n))) + +#define WIMAXASNCP_FLAGS_T WIMAXASNCP_BIT8(6) +#define WIMAXASNCP_FLAGS_R WIMAXASNCP_BIT8(7) + +typedef struct { + wmem_array_t* hf; + wmem_array_t* ett; +} wimaxasncp_build_dict_t; + +static wimaxasncp_dict_t *wimaxasncp_dict = NULL; + +wimaxasncp_build_dict_t wimaxasncp_build_dict; + +static wimaxasncp_dict_tlv_t wimaxasncp_tlv_not_found = +{ + 0, "Unknown", NULL, WIMAXASNCP_TLV_UNKNOWN, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + NULL, NULL, NULL +}; + +static dissector_handle_t wimaxasncp_handle; +static dissector_handle_t eap_handle; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxasncp_flag_vals[] = +{ + { WIMAXASNCP_BIT8(0), "Reserved" }, + { WIMAXASNCP_BIT8(1), "Reserved" }, + { WIMAXASNCP_BIT8(2), "Reserved" }, + { WIMAXASNCP_BIT8(3), "Reserved" }, + { WIMAXASNCP_BIT8(4), "Reserved" }, + { WIMAXASNCP_BIT8(5), "Reserved" }, + { WIMAXASNCP_FLAGS_T, "T - Source and Destination Identifier TLVs"}, + { WIMAXASNCP_FLAGS_R, "R - Reset Next Expected Transaction ID"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxasncp_op_id_vals[] = +{ + { 0, "Invalid"}, + { 1, "Request/Initiation"}, + { 2, "Response"}, + { 3, "Ack"}, + { 4, "Indication"}, + { 5, "Reserved"}, + { 6, "Reserved"}, + { 7, "Reserved"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +#define WIMAXASNCP_FT_QOS 1 +#define WIMAXASNCP_FT_HO_CONTROL 2 +#define WIMAXASNCP_FT_DATA_PATH_CONTROL 3 +#define WIMAXASNCP_FT_CONTEXT_TRANSFER 4 +#define WIMAXASNCP_FT_R3_MOBILITY 5 +#define WIMAXASNCP_FT_PAGING 6 +#define WIMAXASNCP_FT_RRM 7 +#define WIMAXASNCP_FT_AUTHENTICATION 8 +#define WIMAXASNCP_FT_MS_STATE 9 +#define WIMAXASNCP_FT_REAUTHENTICATION 10 +/* since NWG R1 V1.2.0 */ +#define WIMAXASNCP_FT_IM_OPERATIONS 10 +/* since NWG R1 V1.2.1 */ +#define WIMAXASNCP_FT_ACCOUNTING 11 + +/* ------------------------------------------------------------------------- */ + +/* struct to hold a value_string tuple, per version */ +typedef struct _ver_value_string +{ + guint32 since; + value_string vs; +} ver_value_string; + +static const ver_value_string wimaxasncp_function_type_vals[] = +{ + {0, { WIMAXASNCP_FT_QOS, "QoS"}}, + {0, { WIMAXASNCP_FT_HO_CONTROL, "HO Control"}}, + {0, { WIMAXASNCP_FT_DATA_PATH_CONTROL, "Data Path Control"}}, + {0, { WIMAXASNCP_FT_CONTEXT_TRANSFER, "Context Transfer"}}, + {0, { WIMAXASNCP_FT_R3_MOBILITY, "R3 Mobility"}}, + {0, { WIMAXASNCP_FT_PAGING, "Paging"}}, + {0, { WIMAXASNCP_FT_RRM, "RRM"}}, + {0, { WIMAXASNCP_FT_AUTHENTICATION, "Authentication Relay"}}, + {0, { WIMAXASNCP_FT_MS_STATE, "MS State"}}, + {0, { WIMAXASNCP_FT_REAUTHENTICATION, "Re-Authentication"}}, + {WIMAXASNCP_NWGVER_R10_V120, {WIMAXASNCP_FT_IM_OPERATIONS, "IM Operations"}}, + {WIMAXASNCP_NWGVER_R10_V121, { WIMAXASNCP_FT_ACCOUNTING, "Accounting"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_qos_msg_vals[] = +{ + {0,{ 1, "RR_Req"}}, + {0,{ 2, "RR_Rsp"}}, + {0,{ 3, "RR_Ack"}}, + {0,{ 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_ho_control_msg_vals[] = +{ + {0, { 1, "HO_Ack"}}, + {0, { 2, "HO_Complete"}}, + {0, { 3, "HO_Cnf"}}, + {0, { 4, "HO_Req"}}, + {0, { 5, "HO_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 1, "HO_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 2, "HO_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 3, "HO_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 4, "HO_Cnf"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 5, "HO_Complete"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 6, "HO_Directive"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 7, "HO_Directive_Rsp"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_data_path_control_msg_vals[] = +{ + {0, { 1, "Path_Dereg_Ack"}}, + {0, { 2, "Path_Dereg_Req"}}, + {0, { 3, "Path_Dereg_Rsp"}}, + {0, { 4, "Path_Modification_Ack"}}, + {0, { 5, "Path_Modification_Req"}}, + {0, { 6, "Path_Modification_Rsp"}}, + {0, { 7, "Path_Prereg_Ack"}}, + {0, { 8, "Path_Prereg_Req"}}, + {0, { 9, "Path_Prereg_Rsp"}}, + {0, { 10, "Path_Reg_Ack"}}, + {0, { 11, "Path_Reg_Req"}}, + {0, { 12, "Path_Reg_Rsp"}}, + {0, { 13, "MS_Attachment_Req"}}, + {0, { 14, "MS_Attachment_Rsp"}}, + {0, { 15, "MS_Attachment_Ack"}}, + {0, { 16, "Key_Change_Directive"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 1, "Path_Dereg_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 2, "Path_Dereg_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 3, "Path_Dereg_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 4, "Path_Modification_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 5, "Path_Modification_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 6, "Path_Modification_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 7, "Path_Prereg_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 8, "Path_Prereg_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 9, "Path_Prereg_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 10, "Path_Reg_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 11, "Path_Reg_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 12, "Path_Reg_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 13, "Obsolete"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 14, "Obsolete"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 15, "Obsolete"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 16, "Obsolete"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_context_transfer_msg_vals[] = +{ + {0, { 1, "Context_Rpt"}}, + {0, { 2, "Context_Req"}}, + {0, { 3, "Context_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 1, "Context_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 2, "Context_Rpt"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 4, "CMAC_Key_Count_Update"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 5, "CMAC_Key_Count_Update_ACK"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 6, "CMAC_Key_Count_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 7, "CMAC_Key_Count_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 8, "Prepaid Request"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 9, "Prepaid Notify"}}, + {WIMAXASNCP_NWGVER_R10_V121, { 6, "VOID"}}, + {WIMAXASNCP_NWGVER_R10_V121, { 7, "VOID"}}, + {WIMAXASNCP_NWGVER_R10_V121, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_r3_mobility_msg_vals[] = +{ + {0, { 1, "Anchor_DPF_HO_Req"}}, + {0, { 2, "Anchor_DPF_HO_Trigger"}}, + {0, { 3, "Anchor_DPF_HO_Rsp"}}, + {0, { 4, "Anchor_DPF_Relocate_Req"}}, + {0, { 5, "FA_Register_Req"}}, + {0, { 6, "FA_Register_Rsp"}}, + {0, { 7, "Anchor_DPF_Relocate_Rsp"}}, + {0, { 8, "FA_Revoke_Req"}}, + {0, { 9, "FA_Revoke_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 5, "Anchor_DPF_Relocate_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 6, "FA_Register_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 7, "FA_Register_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 10, "Anchor_DPF_Release_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 11, "Relocation_Ready_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 12, "Relocation_Ready_Rsp"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_paging_msg_vals[] = +{ + {0, { 1, "Initiate_Paging_Req"}}, + {0, { 2, "Initiate_Paging_Rsp"}}, + {0, { 3, "LU_Cnf"}}, + {0, { 4, "LU_Req"}}, + {0, { 5, "LU_Rsp"}}, + {0, { 6, "Paging_Announce"}}, + {0, { 7, "CMAC_Key_Count_Req"}}, + {0, { 8, "CMAC_Key_Count_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 1, "Paging_Announce"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 2, "Delete_MS_Entry_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 3, "PC_Relocation_Ind"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 4, "PC_Relocation_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 5, "Obsolete"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 6, "Obsolete"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 7, "Obsolete"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 8, "Obsolete"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_rrm_msg_vals[] = +{ + {0, { 1, "R6 PHY_Parameters_Req"}}, + {0, { 2, "R6 PHY_Parameters_Rpt"}}, + {0, { 3, "R4/R6 Spare_Capacity_Req"}}, + {0, { 4, "R4/R6 Spare_Capacity_Rpt"}}, + {0, { 5, "R6 Neighbor_BS_Resource_Status_Update"}}, + {0, { 6, "R4/R6 Radio_Config_Update_Req"}}, + {0, { 7, "R4/R6 Radio_Config_Update_Rpt"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 8, "R4/R6 Radio_Config_Update_Ack"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_authentication_msg_vals[] = +{ + {0, { 1, "AR_Authenticated_Eap_Start"}}, + {0, { 2, "AR_Authenticated_EAP_Transfer"}}, + {0, { 3, "AR_Eap_Start"}}, + {0, { 4, "AR_EAP_Transfer"}}, + {0, { 5, "AR_EAP_Complete"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 1, "AR_EAP_Start"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 2, "AR_EAP_Transfer"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 3, "Bulk_Interim_Update"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 4, "Bulk_Interim_Update_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 5, "Obsolete"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_ms_state_msg_vals[] = +{ + {0, { 1, "IM_Entry_State_Change_Req"}}, + {0, { 2, "IM_Entry_State_Change_Rsp"}}, + {0, { 3, "IM_Exit_State_Change_Req"}}, + {0, { 4, "IM_Exit_State_Change_Rsp"}}, + {0, { 5, "NW_ReEntry_State_Change_Directive"}}, + {0, { 6, "MS_PreAttachment_Req"}}, + {0, { 7, "MS_PreAttachment_Rsp"}}, + {0, { 8, "MS_PreAttachment_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 1, "MS_PreAttachment_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 2, "MS_PreAttachment_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 3, "MS_PreAttachment_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 4, "MS_Attachment_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 5, "MS_Attachment_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 6, "MS_Attachment_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 7, "Key_Change_Directive"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 8, "Key_Change_Cnf"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 9, "Key_Change_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 10, "Relocation_Complete_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 11, "Relocation_Complete_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 12, "Relocation_Complete_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 13, "Relocation_Notify"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 14, "Relocation_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 15, "Relocation_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 16, "NetExit_MS_State_Change_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 17, "NetExit_MS_State_Change_Rsp"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +/* note - function type 10-im_operation, was once used for re-authrntication */ +static const ver_value_string wimaxasncp_im_operations_msg_vals[] = +{ + {0, { 1, "AR_EAP_Start"}}, + {0, { 2, "Key_Change_Directive"}}, + {0, { 3, "Key_Change_Cnf"}}, + {0, { 4, "Relocation_Cnf"}}, + {0, { 5, "Relocation_Confirm_Ack"}}, + {0, { 6, "Relocation_Notify"}}, + {0, { 7, "Relocation_Notify_Ack"}}, + {0, { 8, "Relocation_Req"}}, + {0, { 9, "Relocation_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 1, "IM_Entry_State_Change_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 2, "IM_Entry_State_Change_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 3, "IM_Entry_State_Change_Ack"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 4, "IM_Exit_State_Change_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 5, "IM_Exit_State_Change_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 6, "Initiate_Paging_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 7, "Initiate_Paging_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 8, "LU_Req"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 9, "LU_Rsp"}}, + {WIMAXASNCP_NWGVER_R10_V120, { 10, "LU_Cnf"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +static const ver_value_string wimaxasncp_accounting_msg_vals_r1v121[] = +{ + {WIMAXASNCP_NWGVER_R10_V121, { 1, "Hot_lining_Req"}}, + {WIMAXASNCP_NWGVER_R10_V121, { 2, "Hot_lining_Rsp"}}, + {0, { 0, NULL}} +}; + +/* ------------------------------------------------------------------------- */ + +/* supported NWG versions */ +static const enum_val_t wimaxasncp_nwg_versions[] = { + { "Release 1.0, Version 1.0.0" , "R1.0 v1.0.0" , WIMAXASNCP_NWGVER_R10_V100 }, + { "Release 1.0, Version 1.2.0" , "R1.0 v1.2.0" , WIMAXASNCP_NWGVER_R10_V120 }, + { "Release 1.0, Version 1.2.1" , "R1.0 v1.2.1" , WIMAXASNCP_NWGVER_R10_V121 }, + { NULL, NULL, 0 } +}; + +/* ------------------------------------------------------------------------- */ + +/* NWG version */ +#define WIMAXASNCP_DEF_NWGVER WIMAXASNCP_NWGVER_R10_V121 +static guint global_wimaxasncp_nwg_ver = WIMAXASNCP_DEF_NWGVER; + +/* ========================================================================= */ + +typedef struct { + guint8 function_type; + const ver_value_string *vals; +} wimaxasncp_func_msg_t; + +/* ------------------------------------------------------------------------ */ + +static const wimaxasncp_func_msg_t wimaxasncp_func_to_msg_vals_map[] = +{ + { WIMAXASNCP_FT_QOS, wimaxasncp_qos_msg_vals }, + { WIMAXASNCP_FT_HO_CONTROL, wimaxasncp_ho_control_msg_vals }, + { WIMAXASNCP_FT_DATA_PATH_CONTROL, wimaxasncp_data_path_control_msg_vals }, + { WIMAXASNCP_FT_CONTEXT_TRANSFER, wimaxasncp_context_transfer_msg_vals }, + { WIMAXASNCP_FT_R3_MOBILITY, wimaxasncp_r3_mobility_msg_vals }, + { WIMAXASNCP_FT_PAGING, wimaxasncp_paging_msg_vals }, + { WIMAXASNCP_FT_RRM, wimaxasncp_rrm_msg_vals }, + { WIMAXASNCP_FT_AUTHENTICATION, wimaxasncp_authentication_msg_vals }, + { WIMAXASNCP_FT_MS_STATE, wimaxasncp_ms_state_msg_vals }, + { WIMAXASNCP_FT_IM_OPERATIONS, wimaxasncp_im_operations_msg_vals }, + { WIMAXASNCP_FT_ACCOUNTING, wimaxasncp_accounting_msg_vals_r1v121 } +}; + +/* ========================================================================= */ + +static const wimaxasncp_dict_tlv_t *wimaxasncp_get_tlv_info( + guint16 type) +{ + wimaxasncp_dict_tlv_t *res = NULL; + + if (wimaxasncp_dict) + { + wimaxasncp_dict_tlv_t *tlv; + + for (tlv = wimaxasncp_dict->tlvs; tlv; tlv = tlv->next) + { + if (tlv->type == type) + { + /* if the TLV is defined for current NWG version */ + if (tlv->since<= global_wimaxasncp_nwg_ver) + { + /* if the current TLV is newer then last found TLV, save it */ + if (!res || (tlv->since > res->since)) + { + res = tlv; + } + } + } + } + } + + if (debug_enabled && !res) + { + g_print("fix-me: unknown TLV type: %u\n", type); + } + + return res? res:&wimaxasncp_tlv_not_found; +} + +/* ========================================================================= */ + +static const gchar *wimaxasncp_get_enum_name( + const wimaxasncp_dict_tlv_t *tlv_info, + guint32 code) +{ + if (tlv_info->enum_vs) + { + return val_to_str_const(code, tlv_info->enum_vs, "Unknown"); + } + else + { + return "Unknown"; + } +} + +/* ========================================================================= */ + +static const value_string wimaxasncp_decode_type_vals[] = +{ + { WIMAXASNCP_TLV_UNKNOWN, "WIMAXASNCP_TLV_UNKNOWN"}, + { WIMAXASNCP_TLV_TBD, "WIMAXASNCP_TLV_TBD"}, + { WIMAXASNCP_TLV_COMPOUND, "WIMAXASNCP_TLV_COMPOUND"}, + { WIMAXASNCP_TLV_BYTES, "WIMAXASNCP_TLV_BYTES"}, + { WIMAXASNCP_TLV_ENUM8, "WIMAXASNCP_TLV_ENUM8"}, + { WIMAXASNCP_TLV_ENUM16, "WIMAXASNCP_TLV_ENUM16"}, + { WIMAXASNCP_TLV_ENUM32, "WIMAXASNCP_TLV_ENUM32"}, + { WIMAXASNCP_TLV_ETHER, "WIMAXASNCP_TLV_ETHER"}, + { WIMAXASNCP_TLV_ASCII_STRING, "WIMAXASNCP_TLV_ASCII_STRING"}, + { WIMAXASNCP_TLV_FLAG0, "WIMAXASNCP_TLV_FLAG0"}, + { WIMAXASNCP_TLV_BITFLAGS8, "WIMAXASNCP_TLV_BITFLAGS8"}, + { WIMAXASNCP_TLV_BITFLAGS16, "WIMAXASNCP_TLV_BITFLAGS16"}, + { WIMAXASNCP_TLV_BITFLAGS32, "WIMAXASNCP_TLV_BITFLAGS32"}, + { WIMAXASNCP_TLV_ID, "WIMAXASNCP_TLV_ID"}, + { WIMAXASNCP_TLV_HEX8, "WIMAXASNCP_TLV_HEX8"}, + { WIMAXASNCP_TLV_HEX16, "WIMAXASNCP_TLV_HEX16"}, + { WIMAXASNCP_TLV_HEX32, "WIMAXASNCP_TLV_HEX32"}, + { WIMAXASNCP_TLV_DEC8, "WIMAXASNCP_TLV_DEC8"}, + { WIMAXASNCP_TLV_DEC16, "WIMAXASNCP_TLV_DEC16"}, + { WIMAXASNCP_TLV_DEC32, "WIMAXASNCP_TLV_DEC32"}, + { WIMAXASNCP_TLV_IP_ADDRESS, "WIMAXASNCP_TLV_IP_ADDRESS"}, + { WIMAXASNCP_TLV_IPV4_ADDRESS, "WIMAXASNCP_TLV_IPV4_ADDRESS"}, + { WIMAXASNCP_TLV_PROTOCOL_LIST, "WIMAXASNCP_TLV_PROTOCOL_LIST"}, + { WIMAXASNCP_TLV_PORT_RANGE_LIST, "WIMAXASNCP_TLV_PORT_RANGE_LIST"}, + { WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST, "WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST"}, + { WIMAXASNCP_TLV_VENDOR_SPECIFIC, "WIMAXASNCP_TLV_VENDOR_SPECIFIC"}, + { 0, NULL} +}; + +/* ========================================================================= */ + +static void wimaxasncp_proto_tree_add_tlv_ipv4_value( + packet_info *pinfo, + tvbuff_t *tvb, + proto_tree *tree, + proto_item *tlv_item, + guint offset, + const wimaxasncp_dict_tlv_t *tlv_info) +{ + int hf_value; + guint32 ip; + const gchar *addr_res; + + if (tlv_info->hf_ipv4 != -1) + { + hf_value = tlv_info->hf_ipv4; + } + else + { + hf_value = tlv_info->hf_value; + } + + ip = tvb_get_ipv4(tvb, offset); + addr_res = tvb_address_with_resolution_to_str(pinfo->pool, tvb, AT_IPv4, offset); + + proto_tree_add_ipv4_format( + tree, hf_value, + tvb, offset, 4, ip, + "Value: %s", addr_res); + + proto_item_append_text( + tlv_item, " - %s", addr_res); +} + +/* ========================================================================= */ + +static void wimaxasncp_proto_tree_add_tlv_ipv6_value( + packet_info *pinfo, + tvbuff_t *tvb, + proto_tree *tree, + proto_item *tlv_item, + guint offset, + const wimaxasncp_dict_tlv_t *tlv_info) +{ + int hf_value; + ws_in6_addr ip; + const gchar *addr_res; + + if (tlv_info->hf_ipv4 != -1) + { + hf_value = tlv_info->hf_ipv6; + } + else + { + hf_value = tlv_info->hf_value; + } + + tvb_get_ipv6(tvb, offset, &ip); + addr_res = tvb_address_with_resolution_to_str(pinfo->pool, tvb, AT_IPv6, offset); + + proto_tree_add_ipv6_format( + tree, hf_value, + tvb, offset, 16, &ip, + "Value: %s", addr_res); + + proto_item_append_text( + tlv_item, " - %s", addr_res); +} + +/* ========================================================================= */ + +static void wimaxasncp_proto_tree_add_ether_value( + packet_info *pinfo, + tvbuff_t *tvb, + proto_tree *tree, + proto_item *tlv_item, + guint offset, + guint length, + const wimaxasncp_dict_tlv_t *tlv_info) +{ + int hf_value; + const guint8 *p; + const gchar *ether_name; + + if (tlv_info->hf_bsid != -1) + { + hf_value = tlv_info->hf_bsid; + } + else + { + hf_value = tlv_info->hf_value; + } + + p = tvb_get_ptr(tvb, offset, length); + ether_name = tvb_address_with_resolution_to_str(pinfo->pool, tvb, AT_ETHER, offset); + + proto_tree_add_ether_format( + tree, hf_value, + tvb, offset, length, p, + "Value: %s", + ether_name); + + proto_item_append_text( + tlv_item, " - %s", + ether_name); +} + +/* ========================================================================= */ + +static void wimaxasncp_dissect_tlv_value( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree, + proto_item *tlv_item, + const wimaxasncp_dict_tlv_t *tlv_info) +{ + guint offset = 0; + guint length; + const guint max_show_bytes = 24; /* arbitrary */ + static const gchar *hex_note = "[hex]"; + + length = tvb_reported_length(tvb); + + switch (tlv_info->decoder) + { + case WIMAXASNCP_TLV_ENUM8: + { + if (length != 1) + { + /* encoding error */ + break; + } + + if (tlv_info->enums == NULL) + { + if (debug_enabled) + { + g_print("fix-me: enum values missing for TLV %s (%u)\n", + tlv_info->name, tlv_info->type); + } + } + + if (tree) + { + guint8 value; + const gchar *s; + + value = tvb_get_guint8(tvb, offset); + + s = wimaxasncp_get_enum_name(tlv_info, value); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: %s (%u)", s, value); + + proto_item_append_text(tlv_item, " - %s", s); + } + + return; + } + case WIMAXASNCP_TLV_ENUM16: + { + if (length != 2) + { + /* encoding error */ + break; + } + + if (tlv_info->enums == NULL) + { + if (debug_enabled) + { + g_print("fix-me: enum values missing for TLV %s (%u)\n", + tlv_info->name, tlv_info->type); + } + } + + if (tree) + { + guint16 value; + const gchar *s; + + value = tvb_get_ntohs(tvb, offset); + + s = wimaxasncp_get_enum_name(tlv_info, value); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: %s (%u)", s, value); + + proto_item_append_text(tlv_item, " - %s", s); + } + + return; + } + case WIMAXASNCP_TLV_ENUM32: + { + if (length != 4) + { + /* encoding error */ + break; + } + + if (tlv_info->enums == NULL) + { + if (debug_enabled) + { + g_print("fix-me: enum values missing for TLV %s (%u)\n", + tlv_info->name, tlv_info->type); + } + } + + if (tree) + { + guint32 value; + const gchar *s; + + value = tvb_get_ntohl(tvb, offset); + + s = wimaxasncp_get_enum_name(tlv_info, value); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: %s (%u)", s, value); + + proto_item_append_text(tlv_item, " - %s", s); + } + + return; + } + case WIMAXASNCP_TLV_ETHER: + { + if (length != 6) + { + /* encoding error */ + break; + } + + if (tree) + { + wimaxasncp_proto_tree_add_ether_value( + pinfo, tvb, tree, tlv_item, offset, length, tlv_info); + } + + return; + } + case WIMAXASNCP_TLV_ASCII_STRING: + { + if (tree) + { + const gchar *s = tvb_get_string_enc(pinfo->pool, tvb, offset, length, ENC_ASCII); + + proto_tree_add_string_format( + tree, tlv_info->hf_value, + tvb, offset, length, s, + "Value: %s", s); + + proto_item_append_text( + tlv_item, " - %s", s); + } + + return; + } + case WIMAXASNCP_TLV_FLAG0: + { + if (length != 0) + { + /* encoding error */ + break; + } + + return; + } + case WIMAXASNCP_TLV_BITFLAGS8: + { + if (length != 1) + { + /* encoding error */ + break; + } + + if (tlv_info->enums == NULL) + { + /* enum values missing */ + } + + if (tree) + { + proto_tree *flags_tree; + proto_item *item; + guint8 value; + guint i; + + value = tvb_get_guint8(tvb, offset); + + item = proto_tree_add_item( + tree, tlv_info->hf_value, + tvb, offset, 1, ENC_NA); + + proto_item_append_text(tlv_item, " - 0x%02x", value); + + if (value != 0) + { + flags_tree = proto_item_add_subtree( + item, ett_wimaxasncp_tlv_value_bitflags8); + + for (i = 0; i < 8; ++i) + { + guint8 mask; + mask = 1U << (7 - i); + + if (value & mask) + { + const gchar *s; + + s = wimaxasncp_get_enum_name(tlv_info, value & mask); + + proto_tree_add_uint_format( + flags_tree, hf_wimaxasncp_tlv_value_bitflags8, + tvb, offset, length, value, + "Bit #%u is set: %s", i, s); + } + } + } + } + + return; + } + case WIMAXASNCP_TLV_BITFLAGS16: + { + if (length != 2) + { + /* encoding error */ + break; + } + + if (tlv_info->enums == NULL) + { + /* enum values missing */ + } + + if (tree) + { + proto_tree *flags_tree; + proto_item *item; + guint16 value; + guint i; + + value = tvb_get_ntohs(tvb, offset); + + item = proto_tree_add_item( + tree, tlv_info->hf_value, + tvb, offset, 2, ENC_BIG_ENDIAN); + + proto_item_append_text(tlv_item, " - 0x%04x", value); + + if (value != 0) + { + flags_tree = proto_item_add_subtree( + item, ett_wimaxasncp_tlv_value_bitflags16); + + for (i = 0; i < 16; ++i) + { + guint16 mask; + mask = 1U << (15 - i); + + if (value & mask) + { + const gchar *s; + + s = wimaxasncp_get_enum_name(tlv_info, value & mask); + + proto_tree_add_uint_format( + flags_tree, hf_wimaxasncp_tlv_value_bitflags16, + tvb, offset, length, value, + "Bit #%u is set: %s", i, s); + } + } + } + } + + return; + } + case WIMAXASNCP_TLV_BITFLAGS32: + { + if (length != 4) + { + /* encoding error */ + break; + } + + if (tlv_info->enums == NULL) + { + /* enum values missing */ + } + + if (tree) + { + proto_tree *flags_tree; + proto_item *item; + guint32 value; + guint i; + + value = tvb_get_ntohl(tvb, offset); + + item = proto_tree_add_item( + tree, tlv_info->hf_value, + tvb, offset, 4, ENC_BIG_ENDIAN); + + proto_item_append_text(tlv_item, " - 0x%08x", value); + + if (value != 0) + { + flags_tree = proto_item_add_subtree( + item, ett_wimaxasncp_tlv_value_bitflags32); + + for (i = 0; i < 32; ++i) + { + guint32 mask; + mask = 1U << (31 - i); + + if (value & mask) + { + const gchar *s; + s = wimaxasncp_get_enum_name(tlv_info, value & mask); + + proto_tree_add_uint_format( + flags_tree, hf_wimaxasncp_tlv_value_bitflags32, + tvb, offset, length, value, + "Bit #%u is set: %s", i, s); + } + } + } + } + + return; + } + case WIMAXASNCP_TLV_ID: + { + if (length == 4) + { + if (tree) + { + wimaxasncp_proto_tree_add_tlv_ipv4_value( + pinfo, tvb, tree, tlv_item, offset, tlv_info); + } + + return; + } + else if (length == 6) + { + if (tree) + { + wimaxasncp_proto_tree_add_ether_value( + pinfo, tvb, tree, tlv_item, offset, length, tlv_info); + } + + return; + } + else if (length == 16) + { + if (tree) + { + wimaxasncp_proto_tree_add_tlv_ipv6_value( + pinfo, tvb, tree, tlv_item, offset, tlv_info); + } + + return; + } + else + { + /* encoding error */ + break; + } + } + case WIMAXASNCP_TLV_BYTES: + { + if (tree) + { + proto_tree_add_item( + tree, tlv_info->hf_value, + tvb, offset, length, ENC_NA); + + if (length) { + const gchar* format; + if (length <= max_show_bytes) + { + format = " - %s"; + } + else + { + format = " - %s..."; + } + const gchar* s = tvb_bytes_to_str_punct( + pinfo->pool, tvb, offset, MIN(length, max_show_bytes), 0); + + proto_item_append_text( + tlv_item, format, s); + } else { + proto_item_append_text(tlv_item, " - "); + } + } + + return; + } + case WIMAXASNCP_TLV_HEX8: + { + if (length != 1) + { + /* encoding error */ + break; + } + + if (tree) + { + guint8 value; + + value = tvb_get_guint8(tvb, offset); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: 0x%02x", value); + + proto_item_append_text(tlv_item, " - 0x%02x", value); + } + + return; + } + case WIMAXASNCP_TLV_HEX16: + { + if (length != 2) + { + /* encoding error */ + break; + } + + if (tree) + { + guint16 value; + + value = tvb_get_ntohs(tvb, offset); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: 0x%04x", value); + + proto_item_append_text(tlv_item, " - 0x%04x", value); + } + + return; + } + case WIMAXASNCP_TLV_HEX32: + { + if (length != 4) + { + /* encoding error */ + break; + } + + if (tree) + { + guint32 value; + + value = tvb_get_ntohl(tvb, offset); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: 0x%08x", value); + + proto_item_append_text(tlv_item, " - 0x%08x", value); + } + + return; + } + case WIMAXASNCP_TLV_DEC8: + { + if (length != 1) + { + /* encoding error */ + break; + } + + if (tree) + { + guint8 value; + + value = tvb_get_guint8(tvb, offset); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: %u", value); + + proto_item_append_text(tlv_item, " - %u", value); + } + + return; + } + case WIMAXASNCP_TLV_DEC16: + { + if (length != 2) + { + /* encoding error */ + break; + } + + if (tree) + { + guint16 value; + + value = tvb_get_ntohs(tvb, offset); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: %u", value); + + proto_item_append_text(tlv_item, " - %u", value); + } + + return; + } + case WIMAXASNCP_TLV_DEC32: + { + if (length != 4) + { + /* encoding error */ + break; + } + + if (tree) + { + guint32 value; + + value = tvb_get_ntohl(tvb, offset); + + proto_tree_add_uint_format( + tree, tlv_info->hf_value, + tvb, offset, length, value, + "Value: %u", value); + + proto_item_append_text(tlv_item, " - %u", value); + } + + return; + } + case WIMAXASNCP_TLV_TBD: + { + if (debug_enabled) + { + g_print( + "fix-me: TBD: TLV %s (%u)\n", tlv_info->name, tlv_info->type); + } + + if (tree) + { + if (length) { + const char *format; + const char *s = tvb_bytes_to_str_punct( + pinfo->pool, tvb, offset, length, 0); + + if (length <= max_show_bytes) { + format = "%s %s"; + } else { + format = "%s %s..."; + } + + proto_tree_add_bytes_format_value( + tree, tlv_info->hf_value, + tvb, offset, length, NULL, format, hex_note, s); + + } else { + proto_tree_add_bytes_format_value( + tree, tlv_info->hf_value, + tvb, offset, length, NULL, "%s", ""); + } + + proto_item_append_text(tlv_item, " - TBD"); + } + + return; + } + case WIMAXASNCP_TLV_IP_ADDRESS: + { + if (length == 4) + { + if (tree) + { + wimaxasncp_proto_tree_add_tlv_ipv4_value( + pinfo, tvb, tree, tlv_item, offset, tlv_info); + } + + return; + } + else if (length == 16) + { + if (tree) + { + wimaxasncp_proto_tree_add_tlv_ipv6_value( + pinfo, tvb, tree, tlv_item, offset, tlv_info); + } + + return; + } + else + { + /* encoding error */ + break; + } + } + case WIMAXASNCP_TLV_IPV4_ADDRESS: + { + if (length != 4) + { + /* encoding error */ + break; + } + + if (tree) + { + wimaxasncp_proto_tree_add_tlv_ipv4_value( + pinfo, tvb, tree, tlv_item, offset, tlv_info); + } + + return; + } + case WIMAXASNCP_TLV_PROTOCOL_LIST: + { + if (length % 2 != 0) + { + /* encoding error */ + break; + } + + if (tree && length > 0) + { + proto_tree *protocol_list_tree; + proto_item *item; + const guint max_protocols_in_tlv_item = 8; /* arbitrary */ + + protocol_list_tree = proto_tree_add_subtree( + tree, tvb, offset, length, + ett_wimaxasncp_tlv_protocol_list, NULL, "Value"); + + /* hidden item for filtering */ + item = proto_tree_add_item( + protocol_list_tree, tlv_info->hf_value, + tvb, offset, length, ENC_NA); + + proto_item_set_hidden(item); + + while (offset < tvb_reported_length(tvb)) + { + guint16 protocol; + const gchar *protocol_name; + + protocol = tvb_get_ntohs(tvb, offset); + protocol_name = ipprotostr(protocol); + + proto_tree_add_uint_format( + protocol_list_tree, tlv_info->hf_protocol, + tvb, offset, 2, protocol, + "Protocol: %s (%u)", protocol_name, protocol); + + if (offset == 0) + { + proto_item_append_text(tlv_item, " - %s", protocol_name); + } + else if (offset < 2 * max_protocols_in_tlv_item) + { + proto_item_append_text(tlv_item, ", %s", protocol_name); + } + else if (offset == 2 * max_protocols_in_tlv_item) + { + proto_item_append_text(tlv_item, ", ..."); + } + + offset += 2; + } + } + + return; + } + case WIMAXASNCP_TLV_PORT_RANGE_LIST: + { + if (length % 4 != 0) + { + /* encoding error */ + break; + } + + if (tree && length > 0) + { + proto_tree *port_range_list_tree; + proto_item *item; + const guint max_port_ranges_in_tlv_item = 3; /* arbitrary */ + + port_range_list_tree = proto_tree_add_subtree( + tree, tvb, offset, length, + ett_wimaxasncp_tlv_port_range_list, NULL, "Value"); + + /* hidden item for filtering */ + item = proto_tree_add_item( + port_range_list_tree, tlv_info->hf_value, + tvb, offset, length, ENC_NA); + + proto_item_set_hidden(item); + + while (offset < tvb_reported_length(tvb)) + { + guint16 portLow; + guint16 portHigh; + proto_tree* range_tree; + + portLow = tvb_get_ntohs(tvb, offset); + portHigh = tvb_get_ntohs(tvb, offset + 2); + + range_tree = proto_tree_add_subtree_format( + port_range_list_tree, tvb, offset, 4, + ett_wimaxasncp_port_range, NULL, "Port Range: %u-%u", portLow, portHigh); + + /* hidden items are for filtering */ + + item = proto_tree_add_item( + range_tree, tlv_info->hf_port_low, + tvb, offset, 2, ENC_BIG_ENDIAN); + + proto_item_set_hidden(item); + + item = proto_tree_add_item( + range_tree, tlv_info->hf_port_high, + tvb, offset + 2, 2, ENC_BIG_ENDIAN); + + proto_item_set_hidden(item); + + if (offset == 0) + { + proto_item_append_text( + tlv_item, " - %u-%u", portLow, portHigh); + } + else if (offset < 4 * max_port_ranges_in_tlv_item) + { + proto_item_append_text( + tlv_item, ", %u-%u", portLow, portHigh); + } + else if (offset == 4 * max_port_ranges_in_tlv_item) + { + proto_item_append_text(tlv_item, ", ..."); + } + + offset += 4; + } + } + + return; + } + case WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST: + { + /* -------------------------------------------------------------------- + * The definion of these TLVs are ambiguous. The length in octets is + * described as Nx8 (IPv4) or Nx32 (IPv6), but this function cannot + * always differentiate between IPv4 and IPv6. For example, if length + * = 32, then is it IPv4 where N=4 (4x8) or IPv6 where N=1 (1x32)? + * + * For now, we presume lengths that *can* indicate an IPv6 address and + * mask list *do* denote an IPv6 address and mask list. + * -------------------------------------------------------------------- + */ + + if (length % 8 != 0) + { + /* encoding error */ + break; + } + + if (tree && length > 0) + { + proto_tree *ip_address_mask_list_tree; + proto_item *item; + + ip_address_mask_list_tree = proto_tree_add_subtree( + tree, tvb, offset, length, + ett_wimaxasncp_tlv_ip_address_mask_list, NULL, "Value"); + + /* hidden item for filtering */ + item = proto_tree_add_item( + ip_address_mask_list_tree, tlv_info->hf_value, + tvb, offset, length, ENC_NA); + + proto_item_set_hidden(item); + + if (length % 32 == 0) + { + /* ------------------------------------------------------------ + * presume IPv6 + * ------------------------------------------------------------ + */ + + while (offset < tvb_reported_length(tvb)) + { + proto_tree *ip_address_mask_tree; + + ip_address_mask_tree = proto_tree_add_subtree( + ip_address_mask_list_tree, tvb, offset, 32, + ett_wimaxasncp_tlv_ip_address_mask, NULL, "IPv6 Address and Mask"); + + /* -------------------------------------------------------- + * address + * -------------------------------------------------------- + */ + + proto_tree_add_item( + ip_address_mask_tree, + tlv_info->hf_ipv6, + tvb, offset, 16, ENC_NA); + + /* too long to display ? + proto_item_append_text( + item, " - %s (%s)", + get_hostname6(&ip), ip6_to_str(&ip)); + */ + + offset += 16; + + /* -------------------------------------------------------- + * mask + * -------------------------------------------------------- + */ + proto_tree_add_item( + ip_address_mask_tree, + tlv_info->hf_ipv6_mask, + tvb, offset, 16, ENC_NA); + + /* too long to display ? + proto_item_append_text( + item, " / %s", s); + */ + + offset += 16; + } + } + else + { + /* ------------------------------------------------------------ + * IPv4 + * ------------------------------------------------------------ + */ + + while (offset < tvb_reported_length(tvb)) + { + proto_tree *ip_address_mask_tree; + guint32 ip; + const gchar *s; + + ip_address_mask_tree = proto_tree_add_subtree( + ip_address_mask_list_tree, tvb, offset, 8, + ett_wimaxasncp_tlv_ip_address_mask, NULL, "IPv4 Address and Mask"); + + /* -------------------------------------------------------- + * address + * -------------------------------------------------------- + */ + + ip = tvb_get_ipv4(tvb, offset); + + proto_tree_add_item( + ip_address_mask_tree, + tlv_info->hf_ipv4, + tvb, offset, 4, ENC_BIG_ENDIAN); + + proto_item_append_text( + item, " - %s (%s)", + get_hostname(ip), tvb_ip_to_str(pinfo->pool, tvb, offset)); + + offset += 4; + + /* -------------------------------------------------------- + * mask + * -------------------------------------------------------- + */ + + s = tvb_ip_to_str(pinfo->pool, tvb, offset); + + proto_tree_add_item( + ip_address_mask_tree, + tlv_info->hf_ipv4_mask, + tvb, offset, 4, ENC_BIG_ENDIAN); + + proto_item_append_text( + item, " / %s", s); + + offset += 4; + } + } + } + + return; + } + case WIMAXASNCP_TLV_EAP: + { + /* + * EAP payload, call eap dissector to dissect eap payload + */ + guint8 eap_code; + guint8 eap_type = 0; + + /* Get code */ + eap_code = tvb_get_guint8(tvb, offset); + if (eap_code == EAP_REQUEST || eap_code == EAP_RESPONSE) + { + /* Get type */ + eap_type = tvb_get_guint8(tvb, offset + 4); + } + + /* Add code and type to info column */ + col_append_str(pinfo->cinfo, COL_INFO, " ["); + col_append_str(pinfo->cinfo, COL_INFO, + val_to_str(eap_code, eap_code_vals, "Unknown code (0x%02X)")); + + if (eap_code == EAP_REQUEST || eap_code == EAP_RESPONSE) + { + col_append_str(pinfo->cinfo, COL_INFO, ", "); + col_append_str(pinfo->cinfo, COL_INFO, + val_to_str_ext(eap_type, &eap_type_vals_ext, "Unknown type (0x%02X)")); + } + + col_append_str(pinfo->cinfo, COL_INFO, "]"); + + + { + proto_tree *eap_tree; + proto_item *item; + gboolean save_writable; + tvbuff_t *eap_tvb; + + /* Create EAP subtree */ + item = proto_tree_add_item(tree, tlv_info->hf_value, tvb, + offset, length, ENC_NA); + proto_item_set_text(item, "Value"); + eap_tree = proto_item_add_subtree(item, ett_wimaxasncp_tlv_eap); + + /* Also show high-level details in this root item */ + proto_item_append_text(item, " (%s", + val_to_str(eap_code, eap_code_vals, + "Unknown code (0x%02X)")); + if (eap_code == EAP_REQUEST || eap_code == EAP_RESPONSE) + { + proto_item_append_text(item, ", %s", + val_to_str_ext(eap_type, &eap_type_vals_ext, + "Unknown type (0x%02X)")); + } + proto_item_append_text(item, ")"); + + + /* Extract remaining bytes into new tvb */ + eap_tvb = tvb_new_subset_remaining(tvb, offset); + + /* Disable writing to info column while calling eap dissector */ + save_writable = col_get_writable(pinfo->cinfo, -1); + col_set_writable(pinfo->cinfo, -1, FALSE); + + /* Call the EAP dissector. */ + call_dissector(eap_handle, eap_tvb, pinfo, eap_tree); + + /* Restore previous writable state of info column */ + col_set_writable(pinfo->cinfo, -1, save_writable); + } + + return; + } + + case WIMAXASNCP_TLV_VENDOR_SPECIFIC: + { + /* -------------------------------------------------------------------- + * The format of the vendor specific information field (VSIF) is not + * clearly defined. It appears to be compound as the spec states + * that the vendor ID field shall be the first TLV embedded inside + * the VSIF. However, the vendor ID is shown as a 24-bit value. Does + * this mean the field is 24-bits? If so, how is alignment/padding + * handled? + * + * For now, we decode the vendor ID as a non-padded 24-bit value and + * dump the rest as hex. + * -------------------------------------------------------------------- + */ + + if (length < 3) + { + /* encoding error */ + break; + } + + if (tree) + { + proto_tree *vsif_tree; + proto_item *item; + guint32 vendorId; + const gchar *vendorName; + + vsif_tree = proto_tree_add_subtree( + tree, tvb, offset, length, + ett_wimaxasncp_tlv_vendor_specific_information_field, NULL, "Value"); + + /* hidden item for filtering */ + item = proto_tree_add_item( + vsif_tree, tlv_info->hf_value, + tvb, offset, length, ENC_NA); + + proto_item_set_hidden(item); + + /* ---------------------------------------------------------------- + * vendor ID (24-bit) + * ---------------------------------------------------------------- + */ + + vendorId = tvb_get_ntoh24(tvb, offset); + + vendorName = enterprises_lookup(vendorId, "Unknown"); + proto_tree_add_uint_format( + vsif_tree, tlv_info->hf_vendor_id, + tvb, offset, 3, vendorId, + "Vendor ID: %s (%u)", vendorName, vendorId); + + proto_item_append_text(tlv_item, " - %s", vendorName); + + offset += 3; + + /* ---------------------------------------------------------------- + * hex dump the rest + * ---------------------------------------------------------------- + */ + + if (offset < tvb_reported_length(tvb)) + { + proto_tree_add_item( + vsif_tree, tlv_info->hf_vendor_rest_of_info, + tvb, offset, length - offset, ENC_NA); + } + } + + return; + } + case WIMAXASNCP_TLV_UNKNOWN: + { + if (tree) + { + const char* s; + if (length) { + const char* format1; + const char* format2; + if (length <= max_show_bytes) + { + format1 = "%s %s"; + format2 = " - %s %s"; + } + else + { + format1 = "%s %s..."; + format2 = " - %s %s..."; + } + s = tvb_bytes_to_str_punct( + pinfo->pool, tvb, offset, MIN(length, max_show_bytes), 0); + + proto_tree_add_bytes_format_value( + tree, tlv_info->hf_value, + tvb, offset, length, NULL, format1, hex_note, s); + + proto_item_append_text( + tlv_item, format2, hex_note, s); + } + else { + proto_tree_add_bytes_format_value( + tree, tlv_info->hf_value, + tvb, offset, length, NULL, "%s", ""); + + proto_item_append_text(tlv_item, " - "); + } + + } + + return; + } + default: + if (debug_enabled) + { + g_print( + "fix-me: unknown decoder: %d\n", tlv_info->decoder); + } + break; + } + + /* default is hex dump */ + + if (tree) + { + if (length) { + const char* format; + const char *s = tvb_bytes_to_str_punct( + pinfo->pool, tvb, offset, MIN(length, max_show_bytes), 0); + + if (length <= max_show_bytes) { + format = "%s %s"; + } else { + format = "%s %s..."; + } + + proto_tree_add_bytes_format_value( + tree, hf_wimaxasncp_tlv_value_bytes, + tvb, offset, length, NULL, + format, hex_note, s); + } else { + proto_tree_add_bytes_format_value( + tree, hf_wimaxasncp_tlv_value_bytes, + tvb, offset, length, NULL, + "%s", ""); + } + } +} + +/* ========================================================================= */ + +static guint dissect_wimaxasncp_tlvs( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree) +{ + guint offset; + + offset = 0; + while (offset < tvb_reported_length(tvb)) + { + const wimaxasncp_dict_tlv_t *tlv_info; + + proto_tree *tlv_tree; + proto_item *tlv_item; + guint16 type; + guint16 length; + guint pad; + + /* -------------------------------------------------------------------- + * type and length + * -------------------------------------------------------------------- + */ + + type = tvb_get_ntohs(tvb, offset); + tlv_info = wimaxasncp_get_tlv_info(type); + + length = tvb_get_ntohs(tvb, offset + 2); +#if 0 /* Commented out padding; As there is no mention of padding in + the Latest specification */ + pad = 4 - (length % 4); + if (pad == 4) + { + pad = 0; + } +#endif + pad = 0; + { + proto_item *type_item; + + gint tree_length = MIN( + (gint)(4 + length + pad), tvb_captured_length_remaining(tvb, offset)); + + tlv_item = proto_tree_add_item( + tree, tlv_info->hf_root, + tvb, offset, tree_length, ENC_NA); + + /* Set label for tlv item */ + proto_item_set_text(tlv_item, "TLV: %s", tlv_info->name); + + /* Show code number if unknown */ + if (tlv_info->decoder == WIMAXASNCP_TLV_UNKNOWN) + { + proto_item_append_text(tlv_item, " (%u)", type); + } + + /* Indicate if a compound tlv */ + if (tlv_info->decoder == WIMAXASNCP_TLV_COMPOUND) + { + proto_item_append_text(tlv_item, " [Compound]"); + } + + /* Create TLV subtree */ + tlv_tree = proto_item_add_subtree( + tlv_item, ett_wimaxasncp_tlv); + + /* Type (expert item if unknown) */ + type_item = proto_tree_add_uint_format( + tlv_tree, hf_wimaxasncp_tlv_type, + tvb, offset, 2, type, + "Type: %s (%u)", tlv_info->name, type); + + if (tlv_info->decoder == WIMAXASNCP_TLV_UNKNOWN) + { + expert_add_info_format(pinfo, type_item, &ei_wimaxasncp_tlv_type, + "Unknown TLV type (%u)", + type); + } + + /* Length */ + proto_tree_add_uint( + tlv_tree, hf_wimaxasncp_tlv_length, + tvb, offset + 2, 2, length); + + } + + offset += 4; + + /* -------------------------------------------------------------------- + * value + * -------------------------------------------------------------------- + */ + + if (tlv_info->decoder == WIMAXASNCP_TLV_COMPOUND) + { + if (length == 0) + { + /* error? compound, but no TLVs inside */ + } + else if (tvb_reported_length_remaining(tvb, offset) > 0) + { + tvbuff_t *tlv_tvb; + + /* N.B. Not padding out tvb length */ + tlv_tvb = tvb_new_subset_length_caplen( + tvb, offset, + MIN(length, tvb_captured_length_remaining(tvb, offset)), + length); + + /* N.B. This is a recursive call... */ + dissect_wimaxasncp_tlvs(tlv_tvb, pinfo, tlv_tree); + } + else + { + /* this should throw */ + tvb_ensure_bytes_exist(tvb, offset, length + pad); + } + } + else + { + tvbuff_t *tlv_tvb; + + tvb_ensure_bytes_exist(tvb, offset, length + pad); + + tlv_tvb = tvb_new_subset_length_caplen( + tvb, offset, + MIN(length, tvb_captured_length_remaining(tvb, offset)), + length); + + wimaxasncp_dissect_tlv_value( + tlv_tvb, pinfo, tlv_tree, tlv_item, tlv_info); + } + + offset += length + pad; + } + + return offset; +} + +/* ========================================================================= */ + +static guint dissect_wimaxasncp_backend( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree) +{ + guint offset = 0; + guint16 ui16; + guint32 ui32; + const guint8 *pmsid; + guint16 tid = 0; + gboolean dbit_show; + + + /* ------------------------------------------------------------------------ + * MSID + * ------------------------------------------------------------------------ + */ + + if (tree) + { + proto_tree_add_item( + tree, hf_wimaxasncp_msid, + tvb, offset, 6, ENC_NA); + } + pmsid = tvb_ether_to_str(pinfo->pool, tvb, offset); + + offset += 6; + + /* ------------------------------------------------------------------------ + * reserved + * ------------------------------------------------------------------------ + */ + + ui32 = tvb_get_ntohl(tvb, offset); + + if (tree) + { + proto_tree_add_uint( + tree, hf_wimaxasncp_reserved1, + tvb, offset, 4, ui32); + } + + offset += 4; + + /* ------------------------------------------------------------------------ + * transaction ID + * ------------------------------------------------------------------------ + */ + + dbit_show = FALSE; + ui16 = tvb_get_ntohs(tvb, offset); + + if (show_transaction_id_d_bit) + { + const guint16 mask = 0x7fff; + + if (ui16 & 0x8000) + { + proto_tree_add_uint_format( + tree, hf_wimaxasncp_transaction_id, + tvb, offset, 2, ui16, + "Transaction ID: D + 0x%04x (0x%04x)", mask & ui16, ui16); + + tid = ui16 & mask; + dbit_show = TRUE; + } + else + { + proto_tree_add_uint_format( + tree, hf_wimaxasncp_transaction_id, + tvb, offset, 2, ui16, + "Transaction ID: 0x%04x", ui16); + + tid = ui16; + } + } + else + { + proto_tree_add_uint( + tree, hf_wimaxasncp_transaction_id, + tvb, offset, 2, ui16); + + tid = ui16; + } + + offset += 2; + + /* ------------------------------------------------------------------------ + * reserved + * ------------------------------------------------------------------------ + */ + + ui16 = tvb_get_ntohs(tvb, offset); + + if (tree) + { + proto_tree_add_uint( + tree, hf_wimaxasncp_reserved2, + tvb, offset, 2, ui16); + } + + offset += 2; + + /* ------------------------------------------------------------------------ + * TLVs + * ------------------------------------------------------------------------ + */ + + if (tvb_reported_length_remaining(tvb, offset) > 0) + { + tvbuff_t *tlv_tvb; + + tlv_tvb = tvb_new_subset_remaining(tvb, offset); + + offset += dissect_wimaxasncp_tlvs(tlv_tvb, pinfo, tree); + } + + col_append_fstr(pinfo->cinfo, COL_INFO, " - MSID:%s", pmsid); + if (dbit_show) + { + col_append_fstr(pinfo->cinfo, COL_INFO, ", TID:D+0x%04x", tid); + } + else + { + col_append_fstr(pinfo->cinfo, COL_INFO, ", TID:0x%04x", tid); + } + + return offset; +} + +/* ========================================================================= */ + + +static const gchar* +match_ver_value_string( + const guint32 val, + const ver_value_string* const strings, + const guint32 max_ver) +{ + const ver_value_string* vvs; + const ver_value_string* res = NULL; + + /* loop on the levels, from max to 0 */ + for(vvs=strings; vvs->vs.strptr; vvs++) + { + if ((vvs->vs.value == val) && (vvs->since <= max_ver)) + { + if (!res || (vvs->since > res->since)) + { + res = vvs; + } + } + } + + return res? res->vs.strptr : NULL; +} + +static int +dissect_wimaxasncp( + tvbuff_t *tvb, + packet_info *pinfo, + proto_tree *tree, + void *data _U_) +{ + static const gchar unknown[] = "Unknown"; + + /* Set up structures needed to add the protocol subtree and manage it */ + proto_item *packet_item = NULL; + proto_item *item = NULL; + proto_tree *wimaxasncp_tree = NULL; + tvbuff_t *subtree; + + guint offset; + guint8 ui8; + + guint8 function_type; + const gchar *function_type_name; + proto_item *function_type_item; + guint16 length; + + const wimaxasncp_func_msg_t *p = NULL; + const gchar *message_name; + gsize i; + + /* ------------------------------------------------------------------------ + * First, we do some heuristics to check if the packet cannot be our + * protocol. + * ------------------------------------------------------------------------ + */ + + /* Should we check a minimum size? If so, uncomment out the following + * code. */ +#if 0 + if (tvb_reported_length(tvb) < WIMAXASNCP_HEADER_SIZE) + { + return 0; + } +#endif + + /* We currently only support version 1. */ + if (tvb_bytes_exist(tvb, 0, 1) && tvb_get_guint8(tvb, 0) != 1) + { + return 0; + } + + /* ------------------------------------------------------------------------ + * Initialize the protocol and info column. + * ------------------------------------------------------------------------ + */ + + /* Make entries in Protocol column and Info column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "WiMAX"); + + /* We'll fill in the "Info" column after fetch data, so we clear the + column first in case calls to fetch data from the packet throw an + exception. */ + col_clear(pinfo->cinfo, COL_INFO); + + /* ======================================================================== + * Disesction starts here + * ======================================================================== + */ + + /* ------------------------------------------------------------------------ + * total packet, we'll adjust after we read the length field + * ------------------------------------------------------------------------ + */ + + offset = 0; + + /* Register protocol fields, etc if haven't done yet. */ + if (hf_wimaxasncp_version == -1) + { + proto_registrar_get_byname("wimaxasncp.version"); + } + + if (tree) + { + packet_item = proto_tree_add_item( + tree, proto_wimaxasncp, + tvb, 0, MIN(WIMAXASNCP_HEADER_LENGTH_END, tvb_captured_length(tvb)), ENC_NA); + + wimaxasncp_tree = proto_item_add_subtree( + packet_item, ett_wimaxasncp); + } + + /* ------------------------------------------------------------------------ + * version + * ------------------------------------------------------------------------ + */ + + if (tree) + { + proto_tree_add_item( + wimaxasncp_tree, hf_wimaxasncp_version, + tvb, offset, 1, ENC_BIG_ENDIAN); + } + + offset += 1; + + /* ------------------------------------------------------------------------ + * flags + * ------------------------------------------------------------------------ + */ + + ui8 = tvb_get_guint8(tvb, offset); + + if (tree) + { + proto_tree *flags_tree; + + if (ui8 == 0) + { + proto_tree_add_uint_format( + wimaxasncp_tree, hf_wimaxasncp_flags, + tvb, offset, 1, ui8, + "Flags: 0x%02x", ui8); + } + else + { + guint j; + item = proto_tree_add_uint_format( + wimaxasncp_tree, hf_wimaxasncp_flags, + tvb, offset, 1, ui8, + "Flags: "); + + if (ui8 & (WIMAXASNCP_FLAGS_T | WIMAXASNCP_FLAGS_R)) + { + if (ui8 & WIMAXASNCP_FLAGS_T) + { + proto_item_append_text(item, "T"); + } + + if (ui8 & WIMAXASNCP_FLAGS_R) + { + proto_item_append_text(item, "R"); + } + + proto_item_append_text(item, " - "); + } + + proto_item_append_text(item, "0x%02x", ui8); + + flags_tree = proto_item_add_subtree( + item, ett_wimaxasncp_flags); + + for (j = 0; j < 8; ++j) + { + guint8 mask; + mask = 1U << (7 - j); + + /* Only add flags that are set */ + if (ui8 & mask) + { + proto_tree_add_uint_format( + flags_tree, hf_wimaxasncp_flags, + tvb, offset, 1, ui8, + "Bit #%u is set: %s", + j, + val_to_str( + ui8 & mask, wimaxasncp_flag_vals, "Unknown")); + } + } + } + } + + offset += 1; + + /* ------------------------------------------------------------------------ + * function type + * ------------------------------------------------------------------------ + */ + + function_type = tvb_get_guint8(tvb, offset); + + function_type_name = match_ver_value_string(function_type, + wimaxasncp_function_type_vals, + global_wimaxasncp_nwg_ver); + + if (function_type_name) + { + /* add the item to the tree */ + proto_tree_add_uint_format( + wimaxasncp_tree, hf_wimaxasncp_function_type, + tvb, offset, 1, function_type, + "%s (%u)", function_type_name, function_type); + } + else + { + /* if not matched, add the item and append expert item */ + function_type_item = proto_tree_add_uint_format( + wimaxasncp_tree, hf_wimaxasncp_function_type, + tvb, offset, 1, function_type, + "Unknown (%u)", function_type); + + expert_add_info_format(pinfo, function_type_item, + &ei_wimaxasncp_function_type, + "Unknown function type (%u)", + function_type); + } + + offset += 1; + + /* ------------------------------------------------------------------------ + * OP ID and message type + * ------------------------------------------------------------------------ + */ + + ui8 = tvb_get_guint8(tvb, offset); + + + /* -------------------------------------------------------------------- + * OP ID + * -------------------------------------------------------------------- + */ + + item = proto_tree_add_uint_format( + wimaxasncp_tree, hf_wimaxasncp_op_id, + tvb, offset, 1, ui8, + "OP ID: %s", val_to_str(ui8 >> 5, wimaxasncp_op_id_vals, unknown)); + + proto_item_append_text(item, " (%u)", ((ui8 >> 5) & 7)); + + + /* use the function type to find the message vals */ + for (i = 0; i < array_length(wimaxasncp_func_to_msg_vals_map); ++i) + { + p = &wimaxasncp_func_to_msg_vals_map[i]; + + if (function_type == p->function_type) + { + break; + } + } + + /* -------------------------------------------------------------------- + * message type + * -------------------------------------------------------------------- + */ + + message_name = p ? match_ver_value_string(0x1f & ui8, p->vals, global_wimaxasncp_nwg_ver) : unknown; + if (message_name == NULL) + { + message_name = unknown; + } + + item = proto_tree_add_uint_format( + wimaxasncp_tree, hf_wimaxasncp_message_type, + tvb, offset, 1, ui8, + "Message Type: %s", message_name); + + proto_item_append_text(item, " (%u)", ui8 & 0x1F); + + /* Add expert item if not matched */ + if (strcmp(message_name, unknown) == 0) + { + expert_add_info_format(pinfo, item, &ei_wimaxasncp_message_type, + "Unknown message type (%u)", + 0x1f & ui8); + } + + col_add_str(pinfo->cinfo, COL_INFO, message_name); + + offset += 1; + + /* ------------------------------------------------------------------------ + * length + * ------------------------------------------------------------------------ + */ + + length = tvb_get_ntohs(tvb, offset); + + if (tree) + { + proto_item_set_len( + packet_item, MAX(WIMAXASNCP_HEADER_LENGTH_END, length)); + + item = proto_tree_add_uint( + wimaxasncp_tree, hf_wimaxasncp_length, + tvb, offset, 2, length); + } + + offset += 2; + + if (length < WIMAXASNCP_HEADER_SIZE) + { + expert_add_info(pinfo, item, &ei_wimaxasncp_length_bad); + + if (tree) + { + proto_item_append_text( + item, " [error: specified length less than header size (20)]"); + } + + if (length <= WIMAXASNCP_HEADER_LENGTH_END) + { + return offset; + } + } + + /* ------------------------------------------------------------------------ + * remaining header fields and TLVs + * ------------------------------------------------------------------------ + */ + + subtree = tvb_new_subset_length_caplen( + tvb, offset, + MIN(length, tvb_captured_length_remaining(tvb, offset)), + length - WIMAXASNCP_HEADER_LENGTH_END); + + offset += dissect_wimaxasncp_backend( + subtree, pinfo, wimaxasncp_tree); + + /* ------------------------------------------------------------------------ + * done, return the amount of data this dissector was able to dissect + * ------------------------------------------------------------------------ + */ + + return offset; +} + +/* ========================================================================= */ +/* Modify the given string to make a suitable display filter */ +static char *alnumerize( + char *name) +{ + char *r = name; /* read pointer */ + char *w = name; /* write pointer */ + char c; + + for ( ; (c = *r); ++r) + { + if (g_ascii_isalnum(c) || c == '_' || c == '.') + { + /* These characters are fine - copy them */ + *(w++) = c; + } + else if (c == ' ' || c == '-' || c == '/') + { + /* Skip these others if haven't written any characters out yet */ + if (w == name) + { + continue; + } + + /* Skip if we would produce multiple adjacent '_'s */ + if (*(w - 1) == '_') + { + continue; + } + + /* OK, replace with underscore */ + *(w++) = '_'; + } + + /* Other undesirable characters are just skipped */ + } + + /* Terminate and return modified string */ + *w = '\0'; + return name; +} + +/* ========================================================================= */ + +static void add_reg_info( + int *hf_ptr, + const char *name, + const char *abbrev, + enum ftenum type, + int display, + const char *blurb) +{ + hf_register_info hf = { + hf_ptr, { name, abbrev, type, display, NULL, 0x0, blurb, HFILL } }; + + wmem_array_append_one(wimaxasncp_build_dict.hf, hf); +} + +/* ========================================================================= */ + +static void add_tlv_reg_info( + wimaxasncp_dict_tlv_t *tlv) +{ + char *name; + char *abbrev; + const char *root_blurb; + char *blurb; + + /* ------------------------------------------------------------------------ + * add root reg info + * ------------------------------------------------------------------------ + */ + + name = wmem_strdup(wmem_epan_scope(), tlv->name); + abbrev = alnumerize(wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s", tlv->name)); + + switch (tlv->decoder) + { + case WIMAXASNCP_TLV_UNKNOWN: + root_blurb = "type=Unknown"; + break; + case WIMAXASNCP_TLV_TBD: + root_blurb = wmem_strdup_printf(wmem_epan_scope(), "type=%u, TBD", tlv->type); + break; + case WIMAXASNCP_TLV_COMPOUND: + root_blurb = wmem_strdup_printf(wmem_epan_scope(), "type=%u, Compound", tlv->type); + break; + case WIMAXASNCP_TLV_FLAG0: + root_blurb = wmem_strdup_printf(wmem_epan_scope(), "type=%u, Value = Null", tlv->type); + break; + default: + root_blurb = wmem_strdup_printf(wmem_epan_scope(), "type=%u", tlv->type); + break; + } + + add_reg_info( + &tlv->hf_root, name, abbrev, FT_BYTES, BASE_NONE, root_blurb); + + /* ------------------------------------------------------------------------ + * add value(s) reg info + * ------------------------------------------------------------------------ + */ + + name = wmem_strdup(wmem_epan_scope(), "Value"); + abbrev = alnumerize(wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value", tlv->name)); + blurb = wmem_strdup_printf(wmem_epan_scope(), "value for type=%u", tlv->type); + + switch (tlv->decoder) + { + case WIMAXASNCP_TLV_UNKNOWN: + wmem_free(wmem_epan_scope(), blurb); + + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, + "value for unknown type"); + break; + + case WIMAXASNCP_TLV_TBD: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb); + break; + + case WIMAXASNCP_TLV_COMPOUND: + case WIMAXASNCP_TLV_FLAG0: + wmem_free(wmem_epan_scope(), name); + wmem_free(wmem_epan_scope(), abbrev); + wmem_free(wmem_epan_scope(), blurb); + break; + + case WIMAXASNCP_TLV_BYTES: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb); + break; + + case WIMAXASNCP_TLV_ENUM8: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT8, BASE_DEC, blurb); + break; + + case WIMAXASNCP_TLV_ENUM16: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT16, BASE_DEC, blurb); + break; + + case WIMAXASNCP_TLV_ENUM32: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT32, BASE_DEC, blurb); + break; + + case WIMAXASNCP_TLV_ETHER: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_ETHER, BASE_NONE, blurb); + break; + + case WIMAXASNCP_TLV_ASCII_STRING: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_STRING, BASE_NONE, blurb); + break; + + case WIMAXASNCP_TLV_BITFLAGS8: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT8, BASE_HEX, blurb); + break; + + case WIMAXASNCP_TLV_BITFLAGS16: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT16, BASE_HEX, blurb); + break; + + case WIMAXASNCP_TLV_BITFLAGS32: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT32, BASE_HEX, blurb); + break; + + case WIMAXASNCP_TLV_ID: + wmem_free(wmem_epan_scope(), abbrev); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.ipv4_value", tlv->name)); + + add_reg_info( + &tlv->hf_ipv4, "IPv4 Address", abbrev, FT_IPv4, BASE_NONE, blurb); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.ipv6_value", tlv->name)); + + add_reg_info( + &tlv->hf_ipv6, "IPv6 Address", abbrev, FT_IPv6, BASE_NONE, blurb); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.bsid_value", tlv->name)); + + add_reg_info( + &tlv->hf_bsid, "BS ID", abbrev, FT_ETHER, BASE_NONE, blurb); + + break; + + case WIMAXASNCP_TLV_HEX8: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT8, BASE_HEX, blurb); + break; + + case WIMAXASNCP_TLV_HEX16: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT16, BASE_HEX, blurb); + break; + + case WIMAXASNCP_TLV_HEX32: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT32, BASE_HEX, blurb); + break; + + case WIMAXASNCP_TLV_DEC8: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT8, BASE_DEC, blurb); + break; + + case WIMAXASNCP_TLV_DEC16: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT16, BASE_DEC, blurb); + break; + + case WIMAXASNCP_TLV_DEC32: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_UINT32, BASE_DEC, blurb); + break; + + case WIMAXASNCP_TLV_IP_ADDRESS: + wmem_free(wmem_epan_scope(), abbrev); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.ipv4_value", tlv->name)); + + add_reg_info( + &tlv->hf_ipv4, "IPv4 Address", abbrev, FT_IPv4, BASE_NONE, blurb); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.ipv6_value", tlv->name)); + + add_reg_info( + &tlv->hf_ipv6, "IPv6 Address", abbrev, FT_IPv6, BASE_NONE, blurb); + + break; + + case WIMAXASNCP_TLV_IPV4_ADDRESS: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_IPv4, BASE_NONE, blurb); + break; + + case WIMAXASNCP_TLV_PROTOCOL_LIST: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb); + + blurb = wmem_strdup_printf(wmem_epan_scope(), "value component for type=%u", tlv->type); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value.protocol", tlv->name)); + + add_reg_info( + &tlv->hf_protocol, "Protocol", abbrev, FT_UINT16, BASE_DEC, blurb); + + break; + + case WIMAXASNCP_TLV_PORT_RANGE_LIST: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb); + + blurb = wmem_strdup_printf(wmem_epan_scope(), "value component for type=%u", tlv->type); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value.port_low", tlv->name)); + + add_reg_info( + &tlv->hf_port_low, "Port Low", abbrev, FT_UINT16, BASE_DEC, blurb); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value.port_high", tlv->name)); + + add_reg_info( + &tlv->hf_port_high, "Port High", abbrev, FT_UINT16, BASE_DEC, blurb); + + break; + + case WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb); + + blurb = wmem_strdup_printf(wmem_epan_scope(), "value component for type=%u", tlv->type); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value.ipv4", tlv->name)); + + add_reg_info( + &tlv->hf_ipv4, "IPv4 Address", abbrev, FT_IPv4, BASE_NONE, blurb); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value.ipv4_mask", tlv->name)); + + add_reg_info( + &tlv->hf_ipv4_mask, "IPv4 Mask", abbrev, FT_IPv4, BASE_NONE, blurb); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value.ipv6", tlv->name)); + + add_reg_info( + &tlv->hf_ipv6, "IPv6 Address", abbrev, FT_IPv6, BASE_NONE, blurb); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value.ipv6_mask", tlv->name)); + + add_reg_info( + &tlv->hf_ipv6_mask, "IPv6 Mask", abbrev, FT_IPv6, BASE_NONE, blurb); + + break; + + case WIMAXASNCP_TLV_VENDOR_SPECIFIC: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb); + + blurb = wmem_strdup_printf(wmem_epan_scope(), "value component for type=%u", tlv->type); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), "wimaxasncp.tlv.%s.value.vendor_id", tlv->name)); + + add_reg_info( + &tlv->hf_vendor_id, "Vendor ID", abbrev, FT_UINT24, BASE_DEC, blurb); + + abbrev = alnumerize( + wmem_strdup_printf(wmem_epan_scope(), + "wimaxasncp.tlv.%s.value.vendor_rest_of_info", tlv->name)); + + add_reg_info( + &tlv->hf_vendor_rest_of_info, "Rest of Info", abbrev, FT_BYTES, BASE_NONE, + blurb); + + break; + + case WIMAXASNCP_TLV_EAP: + blurb = wmem_strdup_printf(wmem_epan_scope(), "EAP payload embedded in %s", name); + + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb); + break; + + + default: + add_reg_info( + &tlv->hf_value, name, abbrev, FT_BYTES, BASE_NONE, blurb); + + if (debug_enabled) + { + g_print( + "fix-me: unknown decoder: %d\n", tlv->decoder); + } + + break; + } +} + +/* ========================================================================= */ +/* Register the protocol fields and subtrees with Wireshark */ +static void +register_wimaxasncp_fields(const char* unused _U_) +{ + gboolean debug_parser; + gboolean dump_dict; + gchar *dir; + gchar* dict_error; + + /* ------------------------------------------------------------------------ + * List of header fields + * ------------------------------------------------------------------------ + */ + + static hf_register_info hf_base[] = { + { + &hf_wimaxasncp_version, /* ID */ + { + "Version", /* FIELDNAME */ + "wimaxasncp.version", /* PROTOABBREV.FIELDABBRE */ + FT_UINT8, /* FIELDTYPE */ + BASE_DEC, /* FIELDBASE */ + NULL, /* FIELDCONVERT */ + 0x0, /* BITMASK */ + NULL, /* FIELDDESCR */ + HFILL /* HFILL */ + } + }, + { + &hf_wimaxasncp_flags, + { + "Flags", + "wimaxasncp.flags", + FT_UINT8, + BASE_HEX, + NULL, + 0xff, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_function_type, + { + "Function Type", + "wimaxasncp.function_type", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_op_id, + { + "OP ID", + "wimaxasncp.opid", + FT_UINT8, + BASE_HEX, + VALS(wimaxasncp_op_id_vals), + 0xE0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_message_type, + { + "Message Type", + "wimaxasncp.message_type", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#if 0 + { + &hf_wimaxasncp_qos_msg, + { + "Message Type", + "wimaxasncp.qos_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_ho_control_msg, + { + "Message Type", + "wimaxasncp.ho_control_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_data_path_control_msg, + { + "Message Type", + "wimaxasncp.data_path_control_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_context_delivery_msg, + { + "Message Type", + "wimaxasncp.context_delivery_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_r3_mobility_msg, + { + "Message Type", + "wimaxasncp.r3_mobility_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_paging_msg, + { + "Message Type", + "wimaxasncp.paging_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_rrm_msg, + { + "Message Type", + "wimaxasncp.rrm_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_authentication_msg, + { + "Message Type", + "wimaxasncp.authentication_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_ms_state_msg, + { + "Message Type", + "wimaxasncp.ms_state_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_reauthentication_msg, + { + "Message Type", + "wimaxasncp.reauthentication_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_session_msg, + { + "Message Type", + "wimaxasncp.session_msg", + FT_UINT8, + BASE_HEX, + NULL, + 0x1F, + NULL, + HFILL + } + }, +#endif + { + &hf_wimaxasncp_length, + { + "Length", + "wimaxasncp.length", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_msid, + { + "MSID", + "wimaxasncp.msid", + FT_ETHER, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_reserved1, + { + "Reserved", + "wimaxasncp.reserved1", + FT_UINT32, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_transaction_id, + { + "Transaction ID", + "wimaxasncp.transaction_id", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_reserved2, + { + "Reserved", + "wimaxasncp.reserved2", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, +#if 0 + { + &hf_wimaxasncp_tlv, + { + "TLV", + "wimaxasncp.tlv", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, +#endif + { + &hf_wimaxasncp_tlv_type, + { + "Type", + "wimaxasncp.tlv.type", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_tlv_length, + { + "Length", + "wimaxasncp.tlv.length", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_tlv_value_bytes, + { + "Value", + "wimaxasncp.tlv_value_bytes", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_tlv_value_bitflags8, + { + "Value", + "wimaxasncp.tlv_value_bitflags8", + FT_UINT8, + BASE_HEX, + NULL, + 0xff, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_tlv_value_bitflags16, + { + "Value", + "wimaxasncp.tlv_value_bitflags16", + FT_UINT16, + BASE_HEX, + NULL, + 0xffff, + NULL, + HFILL + } + }, + { + &hf_wimaxasncp_tlv_value_bitflags32, + { + "Value", + "wimaxasncp.tlv_value_bitflags32", + FT_UINT32, + BASE_HEX, + NULL, + 0xffffffff, + NULL, + HFILL + } + }, +#if 0 + { + &hf_wimaxasncp_tlv_value_protocol, + { + "Value", + "wimaxasncp.tlv_value_protocol", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, +#endif +#if 0 + { + &hf_wimaxasncp_tlv_value_vendor_id, + { + "Vendor ID", + "wimaxasncp.tlv_value_vendor_id", + FT_UINT24, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + } +#endif + }; + + /* ------------------------------------------------------------------------ + * Protocol subtree array + * ------------------------------------------------------------------------ + */ + + static gint *ett_base[] = { + &ett_wimaxasncp, + &ett_wimaxasncp_flags, + &ett_wimaxasncp_tlv, + &ett_wimaxasncp_tlv_value_bitflags8, + &ett_wimaxasncp_tlv_value_bitflags16, + &ett_wimaxasncp_tlv_value_bitflags32, + &ett_wimaxasncp_tlv_protocol_list, + &ett_wimaxasncp_tlv_port_range_list, + &ett_wimaxasncp_tlv_ip_address_mask_list, + &ett_wimaxasncp_tlv_ip_address_mask, + &ett_wimaxasncp_tlv_eap, + &ett_wimaxasncp_tlv_vendor_specific_information_field, + &ett_wimaxasncp_port_range + }; + + static ei_register_info ei[] = { + { &ei_wimaxasncp_tlv_type, { "wimaxasncp.tlv.type.unknown", PI_UNDECODED, PI_WARN, "Unknown tlv", EXPFILL }}, + { &ei_wimaxasncp_function_type, { "wimaxasncp.function_type.unknown", PI_UNDECODED, PI_WARN, "Unknown function type", EXPFILL }}, + { &ei_wimaxasncp_op_id, { "wimaxasncp.opid.unknown", PI_UNDECODED, PI_WARN, "Unknown message op", EXPFILL }}, + { &ei_wimaxasncp_message_type, { "wimaxasncp.message_type.unknown", PI_UNDECODED, PI_WARN, "Unknown message type", EXPFILL }}, + { &ei_wimaxasncp_length_bad, { "wimaxasncp.length.bad", PI_MALFORMED, PI_ERROR, "Bad length", EXPFILL }}, + }; + + expert_module_t* expert_wimaxasncp; + + /* ------------------------------------------------------------------------ + * load the XML dictionary + * ------------------------------------------------------------------------ + */ + + debug_parser = getenv("WIRESHARK_DEBUG_WIMAXASNCP_DICT_PARSER") != NULL; + dump_dict = getenv("WIRESHARK_DUMP_WIMAXASNCP_DICT") != NULL; + + dir = ws_strdup_printf( + "%s" G_DIR_SEPARATOR_S "wimaxasncp", + get_datafile_dir()); + + wimaxasncp_dict = + wimaxasncp_dict_scan(dir, "dictionary.xml", debug_parser, &dict_error); + + g_free(dir); + + if (dict_error) + { + report_failure("wimaxasncp - %s", dict_error); + g_free(dict_error); + } + + if (wimaxasncp_dict && dump_dict) + { + wimaxasncp_dict_print(stdout, wimaxasncp_dict); + } + + /* ------------------------------------------------------------------------ + * build the hf and ett dictionary entries + * ------------------------------------------------------------------------ + */ + + wimaxasncp_build_dict.hf = + wmem_array_new(wmem_epan_scope(), sizeof(hf_register_info)); + + wmem_array_append( + wimaxasncp_build_dict.hf, hf_base, array_length(hf_base)); + + wimaxasncp_build_dict.ett = + wmem_array_new(wmem_epan_scope(), sizeof(gint*)); + + wmem_array_append( + wimaxasncp_build_dict.ett, ett_base, array_length(ett_base)); + + if (wimaxasncp_dict) + { + wimaxasncp_dict_tlv_t *tlv; + + /* For each TLV found in XML file */ + for (tlv = wimaxasncp_dict->tlvs; tlv; tlv = tlv->next) + { + if (tlv->enums) + { + /* Create array for enums */ + wimaxasncp_dict_enum_t *e; + wmem_array_t* array = wmem_array_new(wmem_epan_scope(), sizeof(value_string)); + + /* Copy each entry into value_string array */ + for (e = tlv->enums; e; e = e->next) + { + value_string item = { e->code, e->name }; + wmem_array_append_one(array, item); + } + + /* Set enums to use with this TLV */ + wmem_array_set_null_terminator(array); + tlv->enum_vs = (value_string*)wmem_array_get_raw(array); + } + + add_tlv_reg_info(tlv); + } + } + + /* add an entry for unknown TLVs */ + add_tlv_reg_info(&wimaxasncp_tlv_not_found); + + /* The following debug will only be printed if the debug_enabled variable + * is set programmatically. Setting the value via preferences will not + * work as it will be set too late to affect this code path. + */ + if (debug_enabled) + { + if (wimaxasncp_dict) + { + wimaxasncp_dict_tlv_t *tlv; + + for (tlv = wimaxasncp_dict->tlvs; tlv; tlv = tlv->next) + { + ws_debug_printf( + "%s\n" + " type = %u\n" + " description = %s\n" + " decoder = %s\n" + " hf_root = %d\n" + " hf_value = %d\n" + " hf_ipv4 = %d\n" + " hf_ipv6 = %d\n" + " hf_bsid = %d\n" + " hf_protocol = %d\n" + " hf_port_low = %d\n" + " hf_port_high = %d\n" + " hf_ipv4_mask = %d\n" + " hf_ipv6_mask = %d\n" + " hf_vendor_id = %d\n" + " hf_vendor_rest_of_info = %d\n", + tlv->name, + tlv->type, + tlv->description, + val_to_str( + tlv->decoder, wimaxasncp_decode_type_vals, "Unknown"), + tlv->hf_root, + tlv->hf_value, + tlv->hf_ipv4, + tlv->hf_ipv6, + tlv->hf_bsid, + tlv->hf_protocol, + tlv->hf_port_low, + tlv->hf_port_high, + tlv->hf_ipv4_mask, + tlv->hf_ipv6_mask, + tlv->hf_vendor_id, + tlv->hf_vendor_rest_of_info); + } + } + } + + /* Required function calls to register the header fields and subtrees + * used */ + proto_register_field_array( + proto_wimaxasncp, + (hf_register_info*)wmem_array_get_raw(wimaxasncp_build_dict.hf), + wmem_array_get_count(wimaxasncp_build_dict.hf)); + + proto_register_subtree_array( + (gint**)wmem_array_get_raw(wimaxasncp_build_dict.ett), + wmem_array_get_count(wimaxasncp_build_dict.ett)); + + expert_wimaxasncp = expert_register_protocol(proto_wimaxasncp); + expert_register_field_array(expert_wimaxasncp, ei, array_length(ei)); + +} + + + + +/* ========================================================================= */ +/* Register the protocol with Wireshark */ + +/* this format is require because a script is used to build the C function + that calls all the protocol registration. +*/ + +void +proto_register_wimaxasncp(void) +{ + module_t *wimaxasncp_module; + + /* ------------------------------------------------------------------------ + * complete registration + * ------------------------------------------------------------------------ + */ + + /* Register the protocol name and description */ + proto_wimaxasncp = proto_register_protocol("WiMAX ASN Control Plane Protocol", "WiMAX ASN CP", "wimaxasncp"); + + /* Register this dissector by name */ + wimaxasncp_handle = register_dissector("wimaxasncp", dissect_wimaxasncp, proto_wimaxasncp); + + wimaxasncp_module = prefs_register_protocol(proto_wimaxasncp, NULL); + + /* Register preferences */ + prefs_register_bool_preference( + wimaxasncp_module, + "show_transaction_id_d_bit", + "Show transaction ID direction bit", + "Show transaction ID direction bit separately from the rest of " + "the transaction ID field.", + &show_transaction_id_d_bit); + + prefs_register_bool_preference( + wimaxasncp_module, + "debug_enabled", + "Enable debug output", + "Print debug output to the console.", + &debug_enabled); + + prefs_register_enum_preference( + wimaxasncp_module, + "nwg_version", + "NWG Version", + "Version of the NWG that the R6 protocol complies with", + &global_wimaxasncp_nwg_ver, + wimaxasncp_nwg_versions, + FALSE); + + proto_register_prefix("wimaxasncp", register_wimaxasncp_fields); +} + +/* ========================================================================= */ +/* If this dissector uses sub-dissector registration add a registration + routine. This exact format is required because a script is used to find + these routines and create the code that calls these routines. + + This function is also called by preferences whenever "Apply" is pressed + (see prefs_register_protocol above) so it should accommodate being called + more than once. +*/ +void +proto_reg_handoff_wimaxasncp(void) +{ + /* Find the EAP dissector */ + eap_handle = find_dissector_add_dependency("eap", proto_wimaxasncp); + + dissector_add_uint_with_preference("udp.port", WIMAXASNCP_DEF_UDP_PORT, wimaxasncp_handle); +} + + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/wimaxasncp/wimaxasncp_dict.h b/plugins/epan/wimaxasncp/wimaxasncp_dict.h new file mode 100644 index 00000000..6f136522 --- /dev/null +++ b/plugins/epan/wimaxasncp/wimaxasncp_dict.h @@ -0,0 +1,114 @@ +/* + ** wimaxasncp_dict.h + ** WIMAXASNCP Dictionary Import Routines + ** + ** (c) 2007, Stephen Croll + ** + ** SPDX-License-Identifier: LGPL-2.0-or-later + */ + +#ifndef _WIMAXASNCP_DICT_H_ +#define _WIMAXASNCP_DICT_H_ + +/* ------------------------------------------------------------------------- + * NWG versions + * ------------------------------------------------------------------------- */ + +#define WIMAXASNCP_NWGVER_R10_V100 0 +#define WIMAXASNCP_NWGVER_R10_V120 1 +#define WIMAXASNCP_NWGVER_R10_V121 2 +#define WIMAXASNCP_NWGVER_NUM 3 + +/* ------------------------------------------------------------------------- + * decode types + * ------------------------------------------------------------------------- */ + +enum +{ + WIMAXASNCP_TLV_UNKNOWN, + WIMAXASNCP_TLV_TBD, + WIMAXASNCP_TLV_COMPOUND, + WIMAXASNCP_TLV_BYTES, + WIMAXASNCP_TLV_ENUM8, + WIMAXASNCP_TLV_ENUM16, + WIMAXASNCP_TLV_ENUM32, + WIMAXASNCP_TLV_ETHER, + WIMAXASNCP_TLV_ASCII_STRING, + WIMAXASNCP_TLV_FLAG0, + WIMAXASNCP_TLV_BITFLAGS8, + WIMAXASNCP_TLV_BITFLAGS16, + WIMAXASNCP_TLV_BITFLAGS32, + WIMAXASNCP_TLV_ID, + WIMAXASNCP_TLV_HEX8, + WIMAXASNCP_TLV_HEX16, + WIMAXASNCP_TLV_HEX32, + WIMAXASNCP_TLV_DEC8, + WIMAXASNCP_TLV_DEC16, + WIMAXASNCP_TLV_DEC32, + WIMAXASNCP_TLV_IP_ADDRESS, /* Note: IPv4 or IPv6, determined by length */ + WIMAXASNCP_TLV_IPV4_ADDRESS, + WIMAXASNCP_TLV_PROTOCOL_LIST, + WIMAXASNCP_TLV_PORT_RANGE_LIST, + WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST, + WIMAXASNCP_TLV_EAP, + WIMAXASNCP_TLV_VENDOR_SPECIFIC +}; + +/* ------------------------------------------------------------------------- + * structures and functions + * ------------------------------------------------------------------------- */ + +struct _wimaxasncp_dict_namecode_t { + gchar *name; + guint code; + struct _wimaxasncp_dict_namecode_t *next; +}; + +typedef struct _wimaxasncp_dict_namecode_t wimaxasncp_dict_enum_t; + +typedef struct _wimaxasncp_dict_tlv_t { + guint16 type; + gchar *name; + gchar *description; + gint decoder; + guint since; + int hf_root; + int hf_value; + int hf_ipv4; + int hf_ipv6; + int hf_bsid; + int hf_protocol; + int hf_port_low; + int hf_port_high; + int hf_ipv4_mask; + int hf_ipv6_mask; + int hf_vendor_id; + int hf_vendor_rest_of_info; + value_string *enum_vs; + wimaxasncp_dict_enum_t *enums; + struct _wimaxasncp_dict_tlv_t *next; +} wimaxasncp_dict_tlv_t; + +typedef struct _wimaxasncp_dict_xmlpi_t { + gchar *name; + gchar *key; + gchar *value; + struct _wimaxasncp_dict_xmlpi_t *next; +} wimaxasncp_dict_xmlpi_t; + +typedef struct _wimaxasncp_dict_t { + wimaxasncp_dict_tlv_t *tlvs; + wimaxasncp_dict_xmlpi_t *xmlpis; +} wimaxasncp_dict_t; + +extern void wimaxasncp_dict_print( + FILE *fh, wimaxasncp_dict_t *d); + +extern wimaxasncp_dict_t *wimaxasncp_dict_scan( + const gchar *system_directory, const gchar *filename, int dbg, + gchar **error); + +extern void wimaxasncp_dict_free( + wimaxasncp_dict_t *d); + +#endif diff --git a/plugins/epan/wimaxasncp/wimaxasncp_dict.l b/plugins/epan/wimaxasncp/wimaxasncp_dict.l new file mode 100644 index 00000000..05fa2e51 --- /dev/null +++ b/plugins/epan/wimaxasncp/wimaxasncp_dict.l @@ -0,0 +1,867 @@ +%top { +/* Include this before everything else, for various large-file definitions */ +#include "config.h" +#include +} + +/* + * We want a reentrant scanner. + */ +%option reentrant + +/* + * We don't use input, so don't generate code for it. + */ +%option noinput + +/* + * We don't use unput, so don't generate code for it. + */ +%option nounput + +/* + * We don't read interactively from the terminal. + */ +%option never-interactive + +/* + * We want to stop processing when we get to the end of the input. + */ +%option noyywrap + +/* + * The type for the state we keep for a scanner. + */ +%option extra-type="WimaxasncpDict_scanner_state_t *" + +/* + * We have to override the memory allocators so that we don't get + * "unused argument" warnings from the yyscanner argument (which + * we don't use, as we have a global memory allocator). + * + * We provide, as macros, our own versions of the routines generated by Flex, + * which just call malloc()/realloc()/free() (as the Flex versions do), + * discarding the extra argument. + */ +%option noyyalloc +%option noyyrealloc +%option noyyfree + +/* + * The language we're scanning is case-insensitive. + */ +%option caseless + +/* + * We use start condition stacks. + */ +%option stack + +/* + * Prefix scanner routines with "WimaxasncpDict_" rather than "yy", so this + * scanner can coexist with other scanners. + */ +%option prefix="WimaxasncpDict_" + +%option outfile="wimaxasncp_dict.c" + +%{ + /* + ** wimaxasncp_dict.h + ** WIMAXASNCP Dictionary Import Routines + ** + ** (c) 2007, Luis E. Garcia Ontanon + ** (c) 2007, Stephen Croll + ** + ** This library is free software; you can redistribute it and/or + ** modify it under the terms of the GNU Library General Public + ** License as published by the Free Software Foundation; either + ** version 2 of the License, or (at your option) any later version. + ** + ** This library 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 + ** Library General Public License for more details. + ** + ** You should have received a copy of the GNU Library General Public + ** License along with this library; if not, write to the Free Software + ** Foundation, Inc., 51 Franklin Street, Fifth Floor, + ** Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* array_length */ +#include + +#include "wimaxasncp_dict.h" + +/* + * Disable diagnostics in the code generated by Flex. + */ +DIAG_OFF_FLEX() + +typedef struct entity_t { + gchar *name; + gchar *file; + struct entity_t *next; +} entity_t; + +#define ATTR_UINT(cont) do { D(("attr_uint " #cont "\t" )); yyextra->attr_uint = &(cont); yy_push_state(GET_UINT_ATTR, yyscanner); } while(0) +#define ATTR_UINT16(cont) do { D(("attr_uint16 " #cont "\t" )); yyextra->attr_uint16 = &(cont); yy_push_state(GET_UINT16_ATTR, yyscanner); } while(0) +#define ATTR_STR(cont) do { D(("attr_str " #cont "\t" )); yyextra->attr_str = &(cont); yy_push_state(GET_ATTR, yyscanner); } while(0) +#define ATTR_DECODER(cont) do { D(("attr_decoder " #cont "\t" )); yyextra->attr_uint = &(cont); yy_push_state(GET_DECODER_ATTR, yyscanner); } while(0) +#define WIMAXASNCP_IGNORE() do { D(("ignore: %s\t",yytext)); yy_push_state(IGNORE_ATTR, yyscanner); } while(0) + +#define D(args) wimaxasncp_dict_debug args + +#define MAX_INCLUDE_DEPTH 10 +#define YY_INPUT(buf,result,max_size) { result = yyextra->current_yyinput(buf,max_size,yyscanner); } +#define YY_USER_INIT { \ + WimaxasncpDict_scanner_state_t *scanner_state = WimaxasncpDict_get_extra(yyscanner); \ + BEGIN(scanner_state->start_state); \ +} +#define ECHO +#define APPEND(txt,len) append_to_buffer(txt,(int)len,yyextra) + +typedef struct { + GString *dict_error; + + const gchar *sys_dir; + + gchar *strbuf; + guint size_strbuf; + guint len_strbuf; + + gchar *write_ptr; + gchar *read_ptr; + + wimaxasncp_dict_t *dict; + wimaxasncp_dict_tlv_t *tlv; + wimaxasncp_dict_enum_t *enumitem; + wimaxasncp_dict_xmlpi_t *xmlpi; + + wimaxasncp_dict_tlv_t *last_tlv; + wimaxasncp_dict_enum_t *last_enumitem; + wimaxasncp_dict_xmlpi_t *last_xmlpi; + + entity_t *ents; + + YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH]; + int include_stack_ptr; + size_t (*current_yyinput)(gchar*,size_t,yyscan_t); + + gchar **attr_str; + guint *attr_uint; + gint16 *attr_uint16; + + int start_state; +} WimaxasncpDict_scanner_state_t; + +static guint wimaxasncp_bits(guint bits, char *n); +static gint wimaxasncp_decode_type(const gchar *name); +static void wimaxasncp_dict_debug(const gchar *fmt, ...) G_GNUC_PRINTF(1, 2); +static void append_to_buffer(const gchar *txt, int len, WimaxasncpDict_scanner_state_t *state); +static FILE *wimaxasncp_dict_open(const gchar*, const gchar*); + +/* + * Sleazy hack to suppress compiler warnings in yy_fatal_error(). + */ +#define YY_EXIT_FAILURE ((void)yyscanner, 2) + +/* + * Macros for the allocators, to discard the extra argument. + */ +#define WimaxasncpDict_alloc(size, yyscanner) (void *)malloc(size) +#define WimaxasncpDict_realloc(ptr, size, yyscanner) (void *)realloc((char *)(ptr), (size)) +#define WimaxasncpDict_free(ptr, yyscanner) free((char *)ptr) + +%} + + +xmlpi_start [[:blank:] \r\n]*<\?[[:blank:] \r\n]* +xmlpi_end [[:blank:] \r\n]*\?>[[:blank:] \r\n]* +xmlpi_key_attr [[:blank:] \r\n]*key[[:blank:] \r\n]*=[[:blank:] \r\n]*\042 +xmlpi_value_attr [[:blank:] \r\n]*value[[:blank:] \r\n]*=[[:blank:] \r\n]*\042 + +comment_start [[:blank:] \r\n]*[[:blank:] \r\n]* +open_tag [[:blank:] \r\n]*<[[:blank:] \r\n]* +end_tag [[:blank:] \r\n]*\/>[[:blank:] \r\n]* +close_tag [[:blank:] \r\n]*>[[:blank:] \r\n]* +open_closetag [[:blank:] \r\n]*<\/[[:blank:] \r\n]* +equals [[:blank:] \r\n]*=[[:blank:] \r\n]* +whitespace [[:blank:] \r\n]* +dquoted \042[^\042]*\042 + +doctype [[:blank:] \r\n]*[[:blank:] \r\n]* + +start_entity [[:blank:] \r\n]*<\!ENTITY[[:blank:] \r\n]* +system [[:blank:] \r\n]*SYSTEM[[:blank:] \r\n]*\042 +entityname [a-z0-9-]+ +ndquot [^\042]+ +end_entity \042[[:blank:] \r\n]*>[[:blank:] \r\n]* + +entity \&[a-z0-9-]+; + +any . + + + + +stop > +stop_end \/> +dquot \042 +number [-]?[0-9]*|(0x)?[0-9a-fA-F]* + +dictionary_start +dictionary_end <\/dictionary> + +tlv_start + +type_start {doctype} ; +{doctype_end} ; + +{comment_start} BEGIN LOADING_COMMENT; +. ; +{comment_end} BEGIN LOADING; + +{xmlpi_start} BEGIN LOADING_XMLPI; +{whitespace} ; +{entityname} { + yyextra->xmlpi = g_new(wimaxasncp_dict_xmlpi_t,1); + yyextra->xmlpi->name = g_strdup(yytext); + yyextra->xmlpi->key = NULL; + yyextra->xmlpi->value = NULL; + yyextra->xmlpi->next = NULL; + + if (!yyextra->dict->xmlpis) yyextra->last_xmlpi = yyextra->dict->xmlpis = yyextra->xmlpi; + else yyextra->last_xmlpi = yyextra->last_xmlpi->next = yyextra->xmlpi; + + BEGIN XMLPI_ATTRS; +} + +{xmlpi_key_attr} BEGIN XMLPI_GETKEY; +{ndquot} { yyextra->xmlpi->key = g_strdup(yytext); BEGIN XMLPI_ATTRS; } + +{xmlpi_value_attr} BEGIN XMLPI_GETVAL; +{ndquot} { yyextra->xmlpi->value = g_strdup(yytext); BEGIN XMLPI_ATTRS; } + +. +{xmlpi_end} BEGIN LOADING; + + +{start_entity} BEGIN ENTITY; +{entityname} { + entity_t *e = g_new(entity_t,1); + D(("ENTITY: %s\n",yytext)); + e->name = g_strdup(yytext); + e->next = yyextra->ents; + yyextra->ents = e; + BEGIN GET_SYSTEM; +}; +{system} BEGIN GET_FILE; +{ndquot} { + D(("GET_FILE: %s\n",yytext)); + yyextra->ents->file = g_strdup(yytext); + BEGIN END_ENTITY; +} +{end_entity} BEGIN LOADING; + +{open_tag} APPEND("<",1); + +{close_tag} APPEND(">",1); + +{end_tag} APPEND("/>",2); + +{open_closetag} APPEND("{whitespace} APPEND(" ",1); + +{dquoted} APPEND(yytext,yyleng); + +{equals} APPEND("=",1); + +{any} APPEND(yytext,yyleng); + +{entity} { + gchar *p = ++yytext, *temp_str; + entity_t* e; + + while(*p != ';') p++; + + *p = '\0'; + + D(("looking for entity: %s\n",yytext)); + + if ( yyextra->include_stack_ptr >= MAX_INCLUDE_DEPTH ) { + yyextra->dict_error = g_string_append( + yyextra->dict_error, "included files nested too deeply\n"); + yyterminate(); + } + + yyextra->include_stack[yyextra->include_stack_ptr++] = YY_CURRENT_BUFFER; + + + for (e = yyextra->ents; e; e = e->next) { + if (strcmp(e->name,yytext) == 0) { + yyin = wimaxasncp_dict_open(yyextra->sys_dir,e->file); + D(("entity: %s filename: %s yyin: %p\n",e->name,e->file,(void*)yyin)); + if (!yyin) { + yyterminate(); + } else { + WimaxasncpDict__switch_to_buffer(WimaxasncpDict__create_buffer(yyin, YY_BUF_SIZE, yyscanner), yyscanner); + } + break; + } + } + + if (!e) { + temp_str = ws_strdup_printf( + "cannot find entity: '%s'\n", yytext); + yyextra->dict_error = g_string_append(yyextra->dict_error, temp_str); + g_free(temp_str); + yyterminate(); + } + +} + +<> { + if (!yyin) yyterminate(); + + fclose(yyin); + D(("closing: %p %i\n",(void*)yyin,yyextra->include_stack_ptr)); + + if ( --yyextra->include_stack_ptr < 0 ) { + D(("DONE READING\n")); + yyin = NULL; + yyterminate(); + } else { + WimaxasncpDict__delete_buffer(YY_CURRENT_BUFFER, yyscanner); + WimaxasncpDict__switch_to_buffer(yyextra->include_stack[yyextra->include_stack_ptr], yyscanner); + BEGIN LOADING; + } +} + + +{ndquot} { + *yyextra->attr_str = wmem_strdup(wmem_epan_scope(), yytext); + D(("%s\n",yytext)); + yyextra->attr_str = NULL; + BEGIN END_ATTR; +} + +{number} { + *yyextra->attr_uint = (guint)strtoul(yytext,NULL,0); + D(("%s\n",yytext);); + yyextra->attr_uint = NULL; + BEGIN END_ATTR; +} + +{number} { + *yyextra->attr_uint16 = (gint16) strtol(yytext,NULL,0); + D(("%s\n",yytext);); + yyextra->attr_uint16 = NULL; + BEGIN END_ATTR; +} + +"WIMAXASNCP_BIT32"[ \t]*"(" { BEGIN BIT32; } + +[0-9]+ { + *yyextra->attr_uint = wimaxasncp_bits(32, yytext); + D(("WIMAXASNCP_BIT32(%s)\n",yytext);); + yyextra->attr_uint = NULL; +} + +"WIMAXASNCP_BIT16"[ \t]*"(" { BEGIN BIT16; } + +[0-9]+ { + *yyextra->attr_uint = wimaxasncp_bits(16, yytext); + D(("WIMAXASNCP_BIT16(%s)\n",yytext);); + yyextra->attr_uint = NULL; +} + +"WIMAXASNCP_BIT8"[ \t]*"(" { BEGIN BIT8; } + +[0-9]+ { + *yyextra->attr_uint = wimaxasncp_bits(8, yytext); + D(("WIMAXASNCP_BIT8(%s)\n",yytext);); + yyextra->attr_uint = NULL; +} + +[ \t]*")" { BEGIN END_ATTR; } + +{ndquot} { + *yyextra->attr_uint = wimaxasncp_decode_type(yytext); + D(("%s\n",yytext)); + yyextra->attr_uint = NULL; + BEGIN END_ATTR; +} + +{dquot} { yy_pop_state(yyscanner); } + +. { + /* XXX: should go?*/ + D(("{%s}",yytext)); +} + +{ignored_quoted} { + D(("=>%s<=\n",yytext)); + yy_pop_state(yyscanner); +} + +{dictionary_start} { + D(("dictionary_start\n")); + + BEGIN IN_DICT; +} + +{tlv_start} { + D(("tlv_start\n")); + + yyextra->tlv = wmem_new0(wmem_epan_scope(), wimaxasncp_dict_tlv_t); + yyextra->tlv->hf_root = -1; + yyextra->tlv->hf_value = -1; + yyextra->tlv->hf_ipv4 = -1; + yyextra->tlv->hf_ipv6 = -1; + yyextra->tlv->hf_bsid = -1; + yyextra->tlv->hf_protocol = -1; + yyextra->tlv->hf_port_low = -1; + yyextra->tlv->hf_port_high = -1; + yyextra->tlv->hf_ipv4_mask = -1; + yyextra->tlv->hf_ipv6_mask = -1; + yyextra->tlv->hf_vendor_id = -1; + yyextra->tlv->hf_vendor_rest_of_info = -1; + + if (! yyextra->dict->tlvs ) + yyextra->last_tlv = yyextra->dict->tlvs = yyextra->tlv; + else + yyextra->last_tlv = yyextra->last_tlv->next = yyextra->tlv; + + BEGIN TLV_ATTRS; +} + +{name_attr} { ATTR_STR(yyextra->tlv->name); } +{description_attr} { ATTR_STR(yyextra->tlv->description); } +{type_attr} { ATTR_UINT16(yyextra->tlv->type); } +{decoder_attr} { ATTR_DECODER(yyextra->tlv->decoder); } +{since_attr} { ATTR_UINT(yyextra->tlv->since); } +{stop} { BEGIN IN_TLV; } +{stop_end} { BEGIN IN_DICT; } + + +{enum_start} { + D(("enum_start\n")); + + yyextra->enumitem = wmem_new(wmem_epan_scope(), wimaxasncp_dict_enum_t); + yyextra->enumitem->name = NULL; + yyextra->enumitem->code = 0; + yyextra->enumitem->next = NULL; + + if (!yyextra->tlv->enums) + yyextra->last_enumitem = yyextra->tlv->enums = yyextra->enumitem; + else + yyextra->last_enumitem = yyextra->last_enumitem->next = yyextra->enumitem; + + BEGIN ENUM_ATTRS; +} + + +{name_attr} { ATTR_STR(yyextra->enumitem->name); } +{code_attr} { ATTR_UINT(yyextra->enumitem->code); } + +{stop} { BEGIN IN_TLV; } +{stop_end} { BEGIN IN_TLV; } + +{tlv_end} { D(("tlv_end")); BEGIN IN_DICT; } + +{dictionary_end} { + yyterminate(); +} + +{ignored_attr} WIMAXASNCP_IGNORE(); + +. ; + +%% + +/* + * Turn diagnostics back on, so we check the code that we've written. + */ +DIAG_ON_FLEX() + +static int debugging = 0; + +static void wimaxasncp_dict_debug(const gchar *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + if (debugging) vfprintf(stderr, fmt, ap); + va_end(ap); + + fflush(stderr); +} + +static guint wimaxasncp_bits(guint bits, char *n) +{ + return 1u << ((bits - 1) - (strtoul(n, NULL, 10))); +} + +static const value_string wimaxasncp_decode_type_vals[] = +{ + { WIMAXASNCP_TLV_TBD, "WIMAXASNCP_TLV_TBD"}, + { WIMAXASNCP_TLV_COMPOUND, "WIMAXASNCP_TLV_COMPOUND"}, + { WIMAXASNCP_TLV_BYTES, "WIMAXASNCP_TLV_BYTES"}, + { WIMAXASNCP_TLV_ENUM8, "WIMAXASNCP_TLV_ENUM8"}, + { WIMAXASNCP_TLV_ENUM16, "WIMAXASNCP_TLV_ENUM16"}, + { WIMAXASNCP_TLV_ENUM32, "WIMAXASNCP_TLV_ENUM32"}, + { WIMAXASNCP_TLV_ETHER, "WIMAXASNCP_TLV_ETHER"}, + { WIMAXASNCP_TLV_ASCII_STRING, "WIMAXASNCP_TLV_ASCII_STRING"}, + { WIMAXASNCP_TLV_FLAG0, "WIMAXASNCP_TLV_FLAG0"}, + { WIMAXASNCP_TLV_BITFLAGS8, "WIMAXASNCP_TLV_BITFLAGS8"}, + { WIMAXASNCP_TLV_BITFLAGS16, "WIMAXASNCP_TLV_BITFLAGS16"}, + { WIMAXASNCP_TLV_BITFLAGS32, "WIMAXASNCP_TLV_BITFLAGS32"}, + { WIMAXASNCP_TLV_ID, "WIMAXASNCP_TLV_ID"}, + { WIMAXASNCP_TLV_HEX8, "WIMAXASNCP_TLV_HEX8"}, + { WIMAXASNCP_TLV_HEX16, "WIMAXASNCP_TLV_HEX16"}, + { WIMAXASNCP_TLV_HEX32, "WIMAXASNCP_TLV_HEX32"}, + { WIMAXASNCP_TLV_DEC8, "WIMAXASNCP_TLV_DEC8"}, + { WIMAXASNCP_TLV_DEC16, "WIMAXASNCP_TLV_DEC16"}, + { WIMAXASNCP_TLV_DEC32, "WIMAXASNCP_TLV_DEC32"}, + { WIMAXASNCP_TLV_IP_ADDRESS, "WIMAXASNCP_TLV_IP_ADDRESS"}, + { WIMAXASNCP_TLV_IPV4_ADDRESS, "WIMAXASNCP_TLV_IPV4_ADDRESS"}, + { WIMAXASNCP_TLV_PROTOCOL_LIST, "WIMAXASNCP_TLV_PROTOCOL_LIST"}, + { WIMAXASNCP_TLV_PORT_RANGE_LIST, "WIMAXASNCP_TLV_PORT_RANGE_LIST"}, + { WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST,"WIMAXASNCP_TLV_IP_ADDRESS_MASK_LIST"}, + { WIMAXASNCP_TLV_EAP, "WIMAXASNCP_TLV_EAP"}, + { WIMAXASNCP_TLV_VENDOR_SPECIFIC, "WIMAXASNCP_TLV_VENDOR_SPECIFIC"}, + { 0, NULL} +}; + +static gint wimaxasncp_decode_type(const gchar *name) +{ + gsize i; + for (i = 0; i < array_length(wimaxasncp_decode_type_vals) - 1; ++i) + { + if (strcmp(name, wimaxasncp_decode_type_vals[i].strptr) == 0) + { + return wimaxasncp_decode_type_vals[i].value; + } + } + + /* not found, emit some sort of error here? */ + + return WIMAXASNCP_TLV_TBD; +} + +extern void wimaxasncp_dict_unused(yyscan_t yyscanner); +void wimaxasncp_dict_unused(yyscan_t yyscanner) { + yy_top_state(yyscanner); +} + +static void append_to_buffer(const gchar *txt, int len, WimaxasncpDict_scanner_state_t *state) { + + if (state->strbuf == NULL) { + state->read_ptr = state->write_ptr = state->strbuf = (gchar *)g_malloc(state->size_strbuf); + } + + if (state->len_strbuf + len >= state->size_strbuf) { + state->read_ptr = state->strbuf = (gchar *)g_realloc(state->strbuf,state->size_strbuf *= 2); + } + + state->write_ptr = state->strbuf + state->len_strbuf; + memcpy(state->write_ptr, txt, len + 1); + state->len_strbuf += len; +} + +static size_t file_input(gchar *buf, size_t max, yyscan_t scanner) { + FILE *in = yyget_in(scanner); + size_t read_cnt; + + read_cnt = fread(buf,1,max,in); + + if ( read_cnt == max ) { + return max; + } else if (read_cnt > 0) { + return read_cnt; + } else { + return YY_NULL; + } +} + + +static size_t string_input(gchar *buf, size_t max, yyscan_t scanner) { + WimaxasncpDict_scanner_state_t *statep = yyget_extra(scanner); + + if (statep->read_ptr >= statep->write_ptr ) { + return YY_NULL; + } else if ( statep->read_ptr + max > statep->write_ptr ) { + max = statep->write_ptr - statep->read_ptr; + } + + memcpy(buf,statep->read_ptr,max); + statep->read_ptr += max; + + return max; +} + +static FILE *wimaxasncp_dict_open( + const gchar *system_directory, + const gchar *filename) +{ + FILE *fh; + gchar *fname; + if (system_directory) + { + fname = ws_strdup_printf("%s%s%s", + system_directory, G_DIR_SEPARATOR_S,filename); + } + else + { + fname = g_strdup(filename); + } + + fh = ws_fopen(fname,"r"); + + D(("fname: %s fh: %p\n",fname,(void*)fh)); + + g_free(fname); + + + return fh; +} + +wimaxasncp_dict_t *wimaxasncp_dict_scan( + const gchar *system_directory, const gchar *filename, int dbg, + gchar **error) { + + WimaxasncpDict_scanner_state_t state; + FILE *in; + yyscan_t scanner; + entity_t *e; + + debugging = dbg; + + state.dict_error = g_string_new(""); + + state.sys_dir = system_directory; + + state.dict = g_new(wimaxasncp_dict_t,1); + state.dict->tlvs = NULL; + state.dict->xmlpis = NULL; + + state.strbuf = NULL; + state.size_strbuf = 8192; + state.len_strbuf = 0; + + state.write_ptr = NULL; + state.read_ptr = NULL; + + state.tlv = NULL; + state.enumitem = NULL; + state.xmlpi = NULL; + + state.last_tlv = NULL; + state.last_enumitem = NULL; + state.last_xmlpi = NULL; + + state.ents = NULL; + + /* + * Pass 1. + * + * Reads the file, does some work, and stores a modified version + * of the file contents in memory. + */ + state.current_yyinput = file_input; + state.include_stack_ptr = 0; + + in = wimaxasncp_dict_open(system_directory,filename); + + if (in == NULL) { + /* + * Couldn't open the dictionary. + * + * Treat all failures other then ENOENT as errors? + */ + *error = NULL; + return state.dict; + } + + if (WimaxasncpDict_lex_init(&scanner) != 0) { + D(("Can't initialize scanner: %s\n", strerror(errno))); + fclose(in); + g_free(state.dict); + return NULL; + } + + WimaxasncpDict_set_in(in, scanner); + + /* Associate the state with the scanner */ + WimaxasncpDict_set_extra(&state, scanner); + + state.start_state = LOADING; + WimaxasncpDict_lex(scanner); + + WimaxasncpDict_lex_destroy(scanner); + /* + * XXX - can the lexical analyzer terminate without closing + * all open input files? + */ + + D(("\n---------------\n%s\n------- %d -------\n", + state.strbuf, state.len_strbuf)); + + /* + * Pass 2. + * + * Reads the modified version of the file contents and does the + * rest of the work. + */ + state.current_yyinput = string_input; + + if (WimaxasncpDict_lex_init(&scanner) != 0) { + D(("Can't initialize scanner: %s\n", strerror(errno))); + fclose(in); + g_free(state.dict); + g_free(state.strbuf); + return NULL; + } + + /* Associate the state with the scanner */ + WimaxasncpDict_set_extra(&state, scanner); + + state.start_state = OUTSIDE; + WimaxasncpDict_lex(scanner); + + WimaxasncpDict_lex_destroy(scanner); + g_free(state.strbuf); + + e = state.ents; + while (e) + { + entity_t *next = e->next; + g_free(e->name); + g_free(e->file); + g_free(e); + e = next; + } + + if (state.dict_error->len > 0) + { + *error = g_string_free(state.dict_error, FALSE); + } + else + { + *error = NULL; + g_string_free(state.dict_error, TRUE); + } + return state.dict; +} + +void wimaxasncp_dict_free(wimaxasncp_dict_t *d) { + wimaxasncp_dict_tlv_t *t, *tn; + +#define FREE_NAMEANDOBJ(n) do { g_free(n->name); g_free(n); } while(0) + + for (t = d->tlvs; t; t = tn) { + wimaxasncp_dict_enum_t *e, *en; + tn = t->next; + + for (e = t->enums; e; e = en) { + en = e->next; + FREE_NAMEANDOBJ(e); + } + + g_free(t->description); + FREE_NAMEANDOBJ(t); + } + + g_free(d); +} + +void wimaxasncp_dict_print(FILE *fh, wimaxasncp_dict_t *d) { + wimaxasncp_dict_tlv_t *tlvp; + + fprintf(fh,"\n"); + + for (tlvp = d->tlvs; tlvp; tlvp = tlvp->next) { + wimaxasncp_dict_enum_t *e; + fprintf(fh,"TLV: %s[%u] %s[%d] %s (since %u)\n", + tlvp->name ? tlvp->name : "-", + tlvp->type, + val_to_str(tlvp->decoder, + wimaxasncp_decode_type_vals, + "Unknown"), + tlvp->decoder, + tlvp->description ? tlvp->description : "", + tlvp->since); + + for (e = tlvp->enums; e; e = e->next) { + fprintf(fh,"\tEnum: %s[%u]\n", + e->name ? e->name : "-", + e->code); + } + } +} + +#ifdef TEST_WIMAXASNCP_DICT_STANDALONE +int main(int argc, char **argv) { + wimaxasncp_dict_t *d; + gchar *dname = NULL; + gchar *fname; + int i = 1; + + switch (argc) { + case 3: + dname = argv[i++]; + case 2: + fname = argv[i]; + break; + default: + fprintf(stderr,"%s: usage [dictionary_dir] dictionary_filename\n",argv[0]); + return 1; + } + + d = wimaxasncp_dict_scan(dname,fname,1,&dict_error); + + if (dict_error) + { + printf("wimaxasncp - %s", dict_error); + g_free(dict_error); + } + + wimaxasncp_dict_print(stdout, d); + + return 0; +} +#endif diff --git a/plugins/epan/wimaxmacphy/AUTHORS b/plugins/epan/wimaxmacphy/AUTHORS new file mode 100644 index 00000000..d67332d9 --- /dev/null +++ b/plugins/epan/wimaxmacphy/AUTHORS @@ -0,0 +1,5 @@ +Initial development commissioned by Mobile Metrics - http://mobilemetrics.net/ + +Authors : +Stephen Croll + diff --git a/plugins/epan/wimaxmacphy/CMakeLists.txt b/plugins/epan/wimaxmacphy/CMakeLists.txt new file mode 100644 index 00000000..b3e4e325 --- /dev/null +++ b/plugins/epan/wimaxmacphy/CMakeLists.txt @@ -0,0 +1,64 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(wimaxmacphy 0 0 1 0) + +set(DISSECTOR_SRC + packet-wimaxmacphy.c +) + +set(PLUGIN_FILES + plugin.c + ${DISSECTOR_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin + ${DISSECTOR_SRC} +) + +add_wireshark_plugin_library(wimaxmacphy epan) + +target_link_libraries(wimaxmacphy epan) + +install_plugin(wimaxmacphy epan) + +file(GLOB DISSECTOR_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + wimaxmacphy + SWITCHES + --group dissectors-prohibited + --group dissectors-restricted + SOURCES + ${DISSECTOR_SRC} + ${DISSECTOR_HEADERS} +) + +# +# 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: +# diff --git a/plugins/epan/wimaxmacphy/ChangeLog b/plugins/epan/wimaxmacphy/ChangeLog new file mode 100644 index 00000000..ce4f0bcc --- /dev/null +++ b/plugins/epan/wimaxmacphy/ChangeLog @@ -0,0 +1,5 @@ +2007-08-07 Stephen Croll + + * initial version + + diff --git a/plugins/epan/wimaxmacphy/packet-wimaxmacphy.c b/plugins/epan/wimaxmacphy/packet-wimaxmacphy.c new file mode 100644 index 00000000..908d50b4 --- /dev/null +++ b/plugins/epan/wimaxmacphy/packet-wimaxmacphy.c @@ -0,0 +1,5434 @@ +/* packet-wimaxmacphy.c + * Routines for wimaxmacphy (WiMAX MAX PHY over Ethernet) packet dissection + * Copyright 2008, Mobile Metrics - http://mobilemetrics.net/ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include + +/* IF PROTO exposes code to other dissectors, then it must be exported + in a header file. If not, a header file is not needed at all. */ +#include "packet-wimaxmacphy.h" + +/* Initialize the protocol and registered fields */ + +static dissector_handle_t wimaxmacphy_handle; +static int proto_wimaxmacphy = -1; +static int hf_wimaxmacphy_hdr_phy_entity_id = -1; +static int hf_wimaxmacphy_hdr_message_segmentation = -1; +static int hf_wimaxmacphy_hdr_message_type = -1; +static int hf_wimaxmacphy_unknown = -1; +static int hf_wimaxmacphy_prim_length_of_txvector = -1; +static int hf_wimaxmacphy_prim_length_of_rxvector = -1; +static int hf_wimaxmacphy_prim_status = -1; +static int hf_wimaxmacphy_prim_txstart_indication_status = -1; +static int hf_wimaxmacphy_prim_reserved1 = -1; +static int hf_wimaxmacphy_prim_reserved2 = -1; +static int hf_wimaxmacphy_prim_reserved3 = -1; +static int hf_wimaxmacphy_prim_reserved4 = -1; +static int hf_wimaxmacphy_prim_reserved5 = -1; +static int hf_wimaxmacphy_prim_next_frame_number = -1; +static int hf_wimaxmacphy_prim_extended_frame_number = -1; +static int hf_wimaxmacphy_prim_current_frame_number_lsn = -1; +static int hf_wimaxmacphy_prim_initial_frame_number = -1; +static int hf_wimaxmacphy_prim_dl_zone_number = -1; +static int hf_wimaxmacphy_prim_sub_burst_burst_split_point = -1; +static int hf_wimaxmacphy_prim_dl_sub_burst_burst_number = -1; +static int hf_wimaxmacphy_prim_phy_sdu = -1; +static int hf_wimaxmacphy_prim_phy_request = -1; +static int hf_wimaxmacphy_prim_requested_aas_calibration_zone_size = -1; +static int hf_wimaxmacphy_prim_requested_aas_calibration_zone_alloc = -1; +static int hf_wimaxmacphy_prim_number_of_consecutive_frames_with_aas = -1; +static int hf_wimaxmacphy_prim_frame_number = -1; +static int hf_wimaxmacphy_prim_issid = -1; +static int hf_wimaxmacphy_prim_integrity = -1; +static int hf_wimaxmacphy_prim_number_of_bytes_received = -1; +static int hf_wimaxmacphy_prim_rssi_per_subcarrier_level = -1; +static int hf_wimaxmacphy_prim_cinr = -1; +static int hf_wimaxmacphy_prim_power_offset = -1; +static int hf_wimaxmacphy_prim_current_frame_number_msn = -1; +static int hf_wimaxmacphy_prim_acid_for_harq_data_bursts = -1; +static int hf_wimaxmacphy_prim_indication_type = -1; +static int hf_wimaxmacphy_prim_zone_permutation_type = -1; +static int hf_wimaxmacphy_prim_update_aas_handle_in_mac = -1; +static int hf_wimaxmacphy_prim_aas_handle = -1; +static int hf_wimaxmacphy_prim_time_deviation = -1; +static int hf_wimaxmacphy_prim_frequency_deviation = -1; +static int hf_wimaxmacphy_prim_phy_aas_report_present = -1; +static int hf_wimaxmacphy_prim_number_of_affected_ss = -1; +static int hf_wimaxmacphy_prim_zonexid = -1; +static int hf_wimaxmacphy_prim_cdma_code = -1; +static int hf_wimaxmacphy_prim_cdma_symbol = -1; +static int hf_wimaxmacphy_prim_cdma_subchannel = -1; +static int hf_wimaxmacphy_prim_harq_ack_issid = -1; +static int hf_wimaxmacphy_prim_harq_ack_acid = -1; +static int hf_wimaxmacphy_prim_harq_ack_reserved1 = -1; +static int hf_wimaxmacphy_prim_harq_ack_ack_valid = -1; +static int hf_wimaxmacphy_prim_harq_ack_unnamed = -1; +static int hf_wimaxmacphy_prim_harq_ack_reserved2 = -1; +static int hf_wimaxmacphy_prim_fast_issid = -1; +static int hf_wimaxmacphy_prim_fast_cqich_id = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding_bit0 = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding_bit1 = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding_bit2 = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding_bit3 = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding_bit4 = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding_bit5 = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding_bit6 = -1; +static int hf_wimaxmacphy_prim_fast_feedback_type_coding_bit7 = -1; +static int hf_wimaxmacphy_prim_fast_feedback_valid = -1; +static int hf_wimaxmacphy_prim_fast_feedback_sub_type = -1; +static int hf_wimaxmacphy_prim_fast_reserved = -1; +static int hf_wimaxmacphy_prim_fast_feedback_value = -1; +static int hf_wimaxmacphy_subframe_subframe_type = -1; +static int hf_wimaxmacphy_subframe_frame_number = -1; +static int hf_wimaxmacphy_subframe_downlink_reserved1 = -1; +static int hf_wimaxmacphy_subframe_phy_sap_version_number = -1; +static int hf_wimaxmacphy_subframe_downlink_reserved2 = -1; +static int hf_wimaxmacphy_subframe_allocation_start_time = -1; +static int hf_wimaxmacphy_number_of_zone_descriptors = -1; +static int hf_wimaxmacphy_zone_padding = -1; +static int hf_wimaxmacphy_dl_zone_type = -1; +static int hf_wimaxmacphy_ul_zone_type = -1; +static int hf_wimaxmacphy_zone_number = -1; +static int hf_wimaxmacphy_zone_start_symbol_offset = -1; +static int hf_wimaxmacphy_zone_end_symbol_offset = -1; +static int hf_wimaxmacphy_dl_zone_permutation_type = -1; +static int hf_wimaxmacphy_ul_zone_permutation_type = -1; +static int hf_wimaxmacphy_dl_zone_use_all_subchannels_indicator = -1; +static int hf_wimaxmacphy_ul_zone_use_all_subchannels_indicator = -1; +static int hf_wimaxmacphy_ul_zone_disable_pusc_subchannel_rotation = -1; +static int hf_wimaxmacphy_zone_dl_perm_base = -1; +static int hf_wimaxmacphy_zone_ul_perm_base = -1; +static int hf_wimaxmacphy_zone_prbs_id = -1; +static int hf_wimaxmacphy_zone_agc_range_extension = -1; +static int hf_wimaxmacphy_zone_dedicated_pilots = -1; +static int hf_wimaxmacphy_zone_reserved = -1; +static int hf_wimaxmacphy_zone_stc_type = -1; +static int hf_wimaxmacphy_zone_matrix_indicator = -1; +static int hf_wimaxmacphy_zone_midamble_presence = -1; +static int hf_wimaxmacphy_zone_midamble_boosting = -1; +static int hf_wimaxmacphy_zone_preamble_configuration = -1; +static int hf_wimaxmacphy_zone_sdma_supported_indication = -1; +static int hf_wimaxmacphy_zone_preamble_type = -1; +static int hf_wimaxmacphy_dl_zone_aas_reserved = -1; +static int hf_wimaxmacphy_ul_zone_aas_reserved = -1; +static int hf_wimaxmacphy_number_of_burst_descriptors = -1; +static int hf_wimaxmacphy_burst_padding = -1; +static int hf_wimaxmacphy_dl_burst_type = -1; +static int hf_wimaxmacphy_ul_burst_type = -1; +static int hf_wimaxmacphy_burst_type_extension = -1; +static int hf_wimaxmacphy_burst_number = -1; +static int hf_wimaxmacphy_burst_modulation_fec_code_type = -1; +static int hf_wimaxmacphy_burst_data_length = -1; +static int hf_wimaxmacphy_burst_ofdma_symbol_offset = -1; +static int hf_wimaxmacphy_burst_subchannel_offset = -1; +static int hf_wimaxmacphy_burst_boosting = -1; +static int hf_wimaxmacphy_burst_reserved = -1; +static int hf_wimaxmacphy_burst_repetition_coding_indication = -1; +static int hf_wimaxmacphy_burst_issid = -1; +static int hf_wimaxmacphy_burst_aas_handle = -1; +static int hf_wimaxmacphy_dl_burst_map_number_of_slots = -1; +static int hf_wimaxmacphy_dl_burst_map_reserved = -1; +static int hf_wimaxmacphy_dl_burst_normal_number_of_symbols = -1; +static int hf_wimaxmacphy_dl_burst_normal_number_of_subchannels = -1; +static int hf_wimaxmacphy_dl_burst_normal_aas_handle = -1; +static int hf_wimaxmacphy_ul_burst_normal_number_of_slots = -1; +static int hf_wimaxmacphy_ul_burst_normal_reserved = -1; +static int hf_wimaxmacphy_burst_papr_number_of_symbols = -1; +static int hf_wimaxmacphy_burst_papr_number_of_subchannels = -1; +static int hf_wimaxmacphy_burst_papr_reserved = -1; +static int hf_wimaxmacphy_ul_burst_papr_unnamed = -1; +static int hf_wimaxmacphy_ul_burst_harq_ack_number_of_symbols = -1; +static int hf_wimaxmacphy_ul_burst_harq_ack_number_of_subchannels = -1; +static int hf_wimaxmacphy_ul_burst_harq_ack_reserved = -1; +static int hf_wimaxmacphy_ul_burst_fast_number_of_symbols = -1; +static int hf_wimaxmacphy_ul_burst_fast_number_of_subchannels = -1; +static int hf_wimaxmacphy_ul_burst_fast_reserved = -1; +static int hf_wimaxmacphy_ul_burst_initial_number_of_symbols = -1; +static int hf_wimaxmacphy_ul_burst_initial_number_of_subchannels = -1; +static int hf_wimaxmacphy_ul_burst_initial_ranging_method = -1; +static int hf_wimaxmacphy_ul_burst_initial_reserved1 = -1; +static int hf_wimaxmacphy_ul_burst_initial_zone_xid = -1; +static int hf_wimaxmacphy_ul_burst_initial_reserved2 = -1; +static int hf_wimaxmacphy_ul_burst_periodic_number_of_symbols = -1; +static int hf_wimaxmacphy_ul_burst_periodic_number_of_subchannels = -1; +static int hf_wimaxmacphy_ul_burst_periodic_ranging_method = -1; +static int hf_wimaxmacphy_ul_burst_periodic_reserved1 = -1; +static int hf_wimaxmacphy_ul_burst_periodic_zone_xid = -1; +static int hf_wimaxmacphy_ul_burst_periodic_reserved2 = -1; +static int hf_wimaxmacphy_ul_burst_sounding_number_of_symbols = -1; +static int hf_wimaxmacphy_ul_burst_sounding_number_of_subchannels = -1; +static int hf_wimaxmacphy_ul_burst_sounding_type = -1; +static int hf_wimaxmacphy_ul_burst_sounding_separability_type = -1; +static int hf_wimaxmacphy_ul_burst_sounding_max_cyclic_shift_indx = -1; +static int hf_wimaxmacphy_ul_burst_sounding_decimation_value = -1; +static int hf_wimaxmacphy_ul_burst_sounding_decimation_offset_rand = -1; +static int hf_wimaxmacphy_ul_burst_sounding_reserved = -1; +static int hf_wimaxmacphy_ul_burst_noise_number_of_symbols = -1; +static int hf_wimaxmacphy_ul_burst_noise_number_of_subchannels = -1; +static int hf_wimaxmacphy_ul_burst_noise_reserved = -1; +static int hf_wimaxmacphy_burst_opt_aas_preamble_modifier_type = -1; +static int hf_wimaxmacphy_burst_opt_aas_preamble_shift_index = -1; +static int hf_wimaxmacphy_burst_opt_aas_reserved = -1; +static int hf_wimaxmacphy_burst_opt_mimo_matrix_indicator = -1; +static int hf_wimaxmacphy_burst_opt_mimo_layer_index = -1; +static int hf_wimaxmacphy_dl_burst_opt_mimo_reserved = -1; +static int hf_wimaxmacphy_ul_burst_opt_mimo_matrix_indicator = -1; +static int hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns = -1; +static int hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit0 = -1; +static int hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit1 = -1; +static int hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit2 = -1; +static int hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit3 = -1; +static int hf_wimaxmacphy_ul_burst_opt_mimo_collaborative = -1; +static int hf_wimaxmacphy_ul_burst_opt_mimo_antenna_unnamed = -1; +static int hf_wimaxmacphy_number_of_sub_burst_descriptors = -1; +static int hf_wimaxmacphy_sub_burst_padding = -1; +static int hf_wimaxmacphy_dl_sub_burst_type = -1; +static int hf_wimaxmacphy_ul_sub_burst_type = -1; +static int hf_wimaxmacphy_sub_burst_number = -1; +static int hf_wimaxmacphy_sub_burst_symbol_offset = -1; +static int hf_wimaxmacphy_sub_burst_subchannel_offset = -1; +static int hf_wimaxmacphy_sub_burst_number_of_slots = -1; +static int hf_wimaxmacphy_sub_burst_reserved1 = -1; +static int hf_wimaxmacphy_sub_burst_reserved2 = -1; +static int hf_wimaxmacphy_sub_burst_modulation_fec_code_type = -1; +static int hf_wimaxmacphy_sub_burst_issid = -1; +static int hf_wimaxmacphy_sub_burst_aas_handle = -1; +static int hf_wimaxmacphy_sub_burst_boosting = -1; +static int hf_wimaxmacphy_sub_burst_repetition_coding_indication = -1; +static int hf_wimaxmacphy_sub_burst_data_length = -1; +static int hf_wimaxmacphy_sub_burst_harq_chase_harq_channel_id = -1; +static int hf_wimaxmacphy_sub_burst_harq_chase_harq_sequence_number = -1; +static int hf_wimaxmacphy_sub_burst_harq_chase_flush_unnamed = -1; +static int hf_wimaxmacphy_sub_burst_harq_chase_reserved = -1; +static int hf_wimaxmacphy_sub_burst_mimo_chase_harq_channel_id = -1; +static int hf_wimaxmacphy_sub_burst_mimo_chase_harq_sequence_number = -1; +static int hf_wimaxmacphy_sub_burst_mimo_chase_flush_unnamed = -1; +static int hf_wimaxmacphy_sub_burst_mimo_chase_layer_index = -1; +static int hf_wimaxmacphy_ul_sub_burst_ctype = -1; +static int hf_wimaxmacphy_ul_sub_burst_mini_subchannel_index = -1; +static int hf_wimaxmacphy_ul_sub_burst_mini_reserved = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit0 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit1 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit2 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit3 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit4 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit5 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit6 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit7 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_reserved1 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_sub_type = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_cqich_id = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_reserved2 = -1; +static int hf_wimaxmacphy_ul_sub_burst_feedback_slot_offset = -1; +static int hf_wimaxmacphy_ul_sub_burst_harq_ack_acid = -1; +static int hf_wimaxmacphy_ul_sub_burst_harq_ack_reserved = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_symbol_index = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_power_assignment = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_power_boost = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_allocation_mode = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_start_freq_band = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_num_freq_bands = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_band_bit_map = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_cyclic_time_shift = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_decimation_offset = -1; +static int hf_wimaxmacphy_ul_sub_burst_sounding_reserved = -1; +static int hf_wimaxmacphy_ul_sub_burst_mimo_chase_matrix = -1; + +/* Initialize the subtree pointers */ +static gint ett_wimaxmacphy = -1; +static gint ett_wimaxmacphy_primitive = -1; +static gint ett_wimaxmacphy_prim_harq_ack = -1; +static gint ett_wimaxmacphy_prim_fast_feedback = -1; +static gint ett_wimaxmacphy_prim_fast_feedback_type_coding = -1; +static gint ett_wimaxmacphy_dl_zone_descriptor = -1; +static gint ett_wimaxmacphy_dl_zone_stc = -1; +static gint ett_wimaxmacphy_dl_zone_aas = -1; +static gint ett_wimaxmacphy_dl_burst_descriptor = -1; +static gint ett_wimaxmacphy_dl_burst_map = -1; +static gint ett_wimaxmacphy_dl_burst_normal = -1; +static gint ett_wimaxmacphy_dl_burst_papr = -1; +static gint ett_wimaxmacphy_dl_sub_burst_descriptor = -1; +static gint ett_wimaxmacphy_dl_sub_burst_harq_chase = -1; +static gint ett_wimaxmacphy_dl_sub_burst_mimo_chase = -1; +static gint ett_wimaxmacphy_dl_burst_opt_aas = -1; +static gint ett_wimaxmacphy_dl_burst_opt_mimo = -1; +static gint ett_wimaxmacphy_ul_zone_descriptor = -1; +static gint ett_wimaxmacphy_ul_zone_aas = -1; +static gint ett_wimaxmacphy_ul_burst_descriptor = -1; +static gint ett_wimaxmacphy_ul_burst_harq_ack = -1; +static gint ett_wimaxmacphy_ul_burst_fast_feedback = -1; +static gint ett_wimaxmacphy_ul_burst_initial_ranging = -1; +static gint ett_wimaxmacphy_ul_burst_periodic_ranging = -1; +static gint ett_wimaxmacphy_ul_burst_papr_safety_zone = -1; +static gint ett_wimaxmacphy_ul_burst_sounding_zone = -1; +static gint ett_wimaxmacphy_ul_burst_noise_floor = -1; +static gint ett_wimaxmacphy_ul_burst_normal_data = -1; +static gint ett_wimaxmacphy_ul_burst_opt_aas = -1; +static gint ett_wimaxmacphy_ul_burst_opt_mimo = -1; +static gint ett_wimaxmacphy_ul_sub_burst_descriptor = -1; +static gint ett_wimaxmacphy_ul_pilot_patterns = -1; +static gint ett_wimaxmacphy_ul_feedback_type_coding = -1; +static gint ett_wimaxmacphy_ul_sub_burst_mini_subchannel = -1; +static gint ett_wimaxmacphy_ul_sub_burst_fast_feedback = -1; +static gint ett_wimaxmacphy_ul_sub_burst_harq_ack = -1; +static gint ett_wimaxmacphy_ul_sub_burst_sounding_signal = -1; +static gint ett_wimaxmacphy_ul_sub_burst_harq_chase = -1; +static gint ett_wimaxmacphy_ul_sub_burst_mimo_chase = -1; +static gint ett_wimaxmacphy_ul_sub_burst_sub_allocation_specific = -1; + +static expert_field ei_wimaxmacphy_unknown = EI_INIT; + +/* PHY SAP message header size */ +#define WIMAXMACPHY_HEADER_SIZE 2 + +#define WIMAXMACPHY_BIT(n) (1 << (n)) + +#define WIMAXMACPHY_PHY_TXSTART_REQUEST 1 +#define WIMAXMACPHY_PHY_TXSTART_CONFIRMATION 2 +#define WIMAXMACPHY_PHY_TXSTART_INDICATION 3 +#define WIMAXMACPHY_PHY_TXSDU_REQUEST 4 +#define WIMAXMACPHY_PHY_TXSDU_CONFIRMATION 5 +#define WIMAXMACPHY_PHY_TXEND_INDICATION 6 +#define WIMAXMACPHY_PHY_RXSTART_REQUEST 7 +#define WIMAXMACPHY_PHY_RXSTART_CONFIRMATION 8 +#define WIMAXMACPHY_PHY_RXSTART_INDICATION 9 +#define WIMAXMACPHY_PHY_RXSDU_INDICATION 10 +#define WIMAXMACPHY_PHY_RXEND_INDICATION 11 +#define WIMAXMACPHY_PHY_RXCDMA_INDICATION 15 + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_message_segmentation_vals[] = +{ + { 0x00, "Middle segment of the message segment sequence"}, + { 0x01, "Last segment of the message segment sequence"}, + { 0x02, "First segment of the message segment sequence"}, + { 0x03, "The entire message is contained in this segment"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_message_type_vals[] = +{ + { 0, "Reserved"}, + { 1, "PHY_TXSTART.request"}, + { 2, "PHY_TXSTART.confirmation"}, + { 3, "PHY_TXSTART.indication"}, + { 4, "PHY_TXSDU.request"}, + { 5, "PHY_TXSDU.confirmation"}, + { 6, "PHY_TXEND.indication"}, + { 7, "PHY_RXSTART.request"}, + { 8, "PHY_RXSTART.confirmation"}, + { 9, "PHY_RXSTART.indication"}, + { 10, "PHY_RXSDU.indication"}, + { 11, "PHY_RXEND.indication"}, + { 12, "Reserved (OFDM)"}, + { 13, "Reserved (OFDM)"}, + { 14, "Reserved (OFDM)"}, + { 15, "PHY_RXCDMA.indication"}, + { 16, "Reserved (OFDMA SS)"}, + { 17, "Reserved (OFDMA SS)"}, + { 0, NULL} +}; +#if 0 /* XXX: 'tshark -G values' gives warning on Windows' */ +static value_string_ext wimaxmacphy_message_type_vals_ext = VALUE_STRING_EXT_INIT(wimaxmacphy_message_type_vals); +#endif + +/* ------------------------------------------------------------------------- */ +/* error code field coding, for all but TXSTART.indication + */ +static const value_string wimaxmacphy_prim_status_vals[]= +{ + { 0, "Success"}, + { 1, "Primitive is not supported"}, + { 2, "FEC code type is not supported"}, + { 3, "Overrun"}, + { 4, "Underrun"}, + { 5, "Transport Media Error"}, + { 6, "TX data size do not match TXVECTOR"}, + { 7, "Invalid RX/TX VECTOR format"}, + { 0, NULL} +}; + +/* --------------------------------------------------------------------------- + * error code field coding, TXSTART.indication specific, delta is description + * for value 1 + */ + +static const value_string wimaxmacphy_prim_txstart_indication_status_vals[]= +{ + { 0, "Success"}, + { 1, "Restart flag"}, + { 2, "FEC code type is not supported"}, + { 3, "Overrun"}, + { 4, "Underrun"}, + { 5, "Transport Media Error"}, + { 6, "TX data size do not match TXVECTOR"}, + { 7, "Invalid RX/TX VECTOR format"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +#if 0 +static const value_string wimaxmacphy_prim_sub_burst_burst_split_point_vals[]= +{ + { 0x00, "all 10 bits for burst number"}, + { 0x01, "1 bit sub-burst and 9 bits burst number"}, + { 0x02, "2 bit sub-burst and 8 bits burst number"}, + { 0x03, "3 bit sub-burst and 7 bits burst number"}, + { 0x04, "4 bit sub-burst and 6 bits burst number"}, + { 0x05, "5 bit sub-burst and 5 bits burst number"}, + { 0x06, "6 bit sub-burst and 4 bits burst number"}, + { 0x07, "7 bit sub-burst and 3 bits burst number"}, + { 0, NULL} +}; +#endif + +/* ------------------------------------------------------------------------- */ + +#if 0 +static const value_string wimaxmacphy_prim_phy_request_vals[]= +{ + { 0x0, "LW 1 not present"}, + { 0x1, "AAS calibration request present in LW 1"}, + { 0, NULL} +}; +#endif + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_prim_integrity_vals[]= +{ + { 0, "valid data"}, + { 1, "invalid data"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_prim_indication_type_vals[]= +{ + { 0, "Data burst"}, + { 1, "HARQ ACK channel"}, + { 2, "Fast Feedback Channel"}, + { 3, "HARQ data burst"}, + { 4, "MIMO data burst"}, + { 5, "MIMO HARQ data burst"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_prim_zone_permutation_type_vals[]= +{ + { 0x0, "PUSC"}, + { 0x1, "Optional PUSC"}, + { 0x2, "AMC - 1 x 6"}, + { 0x3, "AMC - 2 x 3"}, + { 0x4, "AMC - 3 x 2"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_prim_phy_aas_report_present_vals[]= +{ + { 0x0, " not present (only LW 0 is significant)"}, + { 0x1, "AAS info aged out report present"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_prim_harq_ack_ack_valid_vals[]= +{ + { 0, "valid data"}, + { 1, "invalid data"}, + { 0, NULL} +}; + +static const true_false_string set_notset = { + "Set", + "Not set" +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_prim_harq_ack_unnamed_vals[]= +{ + { 0, "ACK"}, + { 1, "NAK"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_prim_fast_feedback_valid_vals[]= +{ + { 0, "valid data"}, + { 1, "invalid data"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_prim_fast_feedback_sub_type_vals[]= +{ + { 0, "CQI (CINR) measurement"}, + { 1, "Control feedback"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_subframe_type_vals[]= +{ + { 1, "Downlink Subframe"}, + { 2, "Uplink Subframe"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_dl_zone_type_vals[]= +{ + { 0x20, "Normal Zone Parameters"}, + { 0x21, "STC Zone Parameters"}, + { 0x22, "AAS Zone Parameters"}, + { 0x23, "Common Sync Symbol Parameters"}, + { 0x24, "AAS Calibration Zone"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_zone_type_vals[]= +{ + { 0x20, "Normal Zone Parameters"}, + { 0x21, "Reserved"}, + { 0x22, "AAS Zone Parameters"}, + { 0x23, "Reserved"}, + { 0x24, "Reserved"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_dl_zone_permutation_type_vals[]= +{ + { 0x00, "PUSC"}, + { 0x01, "FUSC"}, + { 0x02, "Optional FUSC"}, + { 0x03, "AMC - 1 x 6"}, + { 0x04, "AMC - 2 x 3"}, + { 0x05, "AMC - 3 x 2"}, + { 0x06, "TUSC1"}, + { 0x07, "TUSC2"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_zone_permutation_type_vals[]= +{ + { 0x00, "PUSC"}, + { 0x01, "FUSC"}, + { 0x02, "Optional FUSC"}, + { 0x03, "AMC - 1 x 6"}, + { 0x04, "AMC - 2 x 3"}, + { 0x05, "AMC - 3 x 2"}, + { 0x06, "Reserved"}, + { 0x07, "Reserved"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_zone_use_all_subchannels_indicator_vals[]= +{ + { 0, "use only subchannels specified in PHY configuration register"}, + { 1, "use all subchannels"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_ul_zone_disable_pusc_subchannel_rotation_vals[]= +{ + { 0, "rotation enabled"}, + { 1, "rotation disabled"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_zone_dedicated_pilots_vals[]= +{ + { 0, "pilots are broadcast"}, + { 1, "pilots are dedicated"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_zone_agc_range_extension_vals[]= +{ + { 0, "default range"}, + { 1, "range to cover SS very close to BS"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_zone_stc_type_vals[]= +{ + { 0x00, "STC using 2 antennas"}, + { 0x01, "STC using 3 antennas"}, + { 0x02, "STC using 4 antennas"}, + { 0x03, "FHDC using 2 antennas"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_matrix_indicator_vals[]= +{ + { 0x00, "Matrix A"}, + { 0x01, "Matrix B"}, + { 0x02, "Matrix C"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_zone_midamble_presence_vals[]= +{ + { 0, "not present"}, + { 1, "present"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_zone_midamble_boosting_vals[]= +{ + { 0, "no boosting"}, + { 1, "boosting"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_zone_preamble_configuration_vals[]= +{ + { 0x00, "0 symbols (preambles not supported)"}, + { 0x01, "1 symbol"}, + { 0x02, "2 symbols"}, + { 0x03, "3 symbols"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_zone_sdma_supported_indication_vals[]= +{ + { 0, "SDMA not supported"}, + { 1, "SDMA supported"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_zone_preamble_type_vals[]= +{ + { 0, "frequency shifted preamble"}, + { 1, "time shifted preamble"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_dl_burst_type_vals[]= +{ + { 0x40, "Map Data Burst"}, + { 0x41, "Normal Data Burst"}, + { 0x42, "Control Command"}, + { 0x43, "PAPR Allocation"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_burst_type_vals[]= +{ + { 0x40, "HARQ ACK Channel allocation"}, + { 0x41, "Fast Feedback Channel allocation"}, + { 0x42, "Initial Ranging/Handover Ranging region"}, + { 0x43, "Periodic Ranging/Bandwidth Request region"}, + { 0x44, "PAPR/Safety Zone allocation"}, + { 0x45, "Sounding Zone allocation"}, + { 0x46, "Noise Floor Calculation allocation"}, + { 0x47, "Normal Data burst"}, + { 0x48, "Control Command"}, + { 0x49, "Reserved"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_burst_type_extension_vals[]= +{ + { 0x00, "no extended data:"}, + { 0x01, "AAS v1"}, + { 0x02, "MIMO v1"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_modulation_fec_code_type_vals[]= +{ + { 0, "QPSK (CC) 1/2"}, + { 1, "QPSK (CC) 3/4"}, + { 2, "16-QAM (CC) 1/2"}, + { 3, "16-QAM (CC) 3/4"}, + { 4, "64-QAM (CC) 1/2"}, + { 5, "64-QAM (CC) 2/3"}, + { 6, "64-QAM (CC) 3/4"}, + { 7, "QPSK (BTC) 1/2"}, + { 8, "QPSK (BTC) 3/4"}, + { 9, "16-QAM (BTC) 3/5"}, + { 10, "16-QAM (BTC) 4/5"}, + { 11, "64-QAM (BTC) 5/8"}, + { 12, "64-QAM (BTC) 4/5"}, + { 13, "QPSK (CTC) 1/2"}, + { 14, "Reserved"}, + { 15, "QPSK (CTC) 3/4"}, + { 16, "16-QAM (CTC) 1/2"}, + { 17, "16-QAM (CTC) 3/4"}, + { 18, "64-QAM (CTC) 1/2"}, + { 19, "64-QAM (CTC) 2/3"}, + { 20, "64-QAM (CTC) 3/4"}, + { 21, "64-QAM (CTC) 5/6"}, + { 22, "QPSK (ZT CC) 1/2"}, + { 23, "QPSK (ZT CC) 3/4"}, + { 24, "16-QAM (ZT CC) 1/2"}, + { 25, "16-QAM (ZT CC) 3/4"}, + { 26, "64-QAM (ZT CC) 1/2"}, + { 27, "64-QAM (ZT CC) 2/3"}, + { 28, "64-QAM (ZT CC) 3/4"}, + { 29, "QPSK (LDPC) 1/2"}, + { 30, "QPSK (LDPC) 2/3 A code"}, + { 31, "QPSK (LDPC) 3/4 A code"}, + { 32, "16-QAM (LDPC) 1/2"}, + { 33, "16-QAM (LDPC) 2/3 A code"}, + { 34, "16-QAM (LDPC) 3/4 A code"}, + { 35, "64-QAM (LDPC) 1/2"}, + { 36, "64-QAM (LDPC) 2/3 A code"}, + { 37, "64-QAM (LDPC) 3/4 A code"}, + { 38, "QPSK (LDPC) 2/3 B code"}, + { 39, "QPSK (LDPC) 3/4 B code"}, + { 40, "16-QAM (LDPC) 2/3 B code"}, + { 41, "16-QAM (LDPC) 3/4 B code"}, + { 42, "64-QAM (LDPC) 2/3 B code"}, + { 43, "64-QAM (LDPC) 3/4 B code"}, + { 44, "QPSK (CC with optional interleaver) 1/2"}, + { 45, "QPSK (CC with optional interleaver) 3/4"}, + { 46, "16-QAM (CC with optional interleaver) 1/2"}, + { 47, "16-QAM (CC with optional interleaver) 3/4"}, + { 48, "64-QAM (CC with optional interleaver) 2/3"}, + { 49, "64-QAM (CC with optional interleaver) 3/4"}, + { 50, "QPSK (LDPC) 5/6"}, + { 51, "16-QAM(LDPC) 5/6"}, + { 52, "64-QAM(LDPC) 5/6"}, + { 0, NULL} +}; +#if 0 /* XXX: 'tshark -G values' gives warning on Windows' */ +static value_string_ext wimaxmacphy_modulation_fec_code_type_vals_ext = + VALUE_STRING_EXT_INIT(wimaxmacphy_modulation_fec_code_type_vals); +#endif + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_burst_boosting_vals[]= +{ + { 0x00, "normal"}, + { 0x01, "+6dB"}, + { 0x02, "-6dB"}, + { 0x03, "+9dB"}, + { 0x04, "+3dB"}, + { 0x05, "-3dB"}, + { 0x06, "-9 dB"}, + { 0x07, "-12 dB"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_burst_repetition_coding_indication_vals[]= +{ + { 0x00, "No repetition coding"}, + { 0x01, "Repetition coding of 2"}, + { 0x02, "Repetition coding of 4"}, + { 0x03, "Repetition coding of 6"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_dl_sub_burst_type_vals[]= +{ + { 0x60, "No HARQ"}, + { 0x61, "HARQ Chase Combining"}, + { 0x62, "HARQ IR-CTC"}, + { 0x63, "HARQ IR-CC"}, + { 0x64, "MIMO Chase Combining"}, + { 0x65, "MIMO IR-CTC"}, + { 0x66, "MIMO IR-CC"}, + { 0x67, "MIMO-STC"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_sub_burst_type_vals[]= +{ + { 0x60, "No HARQ"}, + { 0x61, "HARQ Chase Combining"}, + { 0x62, "HARQ IR-CTC"}, + { 0x63, "HARQ IR-CC"}, + { 0x64, "MIMO Chase Combining"}, + { 0x65, "MIMO IR-CTC"}, + { 0x66, "MIMO IR-CC"}, + { 0x67, "MIMO-STC"}, + { 0x68, "Mini-subchannel"}, + { 0x69, "Fast Feedback channel"}, + { 0x6A, "HARQ ACK subchannel"}, + { 0x6B, "Sounding signal"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_sub_burst_flush_unnamed_vals[]= +{ + { 0x00, "no flush action"}, + { 0x02, "flush request to PHY for the ISSID/ACID"}, + { 0x03, "flush request to PHY for the given ISSID"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_burst_papr_unnamed_vals[]= +{ + { 0, "UL PAPR reduction"}, + { 1, "UL Safety zone"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_burst_ranging_method_vals[]= +{ + { 0, "ranging over 2 symbols"}, + { 1, "ranging over 4 symbols"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_burst_sounding_type_vals[]= +{ + { 0, "Type A"}, + { 1, "Type B"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_ul_burst_sounding_separability_type_vals[]= +{ + { 0, "all subcarriers"}, + { 1, "decimated subcarriers in a band"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_ul_burst_sounding_max_cyclic_shift_indx_vals[]= +{ + { 0x00, "P=4"}, + { 0x01, "P=8;"}, + { 0x02, "P=16"}, + { 0x03, "P=32"}, + { 0x04, "P=9"}, + { 0x05, "P=18"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_ul_burst_sounding_decimation_offset_rand_vals[]= +{ + { 0, "no randomization"}, + { 1, "randomization"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_ul_burst_opt_mimo_matrix_indicator_vals[]= +{ + { 0x00, "Matrix A (STTD)"}, + { 0x01, "Matrix B (SM)"}, + { 0x02, "Reserved"}, + { 0x03, "Reserved"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_burst_opt_mimo_collaborative_vals[]= +{ + { 0, "non-collaborative"}, + { 1, "collaborative"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_burst_opt_mimo_antenna_unnamed_vals[]= +{ + { 0, "Single TX antenna SS"}, + { 1, "Dual TX antenna SS"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_sub_burst_ctype_vals[]= +{ + { 0x00, "2 mini-subchannels adjacent tiles"}, + { 0x01, "2 mini subchannels interleaved tiles"}, + { 0x02, "3 mini subchannels"}, + { 0x03, "6 mini subchannels"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +#if 0 +static const value_string wimaxmacphy_ul_sub_burst_feedback_sub_type_vals[]= +{ + { 0, "CQI (CINR) measurement"}, + { 1, "Control feedback"}, + { 0, NULL} +}; +#endif + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_ul_sub_burst_sounding_power_assignment_vals[]= +{ + { 0x00, "Equal power"}, + { 0x01, "Reserved"}, + { 0x02, "Interference dependent. Per subcarrier power limit."}, + { 0x03, "Interference dependent. Total power limit."}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_sub_burst_sounding_power_boost_vals[]= +{ + { 0, "no boost"}, + { 1, "boost"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static +const value_string wimaxmacphy_ul_sub_burst_sounding_allocation_mode_vals[]= +{ + { 0, "Normal"}, + { 1, "Band AMC"}, + { 0, NULL} +}; + +/* ------------------------------------------------------------------------- */ + +static const value_string wimaxmacphy_ul_sub_burst_mimo_chase_matrix_vals[]= +{ + { 0, "Matrix A"}, + { 1, "Matrix B"}, + { 0, NULL} +}; + +static gint dissect_wimaxmacphy_dl_sub_burst_descriptor(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + guint start_offset = offset; + guint8 sub_burst_type; + proto_tree *subtree; + + sub_burst_type = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_dl_sub_burst_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_symbol_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_subchannel_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_number_of_slots, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_reserved1, tvb, offset, 2, ENC_NA); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_reserved2, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_modulation_fec_code_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_issid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_aas_handle, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_boosting, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_repetition_coding_indication, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_data_length, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* sub-burst-specific parts */ + switch (sub_burst_type) + { + case 0x61: /* HARQ chase combining */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_sub_burst_harq_chase, NULL, "HARQ Chase Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_harq_chase_harq_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_harq_chase_harq_sequence_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_harq_chase_flush_unnamed, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_harq_chase_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + break; + + case 0x64: /* MIMO chase combining */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_sub_burst_mimo_chase, NULL, "MIMO Chase Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_mimo_chase_harq_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_mimo_chase_harq_sequence_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_mimo_chase_flush_unnamed, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_mimo_chase_layer_index, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + break; + + default: + /* do nothing */ + break; + } + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_dl_burst_descriptor(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree) +{ + guint start_offset = offset; + guint8 burst_type, burst_type_extension, sub_burst_descriptor_count, sub_burst; + proto_item *item; + proto_tree *subtree, *opt_tree; + + burst_type = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_dl_burst_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + burst_type_extension = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_burst_type_extension, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_modulation_fec_code_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_data_length, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_ofdma_symbol_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_subchannel_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_boosting, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_repetition_coding_indication, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* burst-specific parts */ + switch (burst_type) + { + case 0x40: /* map */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_burst_map, NULL, "MAP Data Burst Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_dl_burst_map_number_of_slots, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_dl_burst_map_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + case 0x41: /* normal */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_burst_normal, NULL, "Normal Data Burst Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_dl_burst_normal_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_dl_burst_normal_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_dl_burst_normal_aas_handle, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* extensions */ + switch (burst_type_extension) + { + case 0x01: /* AAS v1 */ + + opt_tree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_burst_opt_aas, NULL, "Optional AAS Specific"); + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_aas_preamble_modifier_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_aas_preamble_shift_index, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_aas_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + /* ??? Algorithm specific Information (per Burst Type extension) */ + break; + + case 0x02: /* MIMO v1 */ + + opt_tree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_burst_opt_mimo, NULL, "Optional MIMO Specific"); + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_mimo_matrix_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_mimo_layer_index, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_dl_burst_opt_mimo_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + + /* ??? Algorithm specific Information (per Burst Type extension) */ + break; + + default: + /* do nothing */ + break; + } + + break; + + case 0x43: /* PAPR */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_burst_papr, NULL, "PAPR Allocation Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_burst_papr_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_burst_papr_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_burst_papr_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + default: + /* do nothing */ + break; + } + + /* sub-burst portion */ + sub_burst_descriptor_count = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_number_of_sub_burst_descriptors, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_padding, tvb, offset, 3, ENC_NA); + offset += 3; + + /* sub-burst descriptors */ + for (sub_burst = 0; sub_burst < sub_burst_descriptor_count; ++sub_burst) + { + proto_tree *sub_burst_descriptor_tree; + guint sub_burst_descriptor_length; + + sub_burst_descriptor_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, + ett_wimaxmacphy_dl_sub_burst_descriptor, &item, "Sub-Burst Descriptor %u", sub_burst); + + sub_burst_descriptor_length = dissect_wimaxmacphy_dl_sub_burst_descriptor(tvb, offset, + pinfo, sub_burst_descriptor_tree); + + proto_item_set_len(item, sub_burst_descriptor_length); + offset += sub_burst_descriptor_length; + } + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_dl_zone_descriptor(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree) +{ + guint start_offset = offset; + guint8 zone_type, burst_descriptor_count, burst; + proto_item *item; + proto_tree *subtree; + + zone_type = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_dl_zone_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_start_symbol_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_end_symbol_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_dl_zone_permutation_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_dl_zone_use_all_subchannels_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_dl_perm_base, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_prbs_id, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_dedicated_pilots, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_reserved, tvb, offset, 3, ENC_NA); + offset += 3; + + /* zone-specific parts */ + switch (zone_type) + { + case 0x21: /* STC */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_zone_stc, NULL, "STC Zone Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_stc_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_matrix_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_midamble_presence, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_midamble_boosting, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + break; + + case 0x22: /* AAS */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_dl_zone_aas, NULL, "AAS Zone Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_preamble_configuration, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_sdma_supported_indication, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_dl_zone_aas_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + /* ??? Algorithm Specific Information (per Zone Type) */ + break; + + default: + /* do nothing */ + break; + } + + /* burst portion */ + burst_descriptor_count = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_number_of_burst_descriptors, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_padding, tvb, offset, 3, ENC_NA); + offset += 3; + + /* burst descriptors */ + for (burst = 0; burst < burst_descriptor_count; ++burst) + { + proto_tree *burst_descriptor_tree; + guint burst_descriptor_length; + + /* note: we'll adjust the length later */ + burst_descriptor_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, + ett_wimaxmacphy_dl_burst_descriptor, &item, "Burst Descriptor %u", burst); + + burst_descriptor_length = dissect_wimaxmacphy_dl_burst_descriptor( + tvb, offset, pinfo, burst_descriptor_tree); + + proto_item_set_len(item, burst_descriptor_length); + + offset += burst_descriptor_length; + } + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_dl_subframe_descriptor(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree) +{ + guint start_offset = offset; + guint8 zone_descriptor_count; + guint8 zone; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_subframe_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_downlink_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_phy_sap_version_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_downlink_reserved2, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* zone portion */ + zone_descriptor_count = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_number_of_zone_descriptors, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_number_of_zone_descriptors, tvb, offset, 3, ENC_BIG_ENDIAN); + offset += 3; + + /* zone descriptors */ + for (zone = 0; zone < zone_descriptor_count; ++zone) + { + proto_item *item; + proto_tree *zone_descriptor_tree; + guint zone_descriptor_length; + + zone_descriptor_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_wimaxmacphy_dl_zone_descriptor, &item, "Zone Descriptor %u", zone); + + zone_descriptor_length = dissect_wimaxmacphy_dl_zone_descriptor( + tvb, offset, pinfo, zone_descriptor_tree); + + proto_item_set_len(item, zone_descriptor_length); + + offset += zone_descriptor_length; + } + + return offset - start_offset; +} + +static gint dissect_wimaxmacphy_ul_sub_burst_sub_allocation_specific_part(tvbuff_t *tvb, guint offset, + packet_info *pinfo _U_, proto_tree *tree, guint8 sub_burst_type) +{ + guint start_offset = offset; + proto_item *item, *opt_item; + proto_tree *subtree, *opt_tree; + + subtree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_wimaxmacphy_ul_sub_burst_sub_allocation_specific, &item, "Sub-Allocation Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_symbol_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_subchannel_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_number_of_slots, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_data_length, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_repetition_coding_indication, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_modulation_fec_code_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_sub_burst_reserved1, tvb, offset, 2, ENC_NA); + offset += 2; + + /* HARQ chase and MIMO chase specific parts */ + switch (sub_burst_type) + { + case 0x61: /* HARQ chase combining */ + + opt_tree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_sub_burst_harq_chase, &opt_item, "HARQ Chase Specific"); + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_sub_burst_harq_chase_harq_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_sub_burst_harq_chase_harq_sequence_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_sub_burst_harq_chase_flush_unnamed, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_sub_burst_harq_chase_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + break; + + case 0x64: /* MIMO chase combining */ + + opt_tree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_sub_burst_mimo_chase, NULL, "MIMO Chase Specific"); + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_sub_burst_mimo_chase_harq_channel_id, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_sub_burst_mimo_chase_harq_sequence_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_sub_burst_mimo_chase_flush_unnamed, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_ul_sub_burst_mimo_chase_matrix, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + break; + + default: + /* do nothing */ + break; + } + + proto_item_set_len(item, offset - start_offset); + + return offset - start_offset; +} + +static gint dissect_wimaxmacphy_ul_sub_burst_descriptor(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + guint8 sub_burst_type; + proto_item *feedback_item; + proto_tree *subtree, *feedback_tree; + guint start_offset = offset; + + sub_burst_type = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_ul_sub_burst_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_issid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_aas_handle, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_reserved1, tvb, offset, 2, ENC_NA); + offset += 2; + + /* sub-burst-specific parts */ + switch (sub_burst_type) + { + case 0x68: /* mini-subchannel */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_sub_burst_mini_subchannel, NULL, "Mini-Subchannel Allocation Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_ctype, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_mini_subchannel_index, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_mini_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + case 0x69: /* fast feedback */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_sub_burst_fast_feedback, NULL, "Fast Feedback Allocation Specific"); + + feedback_item = proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding, tvb, offset, 1, ENC_BIG_ENDIAN); + feedback_tree = proto_item_add_subtree(feedback_item, ett_wimaxmacphy_ul_feedback_type_coding); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit3, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit4, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit5, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit6, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit7, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_feedback_reserved1, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_feedback_sub_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_feedback_cqich_id, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_feedback_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_feedback_slot_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + break; + + case 0x6a: /* HARQ ACK */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_sub_burst_harq_ack, NULL, "HARQ ACK Subchannel Allocation Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_harq_ack_acid, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_harq_ack_reserved, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + break; + + case 0x6b: /* sounding signal */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 11, ett_wimaxmacphy_ul_sub_burst_sounding_signal, NULL, "Sounding Signal Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_symbol_index, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_power_assignment, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_power_boost, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_allocation_mode, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_start_freq_band, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_num_freq_bands, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_band_bit_map, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_cyclic_time_shift, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_decimation_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_sub_burst_sounding_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + break; + + default: + offset += dissect_wimaxmacphy_ul_sub_burst_sub_allocation_specific_part( + tvb, offset, pinfo, tree, sub_burst_type); + break; + } + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_ul_burst_descriptor(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree) +{ + guint8 burst_type, burst_type_extension; + guint8 sub_burst_descriptor_count, sub_burst; + proto_item *item, *pilot_patterns_item; + proto_tree *subtree, *opt_tree, *pilot_patterns_tree; + guint start_offset = offset; + + burst_type = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_ul_burst_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + burst_type_extension = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_burst_type_extension, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_modulation_fec_code_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_data_length, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_ofdma_symbol_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_subchannel_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_repetition_coding_indication, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_issid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_aas_handle, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* burst-specific parts */ + switch (burst_type) + { + case 0x40: /* HARQ ACK channel */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_burst_harq_ack, NULL, "HARQ ACK Channel Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_harq_ack_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_harq_ack_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_harq_ack_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + case 0x41: /* fast feedback channel */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_burst_fast_feedback, NULL, "Fast Feedback Channel Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_fast_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_fast_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_fast_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + case 0x42: /* initial ranging/handover ranging */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 8, ett_wimaxmacphy_ul_burst_initial_ranging, NULL, "Initial Ranging/Handover Ranging Allocation Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_initial_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_initial_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_initial_ranging_method, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_initial_reserved1, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_initial_zone_xid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_initial_reserved2, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + case 0x43: /* periodic ranging/bandwidth request */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 8, ett_wimaxmacphy_ul_burst_periodic_ranging, NULL, "Periodic Ranging/Bandwidth Request Allocation Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_periodic_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_periodic_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_periodic_ranging_method, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_periodic_reserved1, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_periodic_zone_xid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_periodic_reserved2, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + case 0x44: /* PAPR/safety zone */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_burst_papr_safety_zone, NULL, "PAPR/Safety Zone Channel Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_burst_papr_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_burst_papr_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_papr_unnamed, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_burst_papr_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + break; + + case 0x45: /* sounding zone */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 8, ett_wimaxmacphy_ul_burst_sounding_zone, NULL, "Sounding Zone Allocation Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_sounding_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_sounding_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_sounding_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_sounding_separability_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_sounding_max_cyclic_shift_indx, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_sounding_decimation_value, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_sounding_decimation_offset_rand, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_sounding_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + break; + + case 0x46: /* noise floor calculation */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_burst_noise_floor, NULL, "Noise Floor Calculation Allocation Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_noise_number_of_symbols, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_noise_number_of_subchannels, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_noise_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + break; + + case 0x47: /* normal data */ + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_burst_normal_data, NULL, "Normal Data Burst Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_normal_number_of_slots, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_burst_normal_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + /* extensions */ + switch (burst_type_extension) + { + case 0x01: /* AAS v1 */ + + opt_tree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_burst_opt_aas, NULL, "Optional AAS Specific"); + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_aas_preamble_modifier_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_aas_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_aas_preamble_shift_index, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* ??? Algorithm specific Information (per Burst Type extension) */ + break; + + case 0x02: /* MIMO v1 */ + + opt_tree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_burst_opt_mimo, NULL, "Optional MIMO Specific"); + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_ul_burst_opt_mimo_matrix_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* optional MIMO-specific - pilot patterns */ + pilot_patterns_item = proto_tree_add_item(opt_tree, hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns, tvb, offset, 1, ENC_BIG_ENDIAN); + pilot_patterns_tree = proto_item_add_subtree(pilot_patterns_item, ett_wimaxmacphy_ul_pilot_patterns); + proto_tree_add_item(pilot_patterns_tree, hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pilot_patterns_tree, hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pilot_patterns_tree, hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(pilot_patterns_tree, hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit3, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_ul_burst_opt_mimo_collaborative, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(opt_tree, hf_wimaxmacphy_ul_burst_opt_mimo_antenna_unnamed, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(opt_tree, hf_wimaxmacphy_burst_opt_mimo_layer_index, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* ??? Algorithm specific Information (per Burst Type extension) */ + break; + + default: + /* do nothing */ + break; + } + + break; + + default: + /* do nothing */ + break; + } + + /* sub-burst portion */ + sub_burst_descriptor_count = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_number_of_sub_burst_descriptors, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_sub_burst_padding, tvb, offset, 3, ENC_NA); + offset += 3; + + /* sub-burst descriptors */ + for (sub_burst = 0; sub_burst < sub_burst_descriptor_count; ++sub_burst) + { + proto_tree *sub_burst_descriptor_tree; + guint sub_burst_descriptor_length; + + sub_burst_descriptor_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_wimaxmacphy_ul_sub_burst_descriptor, &item, "Sub-Burst Descriptor %u", sub_burst); + + sub_burst_descriptor_length = dissect_wimaxmacphy_ul_sub_burst_descriptor(tvb, offset, + pinfo, sub_burst_descriptor_tree); + + proto_item_set_len(item, sub_burst_descriptor_length); + + offset += sub_burst_descriptor_length; + } + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_ul_zone_descriptor(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree) +{ + guint start_offset = offset; + guint8 zone_type, burst_descriptor_count, burst; + proto_item *item; + + zone_type = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_ul_zone_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_start_symbol_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_end_symbol_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_ul_zone_permutation_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_ul_zone_use_all_subchannels_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_ul_zone_disable_pusc_subchannel_rotation, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_ul_perm_base, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_agc_range_extension, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + /* zone-specific parts */ + switch (zone_type) + { + case 0x22: /* AAS */ + { + proto_tree *subtree; + + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_ul_zone_aas, NULL, "AAS Zone Specific"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_preamble_configuration, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_preamble_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_zone_sdma_supported_indication, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_ul_zone_aas_reserved, tvb, offset, 1, ENC_NA); + offset += 1; + + /* ??? Algorithm Specific Information (per Zone Type) */ + break; + } + default: + /* do nothing */ + break; + } + + /* burst portion */ + burst_descriptor_count = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_number_of_burst_descriptors, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_burst_padding, tvb, offset, 3, ENC_NA); + offset += 3; + + /* burst descriptors */ + for (burst = 0; burst < burst_descriptor_count; ++burst) + { + proto_tree *burst_descriptor_tree; + guint burst_descriptor_length; + + burst_descriptor_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_wimaxmacphy_ul_burst_descriptor, &item, "Burst Descriptor %u", burst); + + burst_descriptor_length = dissect_wimaxmacphy_ul_burst_descriptor( + tvb, offset, pinfo, burst_descriptor_tree); + proto_item_set_len(item, burst_descriptor_length); + + offset += burst_descriptor_length; + } + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_ul_subframe_descriptor(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree) +{ + guint start_offset = offset; + guint8 zone_descriptor_count; + guint8 zone; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_subframe_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_downlink_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_phy_sap_version_number, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_subframe_allocation_start_time, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + zone_descriptor_count = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_number_of_zone_descriptors, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_zone_padding, tvb, offset, 3, ENC_NA); + offset += 3; + + /* ----------------------------------------------------------------------- + * zone descriptors + * ----------------------------------------------------------------------- + */ + + for (zone = 0; zone < zone_descriptor_count; ++zone) + { + proto_item *item; + proto_tree *zone_descriptor_tree; + guint zone_descriptor_length; + + zone_descriptor_tree = proto_tree_add_subtree_format(tree, tvb, offset, 1, ett_wimaxmacphy_ul_zone_descriptor, &item, "Zone Descriptor %u", zone); + + zone_descriptor_length = dissect_wimaxmacphy_ul_zone_descriptor( + tvb, offset, pinfo, zone_descriptor_tree); + + proto_item_set_len(item, zone_descriptor_length); + offset += zone_descriptor_length; + } + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_phy_txstart_request(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree) +{ + guint16 txvector_length; + guint subframe_descriptor_length; + + txvector_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_length_of_txvector, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + subframe_descriptor_length = dissect_wimaxmacphy_dl_subframe_descriptor( + tvb, offset, pinfo, tree); + + offset += subframe_descriptor_length; + + if (subframe_descriptor_length < txvector_length) + proto_tree_add_item(tree, hf_wimaxmacphy_unknown, tvb, offset, txvector_length - subframe_descriptor_length, ENC_NA); + + return txvector_length + 2; +} + +static guint dissect_wimaxmacphy_phy_txstart_confirmation(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_wimaxmacphy_prim_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_next_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + /* offset += 1; */ + + return 2; +} + +static guint dissect_wimaxmacphy_phy_txstart_indication(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_wimaxmacphy_prim_txstart_indication_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_extended_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_current_frame_number_lsn, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_initial_frame_number, tvb, offset, 3, ENC_BIG_ENDIAN); + /* offset += 3; */ + + return 6; +} + +static guint dissect_wimaxmacphy_phy_txsdu_request(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + guint length; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_dl_zone_number, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_sub_burst_burst_split_point, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_dl_sub_burst_burst_number, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + length = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_phy_sdu, tvb, offset, length, ENC_NA); + + return length + 2; +} + +static guint dissect_wimaxmacphy_phy_txsdu_confirmation(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_wimaxmacphy_prim_dl_zone_number, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_sub_burst_burst_split_point, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_dl_sub_burst_burst_number, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved5, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_next_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + /* offset += 1; */ + + return 6; +} + +static guint dissect_wimaxmacphy_phy_txend_indication(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_wimaxmacphy_prim_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_phy_request, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_current_frame_number_lsn, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_requested_aas_calibration_zone_size, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_requested_aas_calibration_zone_alloc, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_number_of_consecutive_frames_with_aas, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved5, tvb, offset, 2, ENC_BIG_ENDIAN); + /* offset += 2; */ + + return 6; +} + +static guint dissect_wimaxmacphy_phy_rxstart_request(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree) +{ + guint16 rxvector_length; + guint subframe_descriptor_length; + + rxvector_length = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_length_of_rxvector, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + subframe_descriptor_length = dissect_wimaxmacphy_ul_subframe_descriptor( + tvb, offset, pinfo, tree); + + offset += subframe_descriptor_length; + + /* check for unprocessed bytes */ + if (subframe_descriptor_length < rxvector_length) + proto_tree_add_item(tree, hf_wimaxmacphy_unknown, tvb, offset, rxvector_length - subframe_descriptor_length, ENC_NA); + + return rxvector_length + 2; +} + +static guint dissect_wimaxmacphy_phy_rxstart_confirmation(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_wimaxmacphy_prim_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_frame_number, tvb, offset, 1, ENC_BIG_ENDIAN); + /* offset += 1; */ + + return 2; +} + +static guint dissect_wimaxmacphy_phy_rxstart_indication(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + proto_tree_add_item(tree, hf_wimaxmacphy_prim_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_current_frame_number_lsn, tvb, offset, 1, ENC_BIG_ENDIAN); + /* offset += 1; */ + + return 2; +} + +static guint dissect_wimaxmacphy_phy_rxsdu_indication(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + guint8 indication_type; + proto_item *feedback_item; + proto_tree *subtree, *feedback_tree; + guint length, start_offset = offset; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_issid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_integrity, tvb, offset, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_number_of_bytes_received, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_rssi_per_subcarrier_level, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_cinr, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_power_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_current_frame_number_msn, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_acid_for_harq_data_bursts, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + indication_type = (tvb_get_guint8(tvb, offset) >> 4) & 0x0F; + proto_tree_add_item(tree, hf_wimaxmacphy_prim_indication_type, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_zone_permutation_type, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_update_aas_handle_in_mac, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_aas_handle, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_time_deviation, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_frequency_deviation, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + switch (indication_type) + { + case 0: /* data burst */ + { + length = tvb_reported_length_remaining(tvb, offset); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_phy_sdu, tvb, offset, length, ENC_NA); + offset += length; + break; + } + case 1: /* HARQ ACK */ + { + subtree = proto_tree_add_subtree(tree, tvb, offset, 4, ett_wimaxmacphy_prim_harq_ack, NULL, "HARQ ACK channel data format"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_harq_ack_issid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_harq_ack_acid, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_harq_ack_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_harq_ack_ack_valid, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_harq_ack_unnamed, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_harq_ack_reserved2, tvb, offset, 1, ENC_NA); + offset += 1; + break; + } + case 2: /* fast feedback */ + { + subtree = proto_tree_add_subtree(tree, tvb, offset, 8, ett_wimaxmacphy_prim_harq_ack, NULL, "Fast Feedback channel data format"); + + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_fast_issid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_fast_cqich_id, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + feedback_item = proto_tree_add_item(subtree, hf_wimaxmacphy_prim_fast_feedback_type_coding, tvb, offset, 1, ENC_BIG_ENDIAN); + feedback_tree = proto_item_add_subtree(feedback_item, ett_wimaxmacphy_prim_fast_feedback_type_coding); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_prim_fast_feedback_type_coding_bit0, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_prim_fast_feedback_type_coding_bit1, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_prim_fast_feedback_type_coding_bit2, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_prim_fast_feedback_type_coding_bit3, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_prim_fast_feedback_type_coding_bit4, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_prim_fast_feedback_type_coding_bit5, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_prim_fast_feedback_type_coding_bit6, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(feedback_tree, hf_wimaxmacphy_prim_fast_feedback_type_coding_bit7, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_fast_feedback_valid, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_fast_feedback_sub_type, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_fast_reserved, tvb, offset, 2, ENC_NA); + offset += 2; + + proto_tree_add_item(subtree, hf_wimaxmacphy_prim_fast_feedback_value, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + break; + } + default: + break; + } + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_phy_rxend_indication(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + guint start_offset = offset; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_status, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_phy_aas_report_present, tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_current_frame_number_lsn, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_number_of_affected_ss, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + do + { + /* list of ISSIDs (at least one required) */ + proto_tree_add_item(tree, hf_wimaxmacphy_prim_issid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + } + while (tvb_reported_length_remaining(tvb, offset)); + + return offset - start_offset; +} + +static guint dissect_wimaxmacphy_phy_rxcdma_indication(tvbuff_t *tvb, guint offset, packet_info *pinfo _U_, proto_tree *tree) +{ + guint start_offset = offset; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_zonexid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_cdma_code, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_cdma_symbol, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved1, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_cdma_subchannel, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_rssi_per_subcarrier_level, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_cinr, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved3, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_power_offset, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_current_frame_number_msn, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_wimaxmacphy_prim_reserved4, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_aas_handle, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_time_deviation, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + proto_tree_add_item(tree, hf_wimaxmacphy_prim_frequency_deviation, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + return offset - start_offset; +} + +static int +dissect_wimaxmacphy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) +{ + /* Set up structures needed to add the protocol subtree and manage it */ + proto_tree *wimaxmacphy_tree, *primitive_tree; + proto_item *item; + + guint offset = 0; + guint8 message_type; + + /* Ensure minimum size */ + if (tvb_reported_length(tvb) < WIMAXMACPHY_HEADER_SIZE) + return 0; + + col_set_str(pinfo->cinfo, COL_PROTOCOL, "wimaxmacphy"); + col_clear(pinfo->cinfo, COL_INFO); + + item = proto_tree_add_item(tree, proto_wimaxmacphy, tvb, 0, -1, ENC_NA); + wimaxmacphy_tree = proto_item_add_subtree(item, ett_wimaxmacphy); + + proto_tree_add_item(wimaxmacphy_tree, hf_wimaxmacphy_hdr_phy_entity_id, + tvb, offset, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(wimaxmacphy_tree, hf_wimaxmacphy_hdr_message_segmentation, + tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + message_type = tvb_get_guint8(tvb, offset); + item = proto_tree_add_item(wimaxmacphy_tree, hf_wimaxmacphy_hdr_message_type, + tvb, offset, 1, ENC_BIG_ENDIAN); + + primitive_tree = proto_item_add_subtree(item, ett_wimaxmacphy_primitive); +#if 0 + col_add_str(pinfo->cinfo, COL_INFO, val_to_str_ext_const(message_type, &wimaxmacphy_message_type_vals_ext, "Unknown")); +#endif + col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(message_type, wimaxmacphy_message_type_vals, "Unknown")); + offset += 1; + + switch(message_type) + { + case WIMAXMACPHY_PHY_TXSTART_REQUEST: + offset += dissect_wimaxmacphy_phy_txstart_request( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_TXSTART_CONFIRMATION: + offset += dissect_wimaxmacphy_phy_txstart_confirmation( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_TXSTART_INDICATION: + offset += dissect_wimaxmacphy_phy_txstart_indication( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_TXSDU_REQUEST: + offset += dissect_wimaxmacphy_phy_txsdu_request( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_TXSDU_CONFIRMATION: + offset += dissect_wimaxmacphy_phy_txsdu_confirmation( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_TXEND_INDICATION: + offset += dissect_wimaxmacphy_phy_txend_indication( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_RXSTART_REQUEST: + offset += dissect_wimaxmacphy_phy_rxstart_request( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_RXSTART_CONFIRMATION: + offset += dissect_wimaxmacphy_phy_rxstart_confirmation( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_RXSTART_INDICATION: + offset += dissect_wimaxmacphy_phy_rxstart_indication( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_RXSDU_INDICATION: + offset += dissect_wimaxmacphy_phy_rxsdu_indication( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_RXEND_INDICATION: + offset += dissect_wimaxmacphy_phy_rxend_indication( + tvb, offset, pinfo, primitive_tree); + break; + case WIMAXMACPHY_PHY_RXCDMA_INDICATION: + offset += dissect_wimaxmacphy_phy_rxcdma_indication( + tvb, offset, pinfo, primitive_tree); + break; + default: + proto_tree_add_item(primitive_tree, hf_wimaxmacphy_unknown, + tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); + offset += tvb_reported_length_remaining(tvb, offset); + break; + } + + if (tvb_reported_length_remaining(tvb, offset) > 0) + { + /* Incorporate any "extra" bytes */ + item = proto_tree_add_item(wimaxmacphy_tree, hf_wimaxmacphy_unknown, + tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); + + expert_add_info(pinfo, item, &ei_wimaxmacphy_unknown); + } + + return tvb_captured_length(tvb); +} + +void +proto_register_wimaxmacphy(void) +{ + static hf_register_info hf[] = { + { + &hf_wimaxmacphy_hdr_phy_entity_id, + { + "PHY entity ID", + "wimaxmacphy.hdr_phy_entity_id", + FT_UINT8, + BASE_DEC, + NULL, + 0xfc, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_hdr_message_segmentation, + { + "Message Segmentation", + "wimaxmacphy.hdr_message_segmentation", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_message_segmentation_vals), + 0x03, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_hdr_message_type, + { + "Message Type", + "wimaxmacphy.hdr_message_type", + FT_UINT8, +#if 0 + BASE_HEX | BASE_EXT_STRING, + &wimaxmacphy_message_type_vals_ext, +#endif + BASE_HEX, + VALS(wimaxmacphy_message_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_unknown, + { + "Unknown(!)", + "wimaxmacphy.unknown_primitive", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_length_of_txvector, + { + "Length of TXVECTOR", + "wimaxmacphy.prim_length_of_txvector", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_length_of_rxvector, + { + "Length of RXVECTOR", + "wimaxmacphy.prim_length_of_rxvector", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_status, + { + "Status", + "wimaxmacphy.prim_status", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_prim_status_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_txstart_indication_status, + { + "Status", + "wimaxmacphy.prim_status", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_prim_txstart_indication_status_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_reserved1, + { + "Reserved", + "wimaxmacphy.prim_reserved1", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_reserved2, + { + "Reserved", + "wimaxmacphy.prim_reserved2", + FT_UINT8, + BASE_HEX, + NULL, + 0xF0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_reserved3, + { + "Reserved", + "wimaxmacphy.prim_reserved3", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_reserved4, + { + "Reserved", + "wimaxmacphy.prim_reserved4", + FT_UINT16, + BASE_HEX, + NULL, + 0x0FFF, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_reserved5, + { + "Reserved", + "wimaxmacphy.prim_reserved5", + FT_UINT16, + BASE_HEX, + NULL, + 0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_next_frame_number, + { + "Next Frame Number (lsb)", + "wimaxmacphy.prim_next_frame_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_extended_frame_number, + { + "Extended frame number", + "wimaxmacphy.prim_extended_frame_number", + FT_UINT8, + BASE_DEC, + NULL, + 0xf0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_current_frame_number_lsn, + { + "Current Frame Number (lsb)", + "wimaxmacphy.prim_current_frame_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0f, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_initial_frame_number, + { + "Initial Frame Number (from PHY)", + "wimaxmacphy.prim_initial_frame_number", + FT_UINT24, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_dl_zone_number, + { + "DL zone number", + "wimaxmacphy.prim_dl_zone_number", + FT_UINT16, + BASE_DEC, + NULL, + 0xe000, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_sub_burst_burst_split_point, + { + "Sub-burst/burst split point", + "wimaxmacphy.prim_sub_burst_burst_split_point", + FT_UINT16, + BASE_DEC, + NULL, + 0x1c00, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_dl_sub_burst_burst_number, + { + "DL sub-burst/burst number in this zone", + "wimaxmacphy.prim_dl_sub_burst_burst_number", + FT_UINT16, + BASE_DEC, + NULL, + 0x03ff, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_phy_sdu, + { + "PHY SDU", + "wimaxmacphy.prim_phy_sdu", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_phy_request, + { + "PHY request (LW 1)", + "wimaxmacphy.prim_phy_request", + FT_UINT8, + BASE_HEX, + NULL, + 0xf0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_requested_aas_calibration_zone_size, + { + "Requested AAS Calibration Zone size", + "wimaxmacphy.prim_requested_aas_calibration_zone_size", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_requested_aas_calibration_zone_alloc, + { + "Requested AAS Calibration Zone allocation deadline", + "wimaxmacphy.prim_requested_aas_calibration_zone_alloc", + FT_UINT8, + BASE_DEC, + NULL, + 0xf0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_number_of_consecutive_frames_with_aas, + { + "Number of consecutive frames with AAS Calibration Zone allocation", + "wimaxmacphy.prim_number_of_consecutive_frames_with_aas", + FT_UINT8, + BASE_DEC, + NULL, + 0x0f, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_frame_number, + { + "Frame Number (lsb)", + "wimaxmacphy.prim_frame_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0f, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_issid, + { + "ISSID", + "wimaxmacphy.prim_issid", + FT_INT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_integrity, + { + "Integrity", + "wimaxmacphy.prim_integrity", + FT_UINT32, + BASE_DEC, + VALS(wimaxmacphy_prim_integrity_vals), + 0x80000000, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_number_of_bytes_received, + { + "Number of bytes received", + "wimaxmacphy.prim_number_of_bytes_received", + FT_UINT32, + BASE_DEC, + NULL, + 0x7fffffff, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_rssi_per_subcarrier_level, + { + "RSSI per subcarrier level", + "wimaxmacphy.prim_rssi_per_subcarrier_level", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_cinr, + { + "CINR", + "wimaxmacphy.prim_cinr", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_power_offset, + { + "Power Offset", + "wimaxmacphy.prim_power_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_current_frame_number_msn, + { + "Current Frame Number (lsb)", + "wimaxmacphy.prim_current_frame_number", + FT_UINT16, + BASE_DEC, + NULL, + 0x00f0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_acid_for_harq_data_bursts, + { + "ACID for HARQ data bursts", + "wimaxmacphy.prim_acid_for_harq_data_bursts", + FT_UINT16, + BASE_DEC, + NULL, + 0x000f, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_indication_type, + { + "Indication Type", + "wimaxmacphy.prim_indication_type", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_prim_indication_type_vals), + 0xf0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_zone_permutation_type, + { + "Zone Permutation Type", + "wimaxmacphy.prim_zone_permutation_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_prim_zone_permutation_type_vals), + 0x0e, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_update_aas_handle_in_mac, + { + "Update AAS handle in MAC", + "wimaxmacphy.prim_update_aas_handle_in_mac", + FT_UINT8, + BASE_HEX, + NULL, + 0x1, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_aas_handle, + { + "AAS Handle", + "wimaxmacphy.prim_aas_handle", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_time_deviation, + { + "Time deviation in units of 1/Fs", + "wimaxmacphy.prim_time_deviation", + FT_INT32, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_frequency_deviation, + { + "Frequency deviation in Hz", + "wimaxmacphy.prim_frequency_deviation", + FT_INT32, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_harq_ack_issid, + { + "ISSID", + "wimaxmacphy.prim_harq_ack_issid", + FT_INT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_harq_ack_acid, + { + "ACID", + "wimaxmacphy.prim_harq_ack_acid", + FT_UINT8, + BASE_DEC, + NULL, + 0xf0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_harq_ack_reserved1, + { + "Reserved", + "wimaxmacphy.prim_harq_ack_reserved1", + FT_UINT8, + BASE_HEX, + NULL, + 0x0c, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_harq_ack_ack_valid, + { + "ACK Valid", + "wimaxmacphy.prim_harq_ack_ack_valid", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_prim_harq_ack_ack_valid_vals), + 0x2, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_harq_ack_unnamed, + { + "Unnamed", + "wimaxmacphy.prim_harq_ack_unnamed", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_prim_harq_ack_unnamed_vals), + 0x1, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_harq_ack_reserved2, + { + "Reserved", + "wimaxmacphy.prim_harq_ack_reserved2", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_issid, + { + "ISSID", + "wimaxmacphy.prim_fast_issid", + FT_INT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_cqich_id, + { + "CQICH_ID", + "wimaxmacphy.prim_fast_cqich_id", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding, + { + "Feedback type coding", + "wimaxmacphy.prim_fast_type_coding", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding_bit0, + { + "3 bit-MIMO Fast-feedback", + "wimaxmacphy.prim_fast_type_coding.bit0", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x01, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding_bit1, + { + "Enhanced FAST_FEEDBACK", + "wimaxmacphy.prim_fast_type_coding.bit1", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x02, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding_bit2, + { + "Reserved", + "wimaxmacphy.prim_fast_type_coding.bit2", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x04, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding_bit3, + { + "Reserved", + "wimaxmacphy.prim_fast_type_coding.bit3", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x08, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding_bit4, + { + "UEP fast-feedback", + "wimaxmacphy.prim_fast_type_coding.bit4", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x10, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding_bit5, + { + "A measurement report performed on the last DL burst", + "wimaxmacphy.prim_fast_type_coding.bit5", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x20, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding_bit6, + { + "Primary/Secondary FAST_FEEDBACK", + "wimaxmacphy.prim_fast_type_coding.bit6", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x40, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_type_coding_bit7, + { + "DIUC-CQI Fast-feedback", + "wimaxmacphy.prim_fast_type_coding.bit7", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x80, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_valid, + { + "Feedback Valid", + "wimaxmacphy.prim_fast_feedback_valid", + FT_UINT16, + BASE_DEC, + VALS(wimaxmacphy_prim_fast_feedback_valid_vals), + 0x8000, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_sub_type, + { + "Feedback sub-type", + "wimaxmacphy.prim_fast_feedback_sub_type", + FT_UINT16, + BASE_DEC, + VALS(wimaxmacphy_prim_fast_feedback_sub_type_vals), + 0x7000, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_reserved, + { + "Reserved", + "wimaxmacphy.prim_fast_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_fast_feedback_value, + { + "Feedback value", + "wimaxmacphy.prim_fast_feedback_value", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_phy_aas_report_present, + { + "PHY AAS report present", + "wimaxmacphy.prim_phy_aas_report_present", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_prim_phy_aas_report_present_vals), + 0xf0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_number_of_affected_ss, + { + "Number of affected SS", + "wimaxmacphy.prim_number_of_affected_ss", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_zonexid, + { + "ZoneXID", + "wimaxmacphy.prim_zonexid", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_cdma_code, + { + "CDMA code", + "wimaxmacphy.prim_cdma_code", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_cdma_symbol, + { + "CDMA symbol", + "wimaxmacphy.prim_cdma_symbol", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_prim_cdma_subchannel, + { + "CDMA subchannel", + "wimaxmacphy.prim_cdma_subchannel", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_subframe_subframe_type, + { + "Subframe Type", + "wimaxmacphy.subframe_subframe_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_subframe_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_subframe_frame_number, + { + "Frame Number", + "wimaxmacphy.subframe_frame_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_subframe_downlink_reserved1, + { + "Reserved", + "wimaxmacphy.subframe_downlink_reserved1", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_subframe_phy_sap_version_number, + { + "PHY SAP version number", + "wimaxmacphy.subframe_phy_sap_version_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_subframe_downlink_reserved2, + { + "Downlink reserved", + "wimaxmacphy.subframe_downlink_reserved2", + FT_UINT32, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_subframe_allocation_start_time, + { + "Allocation start time", + "wimaxmacphy.subframe_allocation_start_time", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_number_of_zone_descriptors, + { + "Number of Zone Descriptors", + "wimaxmacphy.number_of_zone_descriptors", + FT_UINT24, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_padding, + { + "Padding", + "wimaxmacphy.zone_padding", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_zone_type, + { + "Zone Type", + "wimaxmacphy.zone_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_dl_zone_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_zone_type, + { + "Zone Type", + "wimaxmacphy.zone_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_ul_zone_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_number, + { + "Zone Number", + "wimaxmacphy.zone_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_start_symbol_offset, + { + "Start Symbol Offset", + "wimaxmacphy.zone_start_symbol_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_end_symbol_offset, + { + "End Symbol Offset", + "wimaxmacphy.zone_end_symbol_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_zone_permutation_type, + { + "Permutation Type", + "wimaxmacphy.zone_permutation_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_dl_zone_permutation_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_zone_permutation_type, + { + "Permutation Type", + "wimaxmacphy.zone_permutation_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_ul_zone_permutation_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_zone_use_all_subchannels_indicator, + { + "Use all subchannels indicator", + "wimaxmacphy.zone_use_all_subchannels_indicator", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_zone_use_all_subchannels_indicator_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_zone_use_all_subchannels_indicator, + { + "Use all subchannels indicator", + "wimaxmacphy.zone_use_all_subchannels_indicator", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_zone_use_all_subchannels_indicator_vals), + 0xf0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_zone_disable_pusc_subchannel_rotation, + { + "Disable PUSC subchannel rotation", + "wimaxmacphy.zone_disable_pusc_subchannel_rotation", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_zone_disable_pusc_subchannel_rotation_vals), + 0x0f, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_dl_perm_base, + { + "DL_PermBase", + "wimaxmacphy.zone_dl_perm_base", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_ul_perm_base, + { + "UL_PermBase", + "wimaxmacphy.zone_ul_perm_base", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_prbs_id, + { + "PRBS_ID", + "wimaxmacphy.zone_prbs_id", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_dedicated_pilots, + { + "Dedicated pilots", + "wimaxmacphy.zone_dedicated_pilots", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_zone_dedicated_pilots_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_agc_range_extension, + { + "Rx AGC range extension", + "wimaxmacphy.zone_agc_range_extension", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_zone_agc_range_extension_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_reserved, + { + "Reserved", + "wimaxmacphy.zone_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_stc_type, + { + "STC type", + "wimaxmacphy.zone_stc_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_zone_stc_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_matrix_indicator, + { + "Matrix Indicator", + "wimaxmacphy.zone_matrix_indicator", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_matrix_indicator_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_midamble_presence, + { + "Midamble presence", + "wimaxmacphy.zone_midamble_presence", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_zone_midamble_presence_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_midamble_boosting, + { + "Midamble boosting", + "wimaxmacphy.zone_midamble_boosting", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_zone_midamble_boosting_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_preamble_configuration, + { + "Preamble configuration", + "wimaxmacphy.zone_preamble_configuration", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_zone_preamble_configuration_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_sdma_supported_indication, + { + "SDMA supported indication", + "wimaxmacphy.zone_sdma_supported_indication", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_zone_sdma_supported_indication_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_zone_preamble_type, + { + "Preamble type", + "wimaxmacphy.zone_preamble_type", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_zone_preamble_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_zone_aas_reserved, + { + "Reserved", + "wimaxmacphy.zone_aas_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_zone_aas_reserved, + { + "Reserved", + "wimaxmacphy.zone_aas_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_number_of_burst_descriptors, + { + "Number of Burst Descriptors", + "wimaxmacphy.number_of_burst_descriptors", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_padding, + { + "Padding", + "wimaxmacphy.burst_padding", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_burst_type, + { + "Burst Type", + "wimaxmacphy.burst_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_dl_burst_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_type, + { + "Burst Type", + "wimaxmacphy.dl_burst_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_ul_burst_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_type_extension, + { + "Burst Type extension", + "wimaxmacphy.burst_type_extension", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_burst_type_extension_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_number, + { + "Burst Number", + "wimaxmacphy.burst_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_modulation_fec_code_type, + { + "Modulation/FEC Code Type", + "wimaxmacphy.burst_modulation_fec_code_type", + FT_UINT8, +#if 0 + BASE_DEC | BASE_EXT_STRING, + &wimaxmacphy_modulation_fec_code_type_vals_ext, +#endif + BASE_DEC, + VALS(wimaxmacphy_modulation_fec_code_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_data_length, + { + "Burst Data Length", + "wimaxmacphy.burst_data_length", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_ofdma_symbol_offset, + { + "OFDMA Symbol offset", + "wimaxmacphy.burst_ofdma_symbol_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_subchannel_offset, + { + "Subchannel offset", + "wimaxmacphy.burst_subchannel_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_boosting, + { + "Boosting", + "wimaxmacphy.burst_boosting", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_burst_boosting_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_reserved, + { + "Reserved", + "wimaxmacphy.burst_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_repetition_coding_indication, + { + "Repetition coding indication", + "wimaxmacphy.burst_repetition_coding_indication", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_burst_repetition_coding_indication_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_issid, + { + "ISSID", + "wimaxmacphy.burst_issid", + FT_INT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_aas_handle, + { + "AAS Handle", + "wimaxmacphy.burst_aas_handle", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_burst_map_number_of_slots, + { + "Number of slots (duration) after repetition code is applied", + "wimaxmacphy.burst_map_number_of_slots", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_burst_map_reserved, + { + "Reserved", + "wimaxmacphy.burst_map_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_burst_normal_number_of_symbols, + { + "Number of Symbols", + "wimaxmacphy.burst_normal_number_of_symbols", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_burst_normal_number_of_subchannels, + { + "Number of Subchannels", + "wimaxmacphy.burst_normal_number_of_subchannels", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_burst_normal_aas_handle, + { + "AAS Handle", + "wimaxmacphy.burst_normal_aas_handle", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_normal_number_of_slots, + { + "Number of slots", + "wimaxmacphy.burst_normal_number_of_slots", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_normal_reserved, + { + "Reserved", + "wimaxmacphy.burst_normal_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_papr_number_of_symbols, + { + "Number of Symbols", + "wimaxmacphy.burst_papr_number_of_symbols", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_papr_number_of_subchannels, + { + "Number of Subchannels", + "wimaxmacphy.burst_papr_number_of_subchannels", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_papr_reserved, + { + "Reserved", + "wimaxmacphy.burst_papr_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_papr_unnamed, + { + "Unnamed", + "wimaxmacphy.burst_papr_unnamed", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_papr_unnamed_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_harq_ack_number_of_symbols, + { + "Number of Symbols", + "wimaxmacphy.burst_harq_ack_number_of_symbols", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_harq_ack_number_of_subchannels, + { + "Number of Subchannels", + "wimaxmacphy.burst_harq_ack_number_of_subchannels", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_harq_ack_reserved, + { + "Reserved", + "wimaxmacphy.burst_harq_ack_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_fast_number_of_symbols, + { + "Number of Symbols", + "wimaxmacphy.burst_fast_number_of_symbols", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_fast_number_of_subchannels, + { + "Number of Subchannels", + "wimaxmacphy.burst_fast_number_of_subchannels", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_fast_reserved, + { + "Reserved", + "wimaxmacphy.burst_fast_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_initial_number_of_symbols, + { + "Number of Symbols", + "wimaxmacphy.burst_initial_number_of_symbols", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_initial_number_of_subchannels, + { + "Number of Subchannels", + "wimaxmacphy.burst_initial_number_of_subchannels", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_initial_ranging_method, + { + "Ranging method", + "wimaxmacphy.burst_initial_ranging_method", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_ranging_method_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_initial_reserved1, + { + "Reserved", + "wimaxmacphy.burst_initial_reserved1", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_initial_zone_xid, + { + "Zone XID", + "wimaxmacphy.burst_initial_zone_xid", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_initial_reserved2, + { + "Reserved", + "wimaxmacphy.burst_initial_reserved2", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_periodic_number_of_symbols, + { + "Number of Symbols", + "wimaxmacphy.burst_periodic_number_of_symbols", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_periodic_number_of_subchannels, + { + "Number of Subchannels", + "wimaxmacphy.burst_periodic_number_of_subchannels", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_periodic_ranging_method, + { + "Ranging method", + "wimaxmacphy.burst_periodic_ranging_method", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_ranging_method_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_periodic_reserved1, + { + "Reserved", + "wimaxmacphy.burst_periodic_reserved1", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_periodic_zone_xid, + { + "Zone XID", + "wimaxmacphy.burst_periodic_zone_xid", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_periodic_reserved2, + { + "Reserved", + "wimaxmacphy.burst_periodic_reserved2", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_noise_number_of_symbols, + { + "Number of Symbols", + "wimaxmacphy.burst_noise_number_of_symbols", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_noise_number_of_subchannels, + { + "Number of Subchannels", + "wimaxmacphy.burst_noise_number_of_subchannels", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_noise_reserved, + { + "Reserved", + "wimaxmacphy.burst_noise_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_sounding_number_of_symbols, + { + "Number of Symbols", + "wimaxmacphy.burst_sounding_number_of_symbols", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_sounding_number_of_subchannels, + { + "Number of Subchannels", + "wimaxmacphy.burst_sounding_number_of_subchannels", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_sounding_type, + { + "Sounding type", + "wimaxmacphy.burst_sounding_type", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_sounding_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_sounding_separability_type, + { + "Separability type", + "wimaxmacphy.burst_sounding_separability_type", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_sounding_separability_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_sounding_max_cyclic_shift_indx, + { + "Max Cyclic Shift Indx", + "wimaxmacphy.burst_sounding_max_cyclic_shift_indx", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_sounding_max_cyclic_shift_indx_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_sounding_decimation_value, + { + "Decimation value", + "wimaxmacphy.burst_sounding_decimation_value", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_sounding_decimation_offset_rand, + { + "Decimation offset randomization", + "wimaxmacphy.burst_sounding_decimation_offset_rand", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_sounding_decimation_offset_rand_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_sounding_reserved, + { + "Reserved", + "wimaxmacphy.burst_sounding_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_opt_aas_preamble_modifier_type, + { + "Preamble Modifier Type", + "wimaxmacphy.burst_opt_aas_preamble_modifier_type", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_opt_aas_preamble_shift_index, + { + "Preamble Shift index", + "wimaxmacphy.burst_opt_aas_preamble_shift_index", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_opt_aas_reserved, + { + "Reserved", + "wimaxmacphy.burst_opt_aas_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_opt_mimo_matrix_indicator, + { + "Matrix indicator", + "wimaxmacphy.burst_opt_mimo_matrix_indicator", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_matrix_indicator_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_burst_opt_mimo_layer_index, + { + "Layer index", + "wimaxmacphy.burst_opt_mimo_layer_index", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_burst_opt_mimo_reserved, + { + "Reserved", + "wimaxmacphy.burst_opt_mimo_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_opt_mimo_matrix_indicator, + { + "Matrix indicator (dual antenna SS)", + "wimaxmacphy.burst_opt_mimo_matrix_indicator", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_ul_burst_opt_mimo_matrix_indicator_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns, + { + "Pilot patterns", + "wimaxmacphy.burst_opt_mimo_pilot_patterns", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit0, + { + "Pattern A", + "wimaxmacphy.burst_opt_mimo_pilot_patterns.A", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x01, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit1, + { + "Pattern B", + "wimaxmacphy.burst_opt_mimo_pilot_patterns.B", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x02, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit2, + { + "Pattern C", + "wimaxmacphy.burst_opt_mimo_pilot_patterns.C", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x04, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_opt_mimo_pilot_patterns_bit3, + { + "Pattern D", + "wimaxmacphy.burst_opt_mimo_pilot_patterns.D", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x08, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_opt_mimo_collaborative, + { + "Collaborative MIMO control", + "wimaxmacphy.burst_opt_mimo_collaborative", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_opt_mimo_collaborative_vals), + 0xf0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_burst_opt_mimo_antenna_unnamed, + { + "Antenna(?)", + "wimaxmacphy.burst_opt_mimo_antenna_unnamed", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_burst_opt_mimo_antenna_unnamed_vals), + 0x0f, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_number_of_sub_burst_descriptors, + { + "Number of Sub-Burst Descriptors", + "wimaxmacphy.number_of_sub_burst_descriptors", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_padding, + { + "Padding", + "wimaxmacphy.sub_burst_padding", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_dl_sub_burst_type, + { + "Sub-Burst Type", + "wimaxmacphy.sub_burst_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_dl_sub_burst_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_type, + { + "Sub-Burst Type", + "wimaxmacphy.sub_burst_type", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_ul_sub_burst_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_number, + { + "Sub-Burst number", + "wimaxmacphy.sub_burst_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_symbol_offset, + { + "Symbol Offset", + "wimaxmacphy.sub_burst_symbol_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_subchannel_offset, + { + "Subchannel Offset", + "wimaxmacphy.sub_burst_subchannel_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_number_of_slots, + { + "Number of slots in this sub-burst", + "wimaxmacphy.sub_burst_number_of_slots", + FT_UINT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_reserved1, + { + "Reserved", + "wimaxmacphy.sub_burst_reserved1", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_reserved2, + { + "Reserved", + "wimaxmacphy.sub_burst_reserved2", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_modulation_fec_code_type, + { + "Modulation/FEC Code Type", + "wimaxmacphy.sub_burst_modulation_fec_code_type", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_modulation_fec_code_type_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_issid, + { + "ISSID", + "wimaxmacphy.sub_burst_issid", + FT_INT16, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_aas_handle, + { + "AAS Handle", + "wimaxmacphy.sub_burst_aas_handle", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_boosting, + { + "Boosting", + "wimaxmacphy.sub_burst_boosting", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_burst_boosting_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_repetition_coding_indication, + { + "Repetition coding indication", + "wimaxmacphy.sub_burst_repetition_coding_indication", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_burst_repetition_coding_indication_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_data_length, + { + "Sub-Burst Data Length", + "wimaxmacphy.sub_burst_data_length", + FT_UINT32, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_harq_chase_harq_channel_id, + { + "HARQ channel id (ACID)", + "wimaxmacphy.sub_burst_harq_chase_harq_channel_id", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_harq_chase_harq_sequence_number, + { + "HARQ sequence number (AI_SN)", + "wimaxmacphy.sub_burst_harq_chase_harq_sequence_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_harq_chase_flush_unnamed, + { + "Flush(?)", + "wimaxmacphy.sub_burst_harq_chase_flush_unnamed", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_sub_burst_flush_unnamed_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_harq_chase_reserved, + { + "Reserved", + "wimaxmacphy.sub_burst_harq_chase_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_mimo_chase_harq_channel_id, + { + "HARQ channel id (ACID)", + "wimaxmacphy.sub_burst_mimo_chase_harq_channel_id", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_mimo_chase_harq_sequence_number, + { + "HARQ sequence number (AI_SN)", + "wimaxmacphy.sub_burst_mimo_chase_harq_sequence_number", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_mimo_chase_flush_unnamed, + { + "Flush(?)", + "wimaxmacphy.sub_burst_mimo_chase_flush_unnamed", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_sub_burst_flush_unnamed_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_sub_burst_mimo_chase_layer_index, + { + "Layer index", + "wimaxmacphy.sub_burst_mimo_chase_layer_index", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_ctype, + { + "CType", + "wimaxmacphy.sub_burst_ctype", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_ul_sub_burst_ctype_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_mini_subchannel_index, + { + "Mini-subchannel Index", + "wimaxmacphy.sub_burst_mini_subchannel_index", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_mini_reserved, + { + "Reserved", + "wimaxmacphy.sub_burst_mini_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding, + { + "Feedback type coding", + "wimaxmacphy.sub_burst_feedback_type_coding", + FT_UINT8, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit0, + { + "3 bit-MIMO Fast-feedback", + "wimaxmacphy.sub_burst_feedback_type_coding.bit0", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x01, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit1, + { + "Enhanced FAST_FEEDBACK", + "wimaxmacphy.sub_burst_feedback_type_coding.bit1", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x02, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit2, + { + "Reserved", + "wimaxmacphy.sub_burst_feedback_type_coding.bit2", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x04, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit3, + { + "Reserved", + "wimaxmacphy.sub_burst_feedback_type_coding.bit3", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x08, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit4, + { + "UEP fast-feedback", + "wimaxmacphy.sub_burst_feedback_type_coding.bit4", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x10, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit5, + { + "A measurement report performed on the last DL burst", + "wimaxmacphy.sub_burst_feedback_type_coding.bit5", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x20, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit6, + { + "Primary/Secondary FAST_FEEDBACK", + "wimaxmacphy.sub_burst_feedback_type_coding.bit6", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x40, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_type_coding_bit7, + { + "DIUC-CQI Fast-feedback", + "wimaxmacphy.sub_burst_feedback_type_coding.bit7", + FT_BOOLEAN, + 8, + TFS(&set_notset), + 0x80, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_reserved1, + { + "Reserved", + "wimaxmacphy.sub_burst_feedback_reserved1", + FT_UINT16, + BASE_DEC, + NULL, + 0x8000, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_sub_type, + { + "Feedback sub-type", + "wimaxmacphy.sub_burst_feedback_sub_type", + FT_UINT16, + BASE_DEC, + NULL, + 0x7000, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_cqich_id, + { + "CQICH_ID", + "wimaxmacphy.sub_burst_feedback_cqich_id", + FT_UINT16, + BASE_DEC, + NULL, + 0x0fff, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_reserved2, + { + "Reserved", + "wimaxmacphy.sub_burst_feedback_reserved2", + FT_UINT8, + BASE_DEC, + NULL, + 0xc0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_feedback_slot_offset, + { + "Slot offset", + "wimaxmacphy.sub_burst_feedback_slot_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x3f, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_harq_ack_acid, + { + "ACID", + "wimaxmacphy.sub_burst_harq_ack_acid", + FT_UINT32, + BASE_DEC, + NULL, + 0x000000f0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_harq_ack_reserved, + { + "Reserved", + "wimaxmacphy.sub_burst_harq_ack_reserved", + FT_UINT32, + BASE_HEX, + NULL, + 0x00000fff, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_symbol_index, + { + "Sounding symbol index within Sounding zone", + "wimaxmacphy.sub_burst_sounding_symbol_index", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_power_assignment, + { + "Power assignment method", + "wimaxmacphy.sub_burst_sounding_power_assignment_method", + FT_UINT8, + BASE_HEX, + VALS(wimaxmacphy_ul_sub_burst_sounding_power_assignment_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_power_boost, + { + "Power boost", + "wimaxmacphy.sub_burst_sounding_power_boost", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_sub_burst_sounding_power_boost_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_allocation_mode, + { + "Allocation mode", + "wimaxmacphy.sub_burst_sounding_allocation_mode", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_sub_burst_sounding_allocation_mode_vals), + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_start_freq_band, + { + "Start frequency band", + "wimaxmacphy.sub_burst_sounding_start_freq_band", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_num_freq_bands, + { + "Number of frequency bands", + "wimaxmacphy.ub_burst_sounding_num_freq_bands", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_band_bit_map, + { + "Band bit map", + "wimaxmacphy.sub_burst_sounding_band_bit_map", + FT_UINT16, + BASE_HEX, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_cyclic_time_shift, + { + "Cyclic time shift index", + "wimaxmacphy.sub_burst_sounding_cyclic_time_shift_index", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_decimation_offset, + { + "Decimation offset", + "wimaxmacphy.sub_burst_sounding_decimation_offset", + FT_UINT8, + BASE_DEC, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_sounding_reserved, + { + "Reserved", + "wimaxmacphy.sub_burst_sounding_reserved", + FT_BYTES, + BASE_NONE, + NULL, + 0x0, + NULL, + HFILL + } + }, + { + &hf_wimaxmacphy_ul_sub_burst_mimo_chase_matrix, + { + "Matrix (dual antenna SS)", + "wimaxmacphy.sub_burst_mimo_chase_matrix", + FT_UINT8, + BASE_DEC, + VALS(wimaxmacphy_ul_sub_burst_mimo_chase_matrix_vals), + 0x0, + NULL, + HFILL + } + } + }; + + /* Protocol subtree array */ + static gint *ett[] = { + &ett_wimaxmacphy, + &ett_wimaxmacphy_primitive, + &ett_wimaxmacphy_prim_harq_ack, + &ett_wimaxmacphy_prim_fast_feedback, + &ett_wimaxmacphy_prim_fast_feedback_type_coding, + &ett_wimaxmacphy_dl_zone_descriptor, + &ett_wimaxmacphy_dl_zone_stc, + &ett_wimaxmacphy_dl_zone_aas, + &ett_wimaxmacphy_dl_burst_descriptor, + &ett_wimaxmacphy_dl_burst_map, + &ett_wimaxmacphy_dl_burst_normal, + &ett_wimaxmacphy_dl_burst_papr, + &ett_wimaxmacphy_dl_burst_opt_aas, + &ett_wimaxmacphy_dl_burst_opt_mimo, + &ett_wimaxmacphy_dl_sub_burst_descriptor, + &ett_wimaxmacphy_dl_sub_burst_harq_chase, + &ett_wimaxmacphy_dl_sub_burst_mimo_chase, + &ett_wimaxmacphy_ul_zone_descriptor, + &ett_wimaxmacphy_ul_zone_aas, + &ett_wimaxmacphy_ul_burst_descriptor, + &ett_wimaxmacphy_ul_burst_harq_ack, + &ett_wimaxmacphy_ul_burst_fast_feedback, + &ett_wimaxmacphy_ul_burst_initial_ranging, + &ett_wimaxmacphy_ul_burst_periodic_ranging, + &ett_wimaxmacphy_ul_burst_papr_safety_zone, + &ett_wimaxmacphy_ul_burst_sounding_zone, + &ett_wimaxmacphy_ul_burst_noise_floor, + &ett_wimaxmacphy_ul_burst_normal_data, + &ett_wimaxmacphy_ul_burst_opt_aas, + &ett_wimaxmacphy_ul_burst_opt_mimo, + &ett_wimaxmacphy_ul_sub_burst_descriptor, + &ett_wimaxmacphy_ul_sub_burst_mini_subchannel, + &ett_wimaxmacphy_ul_sub_burst_fast_feedback, + &ett_wimaxmacphy_ul_sub_burst_harq_ack, + &ett_wimaxmacphy_ul_sub_burst_sounding_signal, + &ett_wimaxmacphy_ul_sub_burst_harq_chase, + &ett_wimaxmacphy_ul_sub_burst_mimo_chase, + &ett_wimaxmacphy_ul_pilot_patterns, + &ett_wimaxmacphy_ul_feedback_type_coding, + &ett_wimaxmacphy_ul_sub_burst_sub_allocation_specific + }; + + static ei_register_info ei[] = { + { &ei_wimaxmacphy_unknown, { "wimaxmacphy.unexpected_bytes", PI_MALFORMED, PI_ERROR, "Unexpected bytes", EXPFILL }}, + }; + + expert_module_t* expert_wimaxmacphy; + + /* Register the protocol name and description */ + proto_wimaxmacphy = proto_register_protocol("WiMAX MAC-PHY over Ethernet", "WiMAX MAC-PHY", "wimaxmacphy"); + wimaxmacphy_handle = register_dissector("wimaxmacphy", dissect_wimaxmacphy, proto_wimaxmacphy); + + /* Required function calls to register the header fields and subtrees + * used */ + proto_register_field_array(proto_wimaxmacphy, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + expert_wimaxmacphy = expert_register_protocol(proto_wimaxmacphy); + expert_register_field_array(expert_wimaxmacphy, ei, array_length(ei)); +} + +void +proto_reg_handoff_wimaxmacphy(void) +{ + dissector_add_for_decode_as_with_preference("udp.port", wimaxmacphy_handle); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/plugins/epan/wimaxmacphy/packet-wimaxmacphy.h b/plugins/epan/wimaxmacphy/packet-wimaxmacphy.h new file mode 100644 index 00000000..5259fe6b --- /dev/null +++ b/plugins/epan/wimaxmacphy/packet-wimaxmacphy.h @@ -0,0 +1,18 @@ +/* + * Routines for wimaxmacphy (WiMAX MAX SHY over Ethernet) packet dissection + * Copyright 2008, Mobile Metrics - http://mobilemetrics.net/ + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef __PACKET_WIMAXASNCP_H__ +#define __PACKET_WIMAXASNCP_H__ + +void proto_register_wimaxmacphy (void); +void proto_reg_handoff_wimaxmacphy(void); + +#endif /* __PACKET_WIMAXASNCP_H__ */ diff --git a/plugins/plugin.rc.in b/plugins/plugin.rc.in new file mode 100644 index 00000000..368c6f47 --- /dev/null +++ b/plugins/plugin.rc.in @@ -0,0 +1,35 @@ +#include "winver.h" +#pragma code_page(65001) + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @RC_MODULE_VERSION@ + PRODUCTVERSION @RC_VERSION@ + FILEFLAGSMASK 0x0L +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0 +#endif + FILEOS VOS_NT_WINDOWS32 + FILETYPE VFT_DLL +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "The Wireshark developer community, https://www.wireshark.org/\0" + VALUE "FileDescription", "@MODULE_NAME@ dissector\0" + VALUE "FileVersion", "@MODULE_VERSION@\0" + VALUE "InternalName", "@MODULE_NAME@ @MODULE_VERSION@\0" + VALUE "LegalCopyright", "Copyright © 1998 Gerald Combs , Gilbert Ramirez and others\0" + VALUE "OriginalFilename", "@MODULE_NAME@.dll\0" + VALUE "ProductName", "Wireshark\0" + VALUE "ProductVersion", "@PROJECT_VERSION@\0" + VALUE "Comments", "Built with @MSVC_VARIANT@\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/plugins/wiretap/usbdump/AUTHORS b/plugins/wiretap/usbdump/AUTHORS new file mode 100644 index 00000000..f00e0146 --- /dev/null +++ b/plugins/wiretap/usbdump/AUTHORS @@ -0,0 +1,2 @@ +Author : +Jaap Keuter diff --git a/plugins/wiretap/usbdump/CMakeLists.txt b/plugins/wiretap/usbdump/CMakeLists.txt new file mode 100644 index 00000000..14fab19d --- /dev/null +++ b/plugins/wiretap/usbdump/CMakeLists.txt @@ -0,0 +1,64 @@ +# CMakeLists.txt +# +# Wireshark - Network traffic analyzer +# By Gerald Combs +# Copyright 1998 Gerald Combs +# +# SPDX-License-Identifier: GPL-2.0-or-later +# + +include(WiresharkPlugin) + +# Plugin name and version info (major minor micro extra) +set_module_info(usbdump 0 0 1 0) + +set(WIRETAP_SRC + usbdump.c +) + +set(PLUGIN_FILES + plugin.c + ${WIRETAP_SRC} +) + +set_source_files_properties( + ${PLUGIN_FILES} + PROPERTIES + COMPILE_FLAGS "${WERROR_COMMON_FLAGS}" +) + +register_plugin_files(plugin.c + plugin_wtap + ${WIRETAP_SRC} +) + +add_wireshark_plugin_library(usbdump wiretap) + +target_include_directories(usbdump PRIVATE ${CMAKE_SOURCE_DIR}/wiretap) + +target_link_libraries(usbdump wiretap) + +install_plugin(usbdump wiretap) + +file(GLOB WIRETAP_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*.h") +CHECKAPI( + NAME + usbdump + SWITCHES + SOURCES + ${WIRETAP_SRC} + ${WIRETAP_HEADERS} +) + +# +# 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: +# diff --git a/plugins/wiretap/usbdump/README b/plugins/wiretap/usbdump/README new file mode 100644 index 00000000..65a9b989 --- /dev/null +++ b/plugins/wiretap/usbdump/README @@ -0,0 +1,3 @@ +This wiretap plugin serves a dual purpose. One is to add usbdump file +reading capability to wiretap and therefore Wireshark and Tshark. +Second it is an illustration of a basic wiretap plugin module. diff --git a/plugins/wiretap/usbdump/usbdump.c b/plugins/wiretap/usbdump/usbdump.c new file mode 100644 index 00000000..5cc01ec1 --- /dev/null +++ b/plugins/wiretap/usbdump/usbdump.c @@ -0,0 +1,355 @@ +/* usbdump.c + * + * Wiretap Library + * Copyright (c) 1998 by Gilbert Ramirez + * + * File format support for usbdump file format + * Copyright (c) 2017 by Jaap Keuter + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * This wiretap is for an usbdump file format reader. The format is + * reverse engineered from FreeBSD source code. + * + * File format is little endian! + * + * Header + * --------------------------------- + * 0E 00 90 9A header magic + * 00 version major + * 03 version minor + * 00 00 00 00 00 00 00 00 reserved + * 00 00 00 00 00 00 00 00 + * 00 00 00 00 00 00 00 00 + * 00 00 + * + * Frames + * --------------------------------- + * F0 26 00 00 length of multiframe read from bpf (9968 octets) + * + * Frame, bpf header (little endian) + * --------------------------------- + * DE 3F 0E 59 ts sec + * 6A 77 01 00 ts usec + * 98 00 00 00 capture length (152) + * 98 00 00 00 data length (152) + * 1C header length (28) + * 04 bpf word alignment size + * 00 00 00 00 00 00 00 00 padding + * 00 00 + * + * Frame, captured data + * --------------------------------- + * 98 00 00 00 00 00 00 00 length, .... + * + */ + +#include "config.h" +#include "wtap-int.h" +#include "file_wrappers.h" +#include "string.h" + +void wtap_register_usbdump(void); + +#define USBDUMP_MAGIC 0x9a90000e + +/* Private data needed to read the file initially. */ +typedef struct { + guint16 version; + guint32 multiframe_size; + gboolean multiframe_overrun; +} usbdump_info_t; + + +static gboolean usbdump_read(wtap *wth, wtap_rec *rec, Buffer *buf, + int *err, gchar **err_info, + gint64 *data_offset); +static gboolean usbdump_seek_read(wtap *wth, gint64 seek_off, + wtap_rec *rec, Buffer *buf, + int *err, gchar **err_info); +static gboolean usbdump_read_packet(wtap *wth, FILE_T fh, + wtap_rec *rec, Buffer *buf, + int *err, gchar **err_info); + +static int usbdump_file_type_subtype; + +/* + * Try to interpret a file as a usbdump formatted file. + * Read relevant parts of the given file and collect information needed to + * read the individual frames. Return value indicates whether or not this is + * recognized as an usbdump file. + */ +static wtap_open_return_val +usbdump_open(wtap *wth, int *err, char **err_info) +{ + guint32 magic; + guint16 version; + guint32 multiframe_size; + usbdump_info_t *usbdump_info; + + /* Read in the number that should be at the start of a "usbdump" file */ + if (!wtap_read_bytes(wth->fh, &magic, sizeof magic, err, err_info)) { + if (*err != WTAP_ERR_SHORT_READ) + return WTAP_OPEN_ERROR; + return WTAP_OPEN_NOT_MINE; + } + + /* Check the file magic */ + if (GUINT32_FROM_LE(magic) != USBDUMP_MAGIC) + { + return WTAP_OPEN_NOT_MINE; + } + + /* Read the version of the header */ + if (!wtap_read_bytes(wth->fh, &version, sizeof version, err, err_info)) { + if (*err != WTAP_ERR_SHORT_READ) + return WTAP_OPEN_ERROR; + return WTAP_OPEN_NOT_MINE; + } + + /* Check for the supported version number */ + if (GUINT16_FROM_BE(version) != 3) { + /* We only support version 0.3 */ + *err = WTAP_ERR_UNSUPPORTED; + *err_info = ws_strdup_printf("usbdump: version %u.%u unsupported", + version >> 8, version & 0xff); + return WTAP_OPEN_NOT_MINE; + } + + /* Read the reserved field of the header */ + if (!wtap_read_bytes(wth->fh, NULL, 26, err, err_info)) { + if (*err != WTAP_ERR_SHORT_READ) + return WTAP_OPEN_ERROR; + return WTAP_OPEN_NOT_MINE; + } + + /* Read the initial multiframe size field */ + if (!wtap_read_bytes(wth->fh, &multiframe_size, sizeof multiframe_size, + err, err_info)) { + if (*err != WTAP_ERR_SHORT_READ) + return WTAP_OPEN_ERROR; + return WTAP_OPEN_NOT_MINE; + } + + /* Create a private structure to track the multiframe */ + usbdump_info = g_new(usbdump_info_t, 1); + usbdump_info->version = GUINT16_FROM_BE(version); + usbdump_info->multiframe_size = GUINT32_FROM_LE(multiframe_size); + usbdump_info->multiframe_overrun = FALSE; + + /* + * We are convinced this is a usbdump format file. + * Setup the wiretap structure and fill it with info of this format. + */ + wth->priv = (void *)usbdump_info; + wth->subtype_read = usbdump_read; + wth->subtype_seek_read = usbdump_seek_read; + wth->file_type_subtype = usbdump_file_type_subtype; + wth->file_encap = WTAP_ENCAP_USB_FREEBSD; + wth->file_tsprec = WTAP_TSPREC_USEC; + + return WTAP_OPEN_MINE; +} + +/* + * Sequential read with offset reporting. + * Read the next frame in the file and adjust for the multiframe size + * indication. Report back where reading of this frame started to + * support subsequent random access read. + */ +static gboolean +usbdump_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err, gchar **err_info, + gint64 *data_offset) +{ + usbdump_info_t *usbdump_info = (usbdump_info_t *)wth->priv; + + /* Report the current file location */ + *data_offset = file_tell(wth->fh); + + /* Try to read a packet worth of data */ + if (!usbdump_read_packet(wth, wth->fh, rec, buf, err, err_info)) + return FALSE; + + /* Check if we overrun the multiframe during the last read */ + if (usbdump_info->multiframe_overrun) + { + *err = WTAP_ERR_BAD_FILE; + *err_info = ws_strdup_printf("Multiframe overrun"); + return FALSE; + } + + /* See if we reached the end of the multiframe */ + if (usbdump_info->multiframe_size == 0) + { + /* + * Try to read the subsequent multiframe size field. + * This will fail at end of file, but that is accepted. + */ + wtap_read_bytes_or_eof(wth->fh, &usbdump_info->multiframe_size, + sizeof usbdump_info->multiframe_size, + err, err_info); + } + + return TRUE; +} + +/* + * Random access read. + * Read the frame at the given offset in the file. Store the frame data + * in a buffer and fill in the packet header info. + */ +static gboolean +usbdump_seek_read(wtap *wth, gint64 seek_off, wtap_rec *rec, + Buffer *buf, int *err, gchar **err_info) +{ + /* Seek to the desired file position at the start of the frame */ + if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1) + return FALSE; + + /* Try to read a packet worth of data */ + if (!usbdump_read_packet(wth, wth->random_fh, rec, buf, err, err_info)) { + if (*err == 0) + *err = WTAP_ERR_SHORT_READ; + return FALSE; + } + + return TRUE; +} + +/* + * Read the actual frame data from the file. + * This requires reading the header, determine the size, read frame size worth + * of data into the buffer and setting the packet header fields to the values + * of the frame header. + * + * Also, for the sequential read, keep track of the position in the multiframe + * so that we can find the next multiframe size field. + */ +static gboolean +usbdump_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec, Buffer *buf, + int *err, gchar **err_info) +{ + usbdump_info_t *usbdump_info = (usbdump_info_t *)wth->priv; + + guint8 bpf_hdr[18]; + guint8 bpf_hdr_len, alignment; + + /* Read the packet header */ + if (!wtap_read_bytes_or_eof(fh, bpf_hdr, 18, err, err_info)) + return FALSE; + + /* Get sizes */ + bpf_hdr_len = bpf_hdr[16]; + alignment = bpf_hdr[17]; + + /* Check header length */ + if (bpf_hdr_len > 18) + { + /* Read packet header padding */ + if (!wtap_read_bytes_or_eof(fh, NULL, bpf_hdr_len - 18, err, err_info)) + return FALSE; + } + + /* Keep track of multiframe_size and detect overrun */ + if (usbdump_info->multiframe_size < bpf_hdr_len) { + usbdump_info->multiframe_overrun = TRUE; + } else { + usbdump_info->multiframe_size -= bpf_hdr_len; + } + + /* Setup the per packet structure and fill it with info from this frame */ + rec->rec_type = REC_TYPE_PACKET; + rec->block = wtap_block_create(WTAP_BLOCK_PACKET); + rec->presence_flags = WTAP_HAS_TS | WTAP_HAS_CAP_LEN; + rec->ts.secs = (guint32)bpf_hdr[3] << 24 | (guint32)bpf_hdr[2] << 16 | + (guint32)bpf_hdr[1] << 8 | (guint32)bpf_hdr[0]; + rec->ts.nsecs = ((guint32)bpf_hdr[7] << 24 | (guint32)bpf_hdr[6] << 16 | + (guint32)bpf_hdr[5] << 8 | (guint32)bpf_hdr[4]) * 1000; + rec->rec_header.packet_header.caplen = (guint32)bpf_hdr[11] << 24 | (guint32)bpf_hdr[10] << 16 | + (guint32)bpf_hdr[9] << 8 | (guint32)bpf_hdr[8]; + rec->rec_header.packet_header.len = (guint32)bpf_hdr[15] << 24 | (guint32)bpf_hdr[14] << 16 | + (guint32)bpf_hdr[13] << 8 | (guint32)bpf_hdr[12]; + + /* Read the packet data */ + if (!wtap_read_packet_bytes(fh, buf, rec->rec_header.packet_header.caplen, err, err_info)) + return FALSE; + + /* Keep track of multiframe_size and detect overrun */ + if (usbdump_info->multiframe_size < rec->rec_header.packet_header.caplen) { + usbdump_info->multiframe_overrun = TRUE; + } else { + usbdump_info->multiframe_size -= rec->rec_header.packet_header.caplen; + } + + /* Check for and apply alignment as defined in the frame header */ + guint8 pad_len = (guint32)alignment - + (((guint32)bpf_hdr_len + rec->rec_header.packet_header.caplen) & + ((guint32)alignment - 1)); + if (pad_len < alignment) { + /* Read alignment from the file */ + if (!wtap_read_bytes(fh, NULL, pad_len, err, err_info)) + return FALSE; + + /* Keep track of multiframe_size and detect overrun */ + if (usbdump_info->multiframe_size < pad_len) { + usbdump_info->multiframe_overrun = TRUE; + } else { + usbdump_info->multiframe_size -= pad_len; + } + } + + return TRUE; +} + +/* + * Register with wiretap. + * Register how we can handle an unknown file to see if this is a valid + * usbdump file and register information about this file format. + */ +static const struct supported_block_type usbdump_blocks_supported[] = { + /* We support packet blocks, with no comments or other options. */ + { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED } +}; +static const struct file_type_subtype_info fi = { + "FreeBSD USBDUMP", + "usbdump", + NULL, + NULL, + FALSE, + BLOCKS_SUPPORTED(usbdump_blocks_supported), + NULL, + NULL, + NULL +}; + +void +wtap_register_usbdump(void) +{ + struct open_info oi = { + "FreeBSD usbdump", + OPEN_INFO_MAGIC, + usbdump_open, + NULL, + NULL, + NULL + }; + + wtap_register_open_info(&oi, FALSE); + + usbdump_file_type_subtype = wtap_register_file_type_subtype(&fi); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ -- cgit v1.2.3