IPMI trace dissector (without PCAP-dependent part).
authorU-beauty\bdn <dima_b@pigeonpoint.com>
Fri, 6 Jun 2014 03:41:07 +0000 (09:41 +0600)
committerAnders Broman <a.broman58@gmail.com>
Fri, 6 Jun 2014 06:43:45 +0000 (06:43 +0000)
Added KCS and TMode protocol dissectors.
Request/response logic has been revised.
Saved request data logic has been revised.
Added Get Message command response dissector.
Added missing PICMG command dissectors.
Added new PICMG command dissectors.
Added new PPS OEM command entries.
Added VITA 46.11 command dissectors.

From: Bill Meier:
- refs to value_strings/range_strings in hf[] entries, by convention, should use VALS/RVALS macros;
- refs to true_false_strings should use TFS(&...) macro.
  also: true_false_string definitions should not be defined as arrays.
- remove some unneeded #includes (packet-ipmi.c).
- Do some re-indentation.
- Add editor-modelines as needed.

bug: 10004
Change-Id: Ib269b35784c0b70892d1e0111bcfb483ea64092c
Reviewed-on: https://code.wireshark.org/review/1185
Reviewed-by: Anders Broman <a.broman58@gmail.com>
16 files changed:
epan/CMakeLists.txt
epan/dissectors/Makefile.common
epan/dissectors/packet-ipmi-app.c
epan/dissectors/packet-ipmi-chassis.c
epan/dissectors/packet-ipmi-picmg.c
epan/dissectors/packet-ipmi-pps.c
epan/dissectors/packet-ipmi-se.c
epan/dissectors/packet-ipmi-session.c
epan/dissectors/packet-ipmi-storage.c
epan/dissectors/packet-ipmi-trace.c [new file with mode: 0755]
epan/dissectors/packet-ipmi-transport.c
epan/dissectors/packet-ipmi-vita.c [new file with mode: 0755]
epan/dissectors/packet-ipmi.c
epan/dissectors/packet-ipmi.h
wiretap/wtap.c
wiretap/wtap.h

index f6d69f5aed76c7605182621c2b9749ae178ecec8..7461dc1cbc3c1b0a4df2283c72503977d32d1862 100644 (file)
@@ -809,6 +809,7 @@ set(DISSECTOR_SRC
        dissectors/packet-ipfc.c
        dissectors/packet-ipmi-session.c
        dissectors/packet-ipmi.c
+       dissectors/packet-ipmi-trace.c
        dissectors/packet-ipnet.c
        dissectors/packet-ipoib.c
        dissectors/packet-ipp.c
@@ -1409,6 +1410,7 @@ set(IPMI_SUBPARSERS
        dissectors/packet-ipmi-transport.c
        dissectors/packet-ipmi-pps.c
        dissectors/packet-ipmi-update.c
+       dissectors/packet-ipmi-vita.c
 )
 
 set(DISSECTOR_SUPPORT_SRC
index 94ce213316fec5a6e1c9e0f6c3f10d25b4dca0cd..6d24559e137ef0734f57c2c23bf16d4d605d23f0 100644 (file)
@@ -729,6 +729,7 @@ DISSECTOR_SRC = \
        packet-ipfc.c           \
        packet-ipmi-session.c   \
        packet-ipmi.c           \
+       packet-ipmi-trace.c             \
        packet-ipnet.c          \
        packet-ipoib.c          \
        packet-ipp.c            \
@@ -1713,7 +1714,8 @@ IPMI_SUBPARSERS = \
        packet-ipmi-storage.c   \
        packet-ipmi-transport.c \
        packet-ipmi-pps.c       \
-       packet-ipmi-update.c
+       packet-ipmi-update.c \
+       packet-ipmi-vita.c
 
 # Dissector helpers.  They're included in the source files in this
 # directory, but they're not dissectors themselves, i.e. they're not
index fffb526827b75c78b3d0d0aeab7d36afb82e3996..97b71bc93f3feb996cfa98b55e96c501a67131af 100644 (file)
@@ -57,6 +57,8 @@ static gint ett_ipmi_app_32_rq_byte1 = -1;
 static gint ett_ipmi_app_32_rq_byte2 = -1;
 static gint ett_ipmi_app_32_rs_byte1 = -1;
 static gint ett_ipmi_app_32_rs_byte2 = -1;
+static gint ett_ipmi_app_33_rs_byte1 = -1;
+static gint ett_ipmi_app_33_msg = -1;
 static gint ett_ipmi_app_34_byte1 = -1;
 static gint ett_ipmi_app_34_msg = -1;
 
@@ -181,10 +183,15 @@ static gint hf_ipmi_app_32_rq_state = -1;
 static gint hf_ipmi_app_32_rs_chno = -1;
 static gint hf_ipmi_app_32_rs_state = -1;
 
+static gint hf_ipmi_app_33_rs_chan = -1;
+static gint hf_ipmi_app_33_rs_priv = -1;
+static gint hf_ipmi_app_33_msg = -1;
+
 static gint hf_ipmi_app_34_track = -1;
 static gint hf_ipmi_app_34_encrypt = -1;
 static gint hf_ipmi_app_34_auth = -1;
 static gint hf_ipmi_app_34_chan = -1;
+static gint hf_ipmi_app_34_msg = -1;
 
 static gint hf_ipmi_app_38_rq_ipmi20 = -1;
 static gint hf_ipmi_app_38_rq_chan = -1;
@@ -422,7 +429,7 @@ rs01(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                &hf_ipmi_app_01_ipmi_ads_sensor, NULL };
        size_t len;
 
-       len = tvb_length(tvb);
+       len = tvb_captured_length(tvb);
 
        proto_tree_add_item(tree, hf_ipmi_app_01_dev_id, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_bitmask_text(tree, tvb, 1, 1, NULL, NULL, ett_ipmi_app_01_byte2, byte2, ENC_LITTLE_ENDIAN, 0);
@@ -481,7 +488,7 @@ rs04(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 static void
 rq05(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       proto_tree_add_item(tree, hf_ipmi_app_05_devspec, tvb, 0, tvb_length(tvb), ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_app_05_devspec, tvb, 0, -1, ENC_NA);
 }
 
 /* Set ACPI Power State.
@@ -659,6 +666,29 @@ static const value_string cc33[] = {
        { 0, NULL }
 };
 
+static void
+rs33(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint *byte1[] = { &hf_ipmi_app_33_rs_chan,
+                       &hf_ipmi_app_33_rs_priv, NULL };
+       tvbuff_t *next;
+       ipmi_dissect_arg_t arg;
+
+       proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL, ett_ipmi_app_33_rs_byte1,
+                       byte1, ENC_LITTLE_ENDIAN, 0);
+
+       next = tvb_new_subset_remaining(tvb, 1);
+
+       arg.context = IPMI_E_GETMSG;
+       arg.channel = tvb_get_guint8(tvb, 0) & 0xF;
+       arg.flags = 0;
+
+       do_dissect_ipmb(next, pinfo, tree,
+                       hf_ipmi_app_33_msg, ett_ipmi_app_33_msg, &arg);
+
+}
+
+
 /* Send Message
  */
 static void
@@ -666,43 +696,34 @@ rq34(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
        static const gint *byte1[] = { &hf_ipmi_app_34_track, &hf_ipmi_app_34_encrypt,
                &hf_ipmi_app_34_auth, &hf_ipmi_app_34_chan, NULL };
-       ipmi_dissect_format_t dfmt;
-       proto_tree *s_tree;
-       proto_item *ti;
        tvbuff_t *next;
+       ipmi_dissect_arg_t arg;
 
        proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL,
                        ett_ipmi_app_34_byte1, byte1, ENC_LITTLE_ENDIAN, 0);
 
-       next = tvb_new_subset(tvb, 1, tvb_length(tvb) - 1, tvb_length(tvb) - 1);
-       ti = proto_tree_add_text(tree, next, 0, tvb_length(next), "Message");
-       s_tree = proto_item_add_subtree(ti, ett_ipmi_app_34_msg);
-
-       memset(&dfmt, 0, sizeof(dfmt));
-       dfmt.flags = ipmi_guess_dissect_flags(next);
-       dfmt.arg = ipmi_current_hdr;
-       dfmt.getmoreheaders = ipmi_sendmsg_getheaders;
-       dfmt.whichresponse = ipmi_sendmsg_whichresponse;
-       dfmt.otheridx = ipmi_sendmsg_otheridx;
-       ipmi_do_dissect(next, pinfo, s_tree, &dfmt);
-       proto_item_set_text(ti, "%s", dfmt.info);
+       next = tvb_new_subset_remaining(tvb, 1);
+
+       arg.context = IPMI_E_SENDMSG_RQ;
+       arg.channel = tvb_get_guint8(tvb, 0) & 0xF;
+       arg.flags = 0;
+
+       do_dissect_ipmb(next, pinfo, tree,
+                       hf_ipmi_app_34_msg, ett_ipmi_app_34_msg, &arg);
 }
 
 static void
 rs34(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       ipmi_dissect_format_t dfmt;
-       proto_tree *s_tree;
-       proto_item *ti;
-
-       ti = proto_tree_add_text(tree, tvb, 0, tvb_length(tvb), "Message");
-       s_tree = proto_item_add_subtree(ti, ett_ipmi_app_34_msg);
-
-       if (tvb_length(tvb)) {
-               memset(&dfmt, 0, sizeof(dfmt));
-               dfmt.flags = ipmi_guess_dissect_flags(tvb);
-               ipmi_do_dissect(tvb, pinfo, s_tree, &dfmt);
-               proto_item_set_text(ti, "%s", dfmt.info);
+       if (tvb_captured_length(tvb)) {
+               ipmi_dissect_arg_t arg;
+
+               arg.context = IPMI_E_SENDMSG_RS;
+               arg.channel = 0;
+               arg.flags = 0;
+
+               do_dissect_ipmb(tvb, pinfo, tree,
+                               hf_ipmi_app_34_msg, ett_ipmi_app_34_msg, &arg);
        }
 }
 
@@ -851,7 +872,7 @@ static void
 rq3c(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_app_3c_session_id, tvb, 0, 4, ENC_LITTLE_ENDIAN);
-       if (tvb_length(tvb) > 4) {
+       if (tvb_captured_length(tvb) > 4) {
                proto_tree_add_item(tree, hf_ipmi_app_3c_session_handle, tvb, 4, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -953,7 +974,7 @@ static const value_string cc62[] = {
 
 static ipmi_cmd_t cmd_app[] = {
   /* IPM Device Global Commands */
-  { 0x01, NULL, rs01, NULL, NULL, "Get Device ID", CMD_MAYBROADCAST },
+  { 0x01, NULL, rs01, NULL, NULL, "Get Device ID", 0 },
   { 0x02, NULL, NULL, NULL, NULL, "Cold Reset", 0 },
   { 0x03, NULL, NULL, NULL, NULL, "Warm Reset", 0 },
   { 0x04, NULL, rs04, NULL, NULL, "Get Self Test Results", 0 },
@@ -978,7 +999,7 @@ static ipmi_cmd_t cmd_app[] = {
   { 0x30, rq30, NULL, NULL, NULL, "Clear Message Flags", 0 },
   { 0x31, NULL, rs31, NULL, NULL, "Get Message Flags", 0 },
   { 0x32, rq32, rs32, NULL, NULL, "Enable Message Channel Receive", 0 },
-  { 0x33, IPMI_TBD,   cc33, NULL, "Get Message", 0 },
+  { 0x33, NULL, rs33, cc33, NULL, "Get Message", CMD_CALLRQ },
   { 0x34, rq34, rs34, cc34, NULL, "Send Message", CMD_CALLRQ },
   { 0x35, IPMI_TBD,   cc35, NULL, "Read Event Message Buffer", 0 },
   { 0x36, IPMI_TBD,   NULL, NULL, "Get BT Interface Capabilities", 0 },
@@ -1313,6 +1334,16 @@ ipmi_register_app(gint proto_ipmi)
                        { "Channel State",
                                "ipmi.app32.rs_state", FT_BOOLEAN, 8, TFS(&tfs_32_state), 0x01, NULL, HFILL }},
 
+               { &hf_ipmi_app_33_rs_chan,
+                       { "Channel",
+                               "ipmi.app33.chan", FT_UINT8, BASE_CUSTOM, ipmi_fmt_channel, 0x0f, NULL, HFILL }},
+               { &hf_ipmi_app_33_rs_priv,
+                       { "Inferred privilege level",
+                               "ipmi.app33.priv", FT_UINT8, BASE_HEX, VALS(vals_XX_priv), 0xf0, NULL, HFILL }},
+               { &hf_ipmi_app_33_msg,
+                       { "Message data",
+                               "ipmi.app33.msg", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
+
                { &hf_ipmi_app_34_track,
                        { "Tracking",
                                "ipmi.app34.track", FT_UINT8, BASE_HEX, VALS(vals_34_track), 0xc0, NULL, HFILL }},
@@ -1325,6 +1356,9 @@ ipmi_register_app(gint proto_ipmi)
                { &hf_ipmi_app_34_chan,
                        { "Channel",
                                "ipmi.app34.chan", FT_UINT8, BASE_CUSTOM, ipmi_fmt_channel, 0x0f, NULL, HFILL }},
+               { &hf_ipmi_app_34_msg,
+                       { "Embedded message",
+                               "ipmi.app34.msg", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }},
 
                { &hf_ipmi_app_38_rq_ipmi20,
                        { "Version compatibility",
@@ -1462,6 +1496,8 @@ ipmi_register_app(gint proto_ipmi)
                &ett_ipmi_app_32_rq_byte2,
                &ett_ipmi_app_32_rs_byte1,
                &ett_ipmi_app_32_rs_byte2,
+               &ett_ipmi_app_33_rs_byte1,
+               &ett_ipmi_app_33_msg,
                &ett_ipmi_app_34_byte1,
                &ett_ipmi_app_34_msg,
                &ett_ipmi_app_38_rq_byte1,
index 2d8d85c5a6158d9f22659b3622f82e33597d381c..98e9ed68b399a3f74b3ca56d9410cbaad6cd0c7d 100644 (file)
@@ -404,7 +404,7 @@ static void
 bootopt_07(tvbuff_t *tvb, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_chs_bo07_block_selector, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_chs_bo07_block_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_chs_bo07_block_data, tvb, 1, -1, ENC_NA);
 }
 
 
@@ -438,7 +438,7 @@ rs00(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_item(tree, hf_ipmi_chs_00_sel_dev_addr, tvb, 3, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(tree, hf_ipmi_chs_00_sm_dev_addr, tvb, 4, 1, ENC_LITTLE_ENDIAN);
 
-       if (tvb_length(tvb) >= 5) {
+       if (tvb_captured_length(tvb) >= 5) {
                proto_tree_add_item(tree, hf_ipmi_chs_00_bridge_dev_addr, tvb, 5, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -470,7 +470,7 @@ rs01(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                        ett_ipmi_chs_01_last_event, byte2, ENC_LITTLE_ENDIAN, 0);
        proto_tree_add_bitmask_text(tree, tvb, 2, 1, "Misc. State: ", NULL,
                        ett_ipmi_chs_01_misc, byte3, ENC_LITTLE_ENDIAN, 0);
-       if (tvb_length(tvb) > 3) {
+       if (tvb_captured_length(tvb) > 3) {
                proto_tree_add_bitmask_text(tree, tvb, 3, 1, "Front panel buttons capabilities: ",
                                NULL, ett_ipmi_chs_01_fpb, byte4, ENC_LITTLE_ENDIAN, BMT_NO_TFS);
        };
@@ -494,11 +494,11 @@ rq04(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        static const int *byte2[] = { &hf_ipmi_chs_04_perm_on, NULL };
 
-       if (tvb_length(tvb) > 0) {
+       if (tvb_captured_length(tvb) > 0) {
                proto_tree_add_item(tree, hf_ipmi_chs_04_ival, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        }
 
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                proto_tree_add_bitmask_text(tree, tvb, 1, 1, "Flags: ", "None",
                                ett_ipmi_chs_04_byte2, byte2, ENC_LITTLE_ENDIAN, 0);
        }
@@ -517,7 +517,7 @@ rq05(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_item(tree, hf_ipmi_chs_05_sdr_dev_addr, tvb, 2, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(tree, hf_ipmi_chs_05_sel_dev_addr, tvb, 3, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(tree, hf_ipmi_chs_05_sm_dev_addr, tvb, 4, 1, ENC_LITTLE_ENDIAN);
-       if (tvb_length(tvb) > 5) {
+       if (tvb_captured_length(tvb) > 5) {
                /* Bridge device address is optional */
                proto_tree_add_item(tree, hf_ipmi_chs_05_bridge_dev_addr, tvb, 5, 1, ENC_LITTLE_ENDIAN);
        }
@@ -588,13 +588,13 @@ rq08(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                        ipmi_dcd8(pno, 0x7f), desc, pno);
 
        /* Data is optional; no data means 'just set validity' */
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                if (pno < array_length(boot_options)) {
-                       sub = tvb_new_subset(tvb, 1, tvb_length(tvb) - 1, tvb_length(tvb) - 1);
+                       sub = tvb_new_subset_remaining(tvb, 1);
                        boot_options[pno].intrp(sub, tree);
                } else {
                        proto_tree_add_none_format(tree, hf_ipmi_chs_08_data, tvb, 1,
-                                       tvb_length(tvb) - 1, "Parameter data: %s", desc);
+                                       -1, "Parameter data: %s", desc);
                }
        }
 }
@@ -670,11 +670,10 @@ rs09(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                        ipmi_dcd8(pno, 0x7f), desc, pno);
 
        if (pno < array_length(boot_options)) {
-               sub = tvb_new_subset(tvb, 2, tvb_length(tvb) - 2, tvb_length(tvb) - 2);
+               sub = tvb_new_subset_remaining(tvb, 2);
                boot_options[pno].intrp(sub, tree);
        } else {
-               proto_tree_add_item(tree, hf_ipmi_chs_09_rs_param_data, tvb, 2,
-                               tvb_length(tvb) - 2, ENC_NA);
+               proto_tree_add_item(tree, hf_ipmi_chs_09_rs_param_data, tvb, 2, -1, ENC_NA);
        }
 }
 
@@ -715,7 +714,7 @@ ipmi_register_chassis(gint proto_ipmi)
        static hf_register_info hf[] = {
                { &hf_ipmi_chs_bo00_sip,
                        { "Set In Progress",
-                               "ipmi.bootopt00.sip", FT_UINT8, BASE_HEX, VALS(bo00_sip_vals), 0x03, NULL, HFILL }},
+                               "ipmi.bootopt00.sip", FT_UINT8, BASE_HEX, VALS(bo00_sip_vals), 0x03, NULL, HFILL }},
                { &hf_ipmi_chs_bo01_spsel,
                        { "Service Partition Selector",
                                "ipmi.bootopt01.spsel", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
index a957ff26ae3867914e26834c504b652fce306793..04f2423747f04b4b736d6550361c2db0571653f1 100644 (file)
 #include "packet-ipmi.h"
 
 static gint ett_ipmi_picmg_led_color = -1;
-static gint ett_ipmi_picmg_link_info = -1;
 static gint ett_ipmi_picmg_05_byte1 = -1;
 static gint ett_ipmi_picmg_06_byte1 = -1;
 static gint ett_ipmi_picmg_06_byte2 = -1;
 static gint ett_ipmi_picmg_06_byte3 = -1;
+static gint ett_ipmi_picmg_link_info = -1;
 static gint ett_ipmi_picmg_08_byte1 = -1;
 static gint ett_ipmi_picmg_09_ipmba = -1;
 static gint ett_ipmi_picmg_09_ipmbb = -1;
@@ -51,6 +51,23 @@ static gint ett_ipmi_picmg_prop01_byte1 = -1;
 static gint ett_ipmi_picmg_34_byte3 = -1;
 static gint ett_ipmi_picmg_36_byte2 = -1;
 static gint ett_ipmi_picmg_37_byte2 = -1;
+static gint ett_ipmi_picmg_link_state = -1;
+static gint ett_ipmi_picmg_link_dev = -1;
+
+static gint ett_ipmi_picmg_clock_setting = -1;
+static gint ett_ipmi_picmg_clock_res = -1;
+
+static gint ett_ipmi_picmg_hpm_caps = -1;
+
+static gint ett_ipmi_picmg_47_byte1 = -1;
+
+static gint ett_ipmi_picmg_23_rq_byte2 = -1;
+static gint ett_ipmi_picmg_23_rs_byte5 = -1;
+static gint ett_ipmi_picmg_25_rs_byte4 = -1;
+static gint ett_ipmi_picmg_25_rs_byte5 = -1;
+static gint ett_ipmi_picmg_27_rs_byte3 = -1;
+static gint ett_ipmi_picmg_28_rq_byte3 = -1;
+static gint ett_ipmi_picmg_29_rs_byte3 = -1;
 
 static gint hf_ipmi_picmg_led_function = -1;
 static gint hf_ipmi_picmg_led_on_duration = -1;
@@ -63,6 +80,30 @@ static gint hf_ipmi_picmg_linkinfo_ports = -1;
 static gint hf_ipmi_picmg_linkinfo_iface = -1;
 static gint hf_ipmi_picmg_linkinfo_chan = -1;
 static gint hf_ipmi_picmg_linkinfo_state = -1;
+static gint hf_ipmi_picmg_linkinfo = -1;
+static gint hf_ipmi_picmg_linkinfo_amc_chan = -1;
+static gint hf_ipmi_picmg_linkinfo_amc_ports = -1;
+static gint hf_ipmi_picmg_linkinfo_amc_type = -1;
+static gint hf_ipmi_picmg_linkinfo_amc_type_ext = -1;
+static gint hf_ipmi_picmg_linkinfo_amc_grpid = -1;
+static gint hf_ipmi_picmg_linkinfo_state_0 = -1;
+static gint hf_ipmi_picmg_linkinfo_state_1 = -1;
+static gint hf_ipmi_picmg_linkinfo_dev = -1;
+static gint hf_ipmi_picmg_linkinfo_dev_type = -1;
+static gint hf_ipmi_picmg_linkinfo_dev_id = -1;
+
+static gint hf_ipmi_picmg_clock_id = -1;
+static gint hf_ipmi_picmg_clock_cfg = -1;
+static gint hf_ipmi_picmg_clock_setting = -1;
+static gint hf_ipmi_picmg_clock_state = -1;
+static gint hf_ipmi_picmg_clock_dir = -1;
+static gint hf_ipmi_picmg_clock_pll = -1;
+static gint hf_ipmi_picmg_clock_family = -1;
+static gint hf_ipmi_picmg_clock_accuracy = -1;
+static gint hf_ipmi_picmg_clock_frequency = -1;
+static gint hf_ipmi_picmg_clock_resource = -1;
+static gint hf_ipmi_picmg_clock_resource_type = -1;
+static gint hf_ipmi_picmg_clock_resource_dev = -1;
 
 static gint hf_ipmi_picmg_00_version = -1;
 static gint hf_ipmi_picmg_00_max_fruid = -1;
@@ -175,6 +216,8 @@ static gint hf_ipmi_picmg_18_li_key = -1;
 static gint hf_ipmi_picmg_18_link_num = -1;
 static gint hf_ipmi_picmg_18_sensor_num = -1;
 
+static gint hf_ipmi_picmg_1a_flags = -1;
+
 static gint hf_ipmi_picmg_1b_addr_active = -1;
 static gint hf_ipmi_picmg_1b_addr_backup = -1;
 
@@ -288,6 +331,114 @@ static gint hf_ipmi_picmg_36_fail_oper_fw = -1;
 
 static gint hf_ipmi_picmg_37_percent = -1;
 
+static gint hf_ipmi_picmg_hpm_id = -1;
+static gint hf_ipmi_picmg_hpm_rev = -1;
+static gint hf_ipmi_picmg_hpm2_mask = -1;
+static gint hf_ipmi_picmg_hpm2_caps = -1;
+static gint hf_ipmi_picmg_hpm2_dyn_ssn = -1;
+static gint hf_ipmi_picmg_hpm2_ver_chg = -1;
+static gint hf_ipmi_picmg_hpm2_ext_mgt = -1;
+static gint hf_ipmi_picmg_hpm2_pkt_trc = -1;
+static gint hf_ipmi_picmg_hpm2_sol_ext = -1;
+static gint hf_ipmi_picmg_hpm_oem_start = -1;
+static gint hf_ipmi_picmg_hpm_oem_rev = -1;
+static gint hf_ipmi_picmg_hpm2_sol_oem_start = -1;
+static gint hf_ipmi_picmg_hpm2_sol_oem_rev = -1;
+static gint hf_ipmi_picmg_hpm_cred_hnd = -1;
+static gint hf_ipmi_picmg_hpm_func_sel = -1;
+static gint hf_ipmi_picmg_hpm_ipmi_rev = -1;
+static gint hf_ipmi_picmg_hpm_cipher_id = -1;
+static gint hf_ipmi_picmg_hpm_auth_type = -1;
+static gint hf_ipmi_picmg_hpm_priv_level = -1;
+static gint hf_ipmi_picmg_hpm_chn_num = -1;
+static gint hf_ipmi_picmg_hpm_avail_time = -1;
+static gint hf_ipmi_picmg_hpm_user_name = -1;
+static gint hf_ipmi_picmg_hpm_user_pwd = -1;
+static gint hf_ipmi_picmg_hpm_bmc_key = -1;
+static gint hf_ipmi_picmg_hpm_operation = -1;
+static gint hf_ipmi_picmg_hpm_ssn_hnd = -1;
+
+static gint hf_ipmi_picmg_hpm_power_draw = -1;
+static gint hf_ipmi_picmg_hpm_base_channels = -1;
+static gint hf_ipmi_picmg_hpm_fabric_channels = -1;
+static gint hf_ipmi_picmg_hpm_update_channels = -1;
+static gint hf_ipmi_picmg_hpm_cross_channels = -1;
+static gint hf_ipmi_picmg_hpm_num_chn_desc = -1;
+static gint hf_ipmi_picmg_hpm_chn_mask = -1;
+
+static gint hf_ipmi_picmg_hpm_ext_mgmt_state = -1;
+static gint hf_ipmi_picmg_hpm_polling_period = -1;
+static gint hf_ipmi_picmg_hpm_auth_pwr_state = -1;
+static gint hf_ipmi_picmg_hpm_amc_pwr_state = -1;
+
+static gint hf_ipmi_picmg47_port = -1;
+static gint hf_ipmi_picmg47_flags = -1;
+static gint hf_ipmi_picmg47_assignment = -1;
+static gint hf_ipmi_picmg47_state = -1;
+static gint hf_ipmi_picmg47_instance = -1;
+
+static gint hf_ipmi_picmg48_sub_fru_type = -1;
+static gint hf_ipmi_picmg48_sub_fru_id = -1;
+static gint hf_ipmi_picmg48_ip_source = -1;
+
+static gint hf_ipmi_picmg_23_rq_byte2 = -1;
+static gint hf_ipmi_picmg_23_slot_sel = -1;
+static gint hf_ipmi_picmg_23_carrier_num = -1;
+static gint hf_ipmi_picmg_23_slot_num = -1;
+static gint hf_ipmi_picmg_23_tier_num = -1;
+static gint hf_ipmi_picmg_23_rs_byte5 = -1;
+static gint hf_ipmi_picmg_23_slot_base = -1;
+static gint hf_ipmi_picmg_23_tier_base = -1;
+static gint hf_ipmi_picmg_23_orientation = -1;
+static gint hf_ipmi_picmg_23_origin_x = -1;
+static gint hf_ipmi_picmg_23_origin_y = -1;
+
+static gint hf_ipmi_picmg_24_channel = -1;
+static gint hf_ipmi_picmg_24_control = -1;
+static gint hf_ipmi_picmg_24_current = -1;
+static gint hf_ipmi_picmg_24_primary_pm = -1;
+static gint hf_ipmi_picmg_24_backup_pm = -1;
+
+static gint hf_ipmi_picmg_25_start = -1;
+static gint hf_ipmi_picmg_25_count = -1;
+static gint hf_ipmi_picmg_25_max = -1;
+static gint hf_ipmi_picmg_25_gstatus = -1;
+static gint hf_ipmi_picmg_25_fault = -1;
+static gint hf_ipmi_picmg_25_pwr_good = -1;
+static gint hf_ipmi_picmg_25_mp_good = -1;
+static gint hf_ipmi_picmg_25_role = -1;
+static gint hf_ipmi_picmg_25_cstatus = -1;
+static gint hf_ipmi_picmg_25_pwr_on = -1;
+static gint hf_ipmi_picmg_25_pwr_ovr = -1;
+static gint hf_ipmi_picmg_25_pwr = -1;
+static gint hf_ipmi_picmg_25_enable = -1;
+static gint hf_ipmi_picmg_25_mp_ovr = -1;
+static gint hf_ipmi_picmg_25_mp = -1;
+static gint hf_ipmi_picmg_25_ps1 = -1;
+
+static gint hf_ipmi_picmg_26_pm_site = -1;
+static gint hf_ipmi_picmg_27_rs_byte3 = -1;
+static gint hf_ipmi_picmg_27_pm_healthy = -1;
+static gint hf_ipmi_picmg_28_timeout = -1;
+static gint hf_ipmi_picmg_28_rq_byte3 = -1;
+static gint hf_ipmi_picmg_28_mch2 = -1;
+static gint hf_ipmi_picmg_28_mch1 = -1;
+
+static gint hf_ipmi_picmg_29_rs_byte3 = -1;
+static gint hf_ipmi_picmg_29_maj_rst = -1;
+static gint hf_ipmi_picmg_29_min_rst = -1;
+static gint hf_ipmi_picmg_29_alarm_cut = -1;
+static gint hf_ipmi_picmg_29_test_mode = -1;
+static gint hf_ipmi_picmg_29_pwr_alarm = -1;
+static gint hf_ipmi_picmg_29_minor_alarm = -1;
+static gint hf_ipmi_picmg_29_major_alarm = -1;
+static gint hf_ipmi_picmg_29_crit_alarm = -1;
+
+static gint hf_ipmi_picmg_2a_alarm_id = -1;
+static gint hf_ipmi_picmg_2a_alarm_ctrl = -1;
+
+static gint hf_ipmi_picmg_2b_alarm_state = -1;
+
 static const value_string site_type_vals[] = {
        { 0x00, "PICMG board" },
        { 0x01, "Power Entry" },
@@ -358,6 +509,21 @@ static const value_string linkinfo_type_vals[] = {
        { 0, NULL }
 };
 
+static const value_string linkinfo_amc_type_vals[] = {
+       { 0x02, "AMC.1 PCI Express" },
+       { 0x03, "AMC.1 PCI Express Advanced Switching" },
+       { 0x04, "AMC.1 PCI Express Advanced Switching" },
+       { 0x05, "AMC.2 Ethernet" },
+       { 0x06, "AMC.3 Serial RapidIO" },
+       { 0x07, "AMC.3 Storage" },
+       { 0xf0, "OEM" }, { 0xf1, "OEM" }, { 0xf2, "OEM" }, { 0xf3, "OEM" },
+       { 0xf4, "OEM" }, { 0xf5, "OEM" }, { 0xf6, "OEM" }, { 0xf7, "OEM" },
+       { 0xf8, "OEM" }, { 0xf9, "OEM" }, { 0xfa, "OEM" }, { 0xfb, "OEM" },
+       { 0xfc, "OEM" }, { 0xfd, "OEM" }, { 0xfe, "OEM" },
+
+       { 0, NULL }
+};
+
 static const value_string linkinfo_ports_vals[] = {
        { 0x00, "None" },
        { 0x01, "0" },
@@ -536,16 +702,16 @@ rs00(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 static void
 rq01(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       if (tvb_length(tvb) > 0) {
+       if (tvb_captured_length(tvb) > 0) {
                proto_tree_add_item(tree, hf_ipmi_picmg_01_rq_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        }
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                proto_tree_add_item(tree, hf_ipmi_picmg_01_rq_addr_key_type, tvb, 1, 1, ENC_LITTLE_ENDIAN);
        }
-       if (tvb_length(tvb) > 2) {
+       if (tvb_captured_length(tvb) > 2) {
                proto_tree_add_item(tree, hf_ipmi_picmg_01_rq_addr_key, tvb, 2, 1, ENC_LITTLE_ENDIAN);
        }
-       if (tvb_length(tvb) > 3) {
+       if (tvb_captured_length(tvb) > 3) {
                proto_tree_add_item(tree, hf_ipmi_picmg_01_rq_site_type, tvb, 3, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -690,10 +856,10 @@ rs08(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_bitmask_text(tree, tvb, 0, 1, "LED States: ", "None",
                        ett_ipmi_picmg_08_byte1, byte1, ENC_LITTLE_ENDIAN, 0);
        parse_led_state(tree, tvb, 1, "Local Control ");
-       if (tvb_length(tvb) > 4) {
+       if (tvb_captured_length(tvb) > 4) {
                parse_led_state(tree, tvb, 4, "Override ");
        }
-       if (tvb_length(tvb) > 7) {
+       if (tvb_captured_length(tvb) > 7) {
                proto_tree_add_item(tree, hf_ipmi_picmg_08_lamptest_duration, tvb, 7, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -788,7 +954,7 @@ static void
 rq0d(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_picmg_0d_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                proto_tree_add_item(tree, hf_ipmi_picmg_0d_start, tvb, 1, 2, ENC_LITTLE_ENDIAN);
        }
 }
@@ -837,6 +1003,9 @@ rq0f(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        static const int *chan[] = { &hf_ipmi_picmg_0f_iface, &hf_ipmi_picmg_0f_chan, NULL };
 
        proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL, ett_ipmi_picmg_0f_chan, chan, ENC_LITTLE_ENDIAN, 0);
+       if (tvb_captured_length(tvb) > 1) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_1a_flags, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       }
 }
 
 static void
@@ -845,19 +1014,21 @@ rs0f(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        static const value_string state_vals[] = {
                { 0x00, "Disabled" },
                { 0x01, "Enabled" },
+               { 0x02, "Disabled, Extended Inactive State Link" },
+               { 0x03, "Enabled, Extended Inactive State Link" },
                { 0, NULL }
        };
 
-       if (tvb_length(tvb) > 0) {
+       if (tvb_captured_length(tvb) > 0) {
                parse_link_info_state(tree, tvb, 0, " 1", state_vals);
        }
-       if (tvb_length(tvb) > 5) {
+       if (tvb_captured_length(tvb) > 5) {
                parse_link_info_state(tree, tvb, 5, " 2", state_vals);
        }
-       if (tvb_length(tvb) > 10) {
+       if (tvb_captured_length(tvb) > 10) {
                parse_link_info_state(tree, tvb, 10, " 3", state_vals);
        }
-       if (tvb_length(tvb) > 15) {
+       if (tvb_captured_length(tvb) > 15) {
                parse_link_info_state(tree, tvb, 15, " 4", state_vals);
        }
 }
@@ -916,7 +1087,7 @@ rs12(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        v = tvb_get_guint8(tvb, 2);
        proto_tree_add_uint_format_value(tree, hf_ipmi_picmg_12_pwr_mult, tvb, 2, 1,
                        v, "%d.%dW", v / 10, v % 10);
-       max = tvb_length(tvb) - 3;
+       max = tvb_captured_length(tvb) - 3;
        if (max == 0) {
                max = 1; /* One byte is mandatory */
        } else if (max > 20) {
@@ -937,7 +1108,7 @@ rs12(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 static void
 rq13(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       if (tvb_length(tvb) > 0) {
+       if (tvb_captured_length(tvb) > 0) {
                proto_tree_add_item(tree, hf_ipmi_picmg_13_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -972,7 +1143,7 @@ rq15(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_item(tree, hf_ipmi_picmg_15_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_uint_format_value(tree, hf_ipmi_picmg_15_fan_level, tvb, 1, 1,
                        v, "%s", val_to_str(v, fan_level_vals, "%d"));
-       if (tvb_length(tvb) > 2) {
+       if (tvb_captured_length(tvb) > 2) {
                proto_tree_add_item(tree, hf_ipmi_picmg_15_local_enable, tvb, 2, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -993,10 +1164,10 @@ rs16(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        v = tvb_get_guint8(tvb, 0);
        proto_tree_add_uint_format_value(tree, hf_ipmi_picmg_16_override_level, tvb, 0, 1,
                        v, "%s", val_to_str(v, fan_level_vals, "%d"));
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                proto_tree_add_item(tree, hf_ipmi_picmg_16_local_level, tvb, 1, 1, ENC_LITTLE_ENDIAN);
        }
-       if (tvb_length(tvb) > 2) {
+       if (tvb_captured_length(tvb) > 2) {
                proto_tree_add_item(tree, hf_ipmi_picmg_16_local_enable, tvb, 2, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -1019,11 +1190,12 @@ rq17(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                { 0x02, "Notify" },
                { 0, NULL }
        };
-       guint to_shmm = ipmi_current_hdr->trg_sa == 0x20;
+       guint to_shmm = ipmi_get_hdr(pinfo)->rs_sa == 0x20;
        guint cmd = tvb_get_guint8(tvb, 0);
 
+       ipmi_set_data(pinfo, 0, (to_shmm << 8) | cmd);
+
        if (!tree) {
-               ipmi_setsaveddata(0, (to_shmm << 8) | cmd);
                return;
        }
 
@@ -1064,7 +1236,7 @@ rs17(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        guint32 val;
        guint8 status;
 
-       if (!ipmi_getsaveddata(0, &val)) {
+       if (!ipmi_get_data(pinfo, 0, &val)) {
                /* Without knowing the command, we cannot decipher the response */
                proto_tree_add_item(tree, hf_ipmi_picmg_17_status, tvb, 0, 1, ENC_LITTLE_ENDIAN);
                return;
@@ -1092,6 +1264,78 @@ rs18(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_item(tree, hf_ipmi_picmg_18_sensor_num, tvb, 1, 1, ENC_LITTLE_ENDIAN);
 }
 
+static void
+parse_amc_link_info_state(proto_tree *tree, tvbuff_t *tvb, guint offs)
+{
+       static const int *amc_link_info[] = {
+                       &hf_ipmi_picmg_linkinfo_amc_ports,
+                       &hf_ipmi_picmg_linkinfo_amc_type,
+                       &hf_ipmi_picmg_linkinfo_amc_type_ext,
+                       &hf_ipmi_picmg_linkinfo_amc_grpid,
+                       NULL };
+       static const int *amc_link_state[] = {
+                       &hf_ipmi_picmg_linkinfo_state_0,
+                       &hf_ipmi_picmg_linkinfo_state_1,
+                       NULL };
+
+       proto_tree_add_bitmask(tree, tvb, offs, hf_ipmi_picmg_linkinfo,
+                       ett_ipmi_picmg_link_info, amc_link_info, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, offs + 3, hf_ipmi_picmg_linkinfo_state,
+                       ett_ipmi_picmg_link_state, amc_link_state, ENC_LITTLE_ENDIAN);
+}
+
+static const int *amc_link_dev[] = {
+               &hf_ipmi_picmg_linkinfo_dev_id,
+               NULL };
+
+/* Set AMC Port State
+ */
+static void
+rq19(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_linkinfo_amc_chan, tvb, 0, 1,
+                       ENC_LITTLE_ENDIAN);
+       parse_amc_link_info_state(tree, tvb, 1);
+       if (tvb_captured_length(tvb) > 5) {
+               proto_tree_add_bitmask(tree, tvb, 5, hf_ipmi_picmg_linkinfo_dev,
+                               ett_ipmi_picmg_link_dev, amc_link_dev, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get AMC Port State
+ */
+static void
+rq1a(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_linkinfo_amc_chan, tvb, 0, 1,
+                       ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 1) {
+               proto_tree_add_bitmask(tree, tvb, 1, hf_ipmi_picmg_linkinfo_dev,
+                               ett_ipmi_picmg_link_state, amc_link_dev, ENC_LITTLE_ENDIAN);
+       }
+       if (tvb_captured_length(tvb) > 2) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_1a_flags, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+static void
+rs1a(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       guint len = tvb_captured_length(tvb);
+       if (len > 0) {
+               parse_amc_link_info_state(tree, tvb, 0);
+       }
+       if (len > 4) {
+               parse_amc_link_info_state(tree, tvb, 4);
+       }
+       if (len > 8) {
+               parse_amc_link_info_state(tree, tvb, 8);
+       }
+       if (len > 12) {
+               parse_amc_link_info_state(tree, tvb, 12);
+       }
+}
+
 /* Get Shelf Manager IPMB Address
  */
 static void
@@ -1109,7 +1353,7 @@ rq1c(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_item(tree, hf_ipmi_picmg_1c_fan_site_number, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(tree, hf_ipmi_picmg_1c_fan_enable_state, tvb, 1, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(tree, hf_ipmi_picmg_1c_fan_policy_timeout, tvb, 2, 1, ENC_LITTLE_ENDIAN);
-       if (tvb_length(tvb) > 3) {
+       if (tvb_captured_length(tvb) > 3) {
                proto_tree_add_item(tree, hf_ipmi_picmg_1c_site_number, tvb, 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(tree, hf_ipmi_picmg_1c_site_type, tvb, 4, 1, ENC_LITTLE_ENDIAN);
        }
@@ -1121,7 +1365,7 @@ static void
 rq1d(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_picmg_1d_fan_site_number, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                proto_tree_add_item(tree, hf_ipmi_picmg_1d_site_number, tvb, 1, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(tree, hf_ipmi_picmg_1d_site_type, tvb, 2, 1, ENC_LITTLE_ENDIAN);
        }
@@ -1131,7 +1375,7 @@ static void
 rs1d(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_picmg_1d_policy, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                proto_tree_add_item(tree, hf_ipmi_picmg_1d_coverage, tvb, 1, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -1185,7 +1429,7 @@ rq20(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_item(tree, hf_ipmi_picmg_20_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(tree, hf_ipmi_picmg_20_lockid, tvb, 1, 2, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(tree, hf_ipmi_picmg_20_offset, tvb, 3, 2, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_picmg_20_data, tvb, 5, tvb_length(tvb) - 5, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_picmg_20_data, tvb, 5, -1, ENC_NA);
 }
 
 static void
@@ -1233,8 +1477,8 @@ rs21(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 static void
 rq22(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
+       ipmi_set_data(pinfo, 0, tvb_get_guint8(tvb, 0));
        if (!tree) {
-               ipmi_setsaveddata(0, tvb_get_guint8(tvb, 0));
                return;
        }
        proto_tree_add_item(tree, hf_ipmi_picmg_22_feed_idx, tvb, 0, 1, ENC_LITTLE_ENDIAN);
@@ -1249,12 +1493,12 @@ rs22(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 
        proto_tree_add_item(tree, hf_ipmi_picmg_22_update_cnt, tvb, 0, 2, ENC_LITTLE_ENDIAN);
 
-       max = tvb_length(tvb) / 2 - 1;
+       max = tvb_captured_length(tvb) / 2 - 1;
        if (!max) {
                /* At least one shall be present */
                max = 1;
        }
-       ipmi_getsaveddata(0, &offs);
+       ipmi_get_data(pinfo, 0, &offs);
        for (i = 0; i < max; i++) {
                v = tvb_get_letohs(tvb, 2 + 2 * i);
                proto_tree_add_uint_format(tree, hf_ipmi_picmg_22_pwr_alloc, tvb, 2 + 2 * i, 2,
@@ -1262,6 +1506,392 @@ rs22(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        }
 }
 
+static const value_string picmg_23_slot_selectors[] = {
+       { 0, "MicroTCA Shelf within a Frame" },
+       { 1, "MicroTCA Carrier within a Shelf" },
+       { 2, "Slot within a MicroTCA Carrier" },
+       { 0, NULL }
+};
+
+static const value_string picmg_23_num_bases[] = {
+       { 0, "Zero-based" },
+       { 1, "One-based" },
+       { 0, NULL }
+};
+
+static const value_string picmg_23_orientations[] = {
+       { 0, "Vertical" },
+       { 1, "Horizontal" },
+       { 0, NULL }
+};
+
+/* Get Location Info
+ */
+static void
+rq23(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const int * picmg_23_rq_byte2[] = {
+               &hf_ipmi_picmg_23_slot_sel,
+               &hf_ipmi_picmg_23_carrier_num,
+               NULL
+       };
+
+       proto_tree_add_bitmask(tree, tvb, 0, hf_ipmi_picmg_23_rq_byte2,
+                       ett_ipmi_picmg_23_rq_byte2, picmg_23_rq_byte2,
+                       ENC_LITTLE_ENDIAN);
+       if ((tvb_get_guint8(tvb, 0) & 0xC0) == 0x80) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_01_rs_site_num,
+                               tvb, 1, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_01_rs_site_type,
+                               tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+static void
+rs23(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const int * picmg_23_rs_byte5[] = {
+               &hf_ipmi_picmg_23_slot_base,
+               &hf_ipmi_picmg_23_tier_base,
+               &hf_ipmi_picmg_23_orientation,
+               NULL
+       };
+
+       proto_tree_add_item(tree, hf_ipmi_picmg_23_slot_num,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_23_tier_num,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 2, hf_ipmi_picmg_23_rs_byte5,
+                       ett_ipmi_picmg_23_rs_byte5, picmg_23_rs_byte5,
+                       ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_23_origin_x,
+                       tvb, 3, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_23_origin_y,
+                       tvb, 5, 2, ENC_LITTLE_ENDIAN);
+}
+
+static const value_string picmg_24_controls[] = {
+       { 0, "Disable MP" },
+       { 1, "Enable MP" },
+       { 2, "De-assert ENABLE#" },
+       { 3, "Assert ENABLE#" },
+       { 4, "Disable PWR" },
+       { 5, "Enable PWR" },
+       { 0, NULL }
+};
+
+void
+fmt_power_amps(gchar *s, guint32 v)
+{
+       g_snprintf(s, ITEM_LABEL_LENGTH, "%d.%dA", v / 10, v % 10);
+}
+
+/* Power Channel Control
+ */
+static void
+rq24(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_24_channel,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_24_control,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_24_current,
+                       tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_24_primary_pm,
+                       tvb, 3, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_24_backup_pm,
+                       tvb, 4, 1, ENC_LITTLE_ENDIAN);
+}
+
+static const value_string picmg_25_fault_vals[] = {
+       { 0, "Redundant PM is not providing Payload Power current" },
+       { 1, "Redundant PM is providing Payload Power current" },
+       { 0, NULL }
+};
+
+static const true_false_string picmg_25_roles = {
+       "Primary",  "Redundant"
+};
+
+/* Get Power Channel Status
+ */
+static void
+rq25(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_25_start,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_25_count,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+static void
+rs25(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint * picmg_25_gstatus[] = {
+               &hf_ipmi_picmg_25_fault,
+               &hf_ipmi_picmg_25_pwr_good,
+               &hf_ipmi_picmg_25_mp_good,
+               &hf_ipmi_picmg_25_role,
+               NULL
+       };
+       static const gint * picmg_25_cstatus[] = {
+               &hf_ipmi_picmg_25_pwr_on,
+               &hf_ipmi_picmg_25_pwr_ovr,
+               &hf_ipmi_picmg_25_pwr,
+               &hf_ipmi_picmg_25_enable,
+               &hf_ipmi_picmg_25_mp_ovr,
+               &hf_ipmi_picmg_25_mp,
+               &hf_ipmi_picmg_25_ps1,
+               NULL
+       };
+
+       guint i, len = tvb_captured_length(tvb);
+
+       proto_tree_add_item(tree, hf_ipmi_picmg_25_max,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 1, hf_ipmi_picmg_25_gstatus,
+                       ett_ipmi_picmg_25_rs_byte4, picmg_25_gstatus,
+                       ENC_LITTLE_ENDIAN);
+
+       for (i = 2; i < len; i++) {
+               proto_tree_add_bitmask(tree, tvb, i, hf_ipmi_picmg_25_cstatus,
+                               ett_ipmi_picmg_25_rs_byte5, picmg_25_cstatus,
+                               ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* PM Reset
+ */
+static void
+rq26(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_26_pm_site,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get PM Status
+ */
+static void
+rs27(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint * picmg_27_status[] = {
+               &hf_ipmi_picmg_27_pm_healthy,
+               NULL
+       };
+       proto_tree_add_bitmask(tree, tvb, 0, hf_ipmi_picmg_27_rs_byte3,
+                       ett_ipmi_picmg_27_rs_byte3, picmg_27_status,
+                       ENC_LITTLE_ENDIAN);
+}
+
+static const value_string cc28[] = {
+       { 0x80, "Returned from autonomous mode" },
+       { 0, NULL }
+};
+
+void
+fmt_100ms(gchar *s, guint32 v)
+{
+       g_snprintf(s, ITEM_LABEL_LENGTH, "%d.%dS", v / 10, v % 10);
+}
+
+/* PM Heart-Beat
+ */
+static void
+rq28(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint * picmg_28_flags[] = {
+               &hf_ipmi_picmg_28_mch2,
+               &hf_ipmi_picmg_28_mch1,
+               NULL
+       };
+       proto_tree_add_item(tree, hf_ipmi_picmg_28_timeout,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 1, hf_ipmi_picmg_28_rq_byte3,
+                       ett_ipmi_picmg_28_rq_byte3, picmg_28_flags,
+                       ENC_LITTLE_ENDIAN);
+}
+
+static const true_false_string picmg_29_alarm_actions = {
+       "Produces(results in) an implementation-defined action",
+       "Not implemented"
+};
+
+static const true_false_string picmg_29_alarm_modes = {
+       "Can be controlled/enabled by the Set Telco Alarm State command",
+       "Can not be controlled/enabled"
+};
+
+/* Get Telco Alarm Capabilities
+ */
+static void
+rs29(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint * picmg_29_caps[] = {
+               &hf_ipmi_picmg_29_maj_rst,
+               &hf_ipmi_picmg_29_min_rst,
+               &hf_ipmi_picmg_29_alarm_cut,
+               &hf_ipmi_picmg_29_test_mode,
+               &hf_ipmi_picmg_29_pwr_alarm,
+               &hf_ipmi_picmg_29_minor_alarm,
+               &hf_ipmi_picmg_29_major_alarm,
+               &hf_ipmi_picmg_29_crit_alarm,
+               NULL
+       };
+       proto_tree_add_bitmask(tree, tvb, 0, hf_ipmi_picmg_29_rs_byte3,
+                       ett_ipmi_picmg_29_rs_byte3, picmg_29_caps,
+                       ENC_LITTLE_ENDIAN);
+}
+
+static const value_string picmg_2a_alarm_ids[] = {
+       { 0, "Critical Alarm" },
+       { 1, "Major Alarm" },
+       { 2, "Minor Alarm" },
+       { 3, "Power Alarm" },
+       { 4, "Alarm Cutoff" },
+       { 0, NULL }
+};
+
+static const value_string picmg_2a_alarm_ctrls[] = {
+       { 0, "off / cutoff disabled" },
+       { 1, "on / cutoff enabled" },
+       { 0xFF, "test mode" },
+       { 0, NULL }
+};
+
+/* Set Telco Alarm State
+ */
+static void
+rq2a(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_05_fruid,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_2a_alarm_id,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_2a_alarm_ctrl,
+                       tvb, 2, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get Telco Alarm State
+ */
+static void
+rq2b(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_05_fruid,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_2a_alarm_id,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+static void
+rs2b(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_2b_alarm_state,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
+static const value_string amc_clock_ids[] = {
+       { 1, "TCLKA(CLK1A)" },
+       { 2, "TCLKB(CLK1B)" },
+       { 3, "TCLKC(CLK1)" },
+       { 4, "TCLKD(CLK2A)" },
+       { 5, "FCLKA(CLK2B)" },
+       { 6, "CLK2" },
+       { 7, "CLK3A" },
+       { 8, "CLK3B" },
+       { 9, "CLK3" },
+       { 0, NULL }
+};
+
+static const value_string amc_clock_dirs[] = {
+       { 0, "Clock receiver" },
+       { 1, "Clock source" },
+       { 0, NULL }
+};
+
+static const value_string amc_clock_plls[] = {
+       { 0, "Default state" },
+       { 1, "Connect through PLL" },
+       { 2, "Bypass PLL" },
+       { 0, NULL }
+};
+
+static const range_string amc_clock_families[] = {
+       { 0, 0, "Unspecified" },
+       { 1, 1, "SONET/SDH/PDH" },
+       { 2, 2, "Reserved for PCI Express" },
+       { 3, 0xC8, "Reserved" },
+       { 0xC9, 0xFF, "Vendor defined" },
+       { 0, 0, NULL }
+};
+
+static const value_string amc_clock_resource_types[] = {
+       { 0, "On-Carrier device" },
+       { 1, "AMC module" },
+       { 2, "Backplane" },
+       { 3, "Reserved" },
+       { 0, NULL }
+};
+
+static const int * amc_clock_setting[] = {
+       &hf_ipmi_picmg_clock_pll,
+       &hf_ipmi_picmg_clock_dir,
+       &hf_ipmi_picmg_clock_state,
+       NULL
+};
+
+static const int * amc_clock_resource[] = {
+       &hf_ipmi_picmg_clock_resource_type,
+       &hf_ipmi_picmg_clock_resource_dev,
+       NULL
+};
+
+/* Set Clock State
+ */
+static void
+rq2c(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_clock_id, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_clock_cfg, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 2, hf_ipmi_picmg_clock_setting,
+                       ett_ipmi_picmg_clock_setting, amc_clock_setting, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 3) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_clock_family, tvb, 3, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_clock_accuracy, tvb, 4, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_clock_frequency, tvb, 5, 4, ENC_LITTLE_ENDIAN);
+       }
+       if (tvb_captured_length(tvb) > 9) {
+               proto_tree_add_bitmask(tree, tvb, 9, hf_ipmi_picmg_clock_resource,
+                               ett_ipmi_picmg_clock_res, amc_clock_resource, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get Clock State (request)
+ */
+static void
+rq2d(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_clock_id, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 1) {
+               proto_tree_add_bitmask(tree, tvb, 1, hf_ipmi_picmg_clock_resource,
+                               ett_ipmi_picmg_clock_res, amc_clock_resource, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get Clock State (response)
+ */
+static void
+rs2d(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_bitmask(tree, tvb, 0, hf_ipmi_picmg_clock_setting,
+                       ett_ipmi_picmg_clock_setting, amc_clock_setting, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 1) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_clock_cfg, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_clock_family, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_clock_accuracy, tvb, 3, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_clock_frequency, tvb, 4, 4, ENC_LITTLE_ENDIAN);
+       }
+}
+
 static void
 add_component_bits(proto_tree *tree, tvbuff_t *tvb, guint offs, const char *desc)
 {
@@ -1322,7 +1952,7 @@ parse_version(tvbuff_t *tvb, proto_tree *tree)
 static void
 prop_02(tvbuff_t *tvb, proto_tree *tree)
 {
-       guint len = tvb_length(tvb);
+       guint len = tvb_captured_length(tvb);
 
        if (len > 12) {
                len = 12;
@@ -1347,8 +1977,8 @@ rq2f(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        guint8 pno = tvb_get_guint8(tvb, 1);
        const char *desc;
 
+       ipmi_set_data(pinfo, 0, pno);
        if (!tree) {
-               ipmi_setsaveddata(0, pno);
                return;
        }
 
@@ -1372,9 +2002,9 @@ rs2f(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        const char *desc;
        proto_item *ti;
 
-       if (!ipmi_getsaveddata(0, &pno)) {
+       if (!ipmi_get_data(pinfo, 0, &pno)) {
                /* Can't parse further if property selector is not known */
-               proto_tree_add_item(tree, hf_ipmi_picmg_2f_prop_data, tvb, 0, tvb_length(tvb), ENC_NA);
+               proto_tree_add_item(tree, hf_ipmi_picmg_2f_prop_data, tvb, 0, -1, ENC_NA);
                return;
        }
 
@@ -1391,7 +2021,7 @@ rs2f(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        if (pno < array_length(compprops)) {
                compprops[pno].intrp(tvb, tree);
        } else {
-               proto_tree_add_item(tree, hf_ipmi_picmg_2f_prop_data, tvb, 0, tvb_length(tvb), ENC_NA);
+               proto_tree_add_item(tree, hf_ipmi_picmg_2f_prop_data, tvb, 0, -1, ENC_NA);
        }
 }
 
@@ -1431,13 +2061,13 @@ static void
 rq32(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_picmg_32_block, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_picmg_32_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_picmg_32_data, tvb, 1, -1, ENC_NA);
 }
 
 static void
 rs32(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       if (tvb_length(tvb) > 0) {
+       if (tvb_captured_length(tvb) > 0) {
                proto_tree_add_item(tree, hf_ipmi_picmg_32_sec_offs, tvb, 0, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(tree, hf_ipmi_picmg_32_sec_len, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        }
@@ -1484,7 +2114,7 @@ rs34(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        v = tvb_get_guint8(tvb, 1);
        proto_tree_add_uint_format_value(tree, hf_ipmi_picmg_34_ccode, tvb, 1, 1, v,
                        "%s (0x%02x)", ipmi_get_completion_code(v, c), v);
-       if (tvb_length(tvb) > 2) {
+       if (tvb_captured_length(tvb) > 2) {
                proto_tree_add_bitmask_text(tree, tvb, 2, 1, NULL, NULL,
                                ett_ipmi_picmg_34_byte3, byte3, ENC_LITTLE_ENDIAN, 0);
        }
@@ -1500,7 +2130,7 @@ static const value_string cc34[] = {
 static void
 rq35(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       if (tvb_length(tvb) > 0) {
+       if (tvb_captured_length(tvb) > 0) {
                proto_tree_add_item(tree, hf_ipmi_picmg_35_rollback_override, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        }
 }
@@ -1556,7 +2186,7 @@ rs37(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        static const gint *byte2[] = { &hf_ipmi_picmg_37_percent, NULL };
        const char *desc;
 
-       switch (ipmi_current_hdr->ccode) {
+       switch (ipmi_get_ccode(pinfo)) {
        case 0x00: desc = "Components completed rollback: "; break;
        case 0x80: desc = "Components (should be None): "; break;
        case 0x81: desc = "Components failed to rollback: "; break;
@@ -1564,12 +2194,198 @@ rs37(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        }
 
        add_component_bits(tree, tvb, 0, desc);
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                proto_tree_add_bitmask_text(tree, tvb, 1, 1, NULL, NULL,
                                ett_ipmi_picmg_37_byte2, byte2, ENC_LITTLE_ENDIAN, 0);
        }
 }
 
+/* Get HPM.x Capabilities
+ */
+static void
+rq3e(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_id, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
+static void
+rs3e(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint *hpm2_caps[] = {
+                       &hf_ipmi_picmg_hpm2_dyn_ssn,
+                       &hf_ipmi_picmg_hpm2_ver_chg,
+                       &hf_ipmi_picmg_hpm2_ext_mgt,
+                       &hf_ipmi_picmg_hpm2_pkt_trc,
+                       &hf_ipmi_picmg_hpm2_sol_ext,
+                       NULL };
+       guint8 hpm_x;
+
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_id, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_rev, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+
+       hpm_x = tvb_get_guint8(tvb, 0);
+
+       if (hpm_x == 2) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm2_mask, tvb, 2, 2, ENC_LITTLE_ENDIAN);
+               if (tvb_captured_length(tvb) > 4) {
+                       proto_tree_add_bitmask(tree, tvb, 4, hf_ipmi_picmg_hpm2_caps,
+                                       ett_ipmi_picmg_hpm_caps, hpm2_caps, ENC_LITTLE_ENDIAN);
+               }
+               if (tvb_captured_length(tvb) > 5) {
+                       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_oem_start,
+                                       tvb, 5, 1, ENC_LITTLE_ENDIAN);
+                       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_oem_rev,
+                                       tvb, 6, 1, ENC_LITTLE_ENDIAN);
+               }
+               if (tvb_captured_length(tvb) > 7) {
+                       proto_tree_add_item(tree, hf_ipmi_picmg_hpm2_sol_oem_start,
+                                       tvb, 7, 1, ENC_LITTLE_ENDIAN);
+                       proto_tree_add_item(tree, hf_ipmi_picmg_hpm2_sol_oem_rev,
+                                       tvb, 8, 1, ENC_LITTLE_ENDIAN);
+               }
+       } else if (hpm_x == 3) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_oem_start,
+                               tvb, 2, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_oem_rev,
+                               tvb, 3, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+static const value_string hpm2_func_selectors[] = {
+       { 0x0, "Create Credentials" },
+       { 0x1, "Get Session Info" },
+       { 0x2, "Get User Name, least significant bytes" },
+       { 0x3, "Get User Name, most significant bytes" },
+       { 0x4, "Get Password, least significant bytes" },
+       { 0x5, "Get Password, most significant bytes" },
+       { 0x6, "Get BMC Key, least significant bytes" },
+       { 0x7, "Get BMC Key, most significant bytes" },
+       { 0, NULL }
+};
+
+static const value_string hpm2_ipmi_revs[] = {
+       { 0x0, "IPMI 1.5 session" },
+       { 0x1, "IPMI 2.0 session" },
+       { 0, NULL }
+};
+
+static const value_string hpm2_auth_types[] = {
+       { 0x0, "None" },
+       { 0x1, "MD2" },
+       { 0x2, "MD5" },
+       { 0x4, "Straight password" },
+       { 0x5, "OEM" },
+       { 0, NULL }
+};
+
+/* Get Dynamic Credentials
+ */
+static void
+rq3f(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_cred_hnd,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_func_sel,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       if (!tvb_get_guint8(tvb, 1)) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_ipmi_rev,
+                               tvb, 2, 1, ENC_LITTLE_ENDIAN);
+               if (tvb_get_guint8(tvb, 2)) {
+                       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_cipher_id,
+                                       tvb, 3, 1, ENC_LITTLE_ENDIAN);
+               } else {
+                       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_auth_type,
+                                       tvb, 3, 1, ENC_LITTLE_ENDIAN);
+               }
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_priv_level,
+                               tvb, 4, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_chn_num,
+                               tvb, 5, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_avail_time,
+                               tvb, 6, 4, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_21_ipaddr,
+                               tvb, 10, 4, ENC_BIG_ENDIAN);
+       }
+}
+
+static void
+rs3f(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       guint8 func;
+
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_cred_hnd,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_func_sel,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+
+       func = tvb_get_guint8(tvb, 1);
+
+       switch (func) {
+       case 0:
+       case 1:
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_avail_time,
+                               tvb, 2, 4, ENC_LITTLE_ENDIAN);
+               break;
+       case 2:
+       case 3:
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_user_name,
+                               tvb, 2, 8, ENC_NA);
+               break;
+       case 4:
+       case 5:
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_user_pwd,
+                               tvb, 2, 10, ENC_NA);
+               break;
+       case 6:
+       case 7:
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_bmc_key,
+                               tvb, 2, 10, ENC_NA);
+               break;
+       }
+}
+
+static const value_string picmg40_operations[] = {
+       { 0x0, "Initiate new operation" },
+       { 0x1, "Poll for completion status" },
+       { 0, NULL }
+};
+
+static const value_string cc40[] = {
+       { 0x80, "In progress" },
+       { 0x81, "No previous establishment request" },
+       { 0x82, "LAN sessions are not supported" },
+       { 0x83, "Error trying to establish a session" },
+       { 0, NULL }
+};
+
+/* Get Session Handle for Explicit LAN Bridging
+ */
+static void
+rq40(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_01_rs_ipmbaddr,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_01_rs_fruid,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 2) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_operation,
+                               tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+static void
+rs40(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_chn_num,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_ssn_hnd,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_ssn_hnd,
+                       tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_ssn_hnd,
+                       tvb, 3, 1, ENC_LITTLE_ENDIAN);
+}
+
 static const value_string cc37[] = {
        { 0x80, "Rollback in progress" },
        { 0x81, "Rollback failure" },
@@ -1585,65 +2401,270 @@ static const value_string cc38[] = {
        { 0, NULL }
 };
 
+static const value_string hpm_x_ids[] = {
+       { 0x02, "HPM.2" },
+       { 0x03, "HPM.3" },
+       { 0, NULL }
+};
+
+/* Get ATCA Extended Management Resources
+ */
+static void
+rs41(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_power_draw,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_base_channels,
+                       tvb, 1, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_fabric_channels,
+                       tvb, 3, 2, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 5) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_update_channels,
+                               tvb, 5, 1, ENC_LITTLE_ENDIAN);
+       }
+       if (tvb_captured_length(tvb) > 6) {
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_cross_channels,
+                               tvb, 6, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+
+static const value_string amc_resource_types[] = {
+       { 0, "On-Carrier device (IRTM, MCH)" },
+       { 1, "AMC module" },
+       { 0, NULL }
+};
+
+/* Get AMC Extended Management Resources
+ */
+static void
+rs42(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint *amc_resource_type[] = {
+                       &hf_ipmi_picmg_linkinfo_dev_type,
+                       &hf_ipmi_picmg_linkinfo_dev_id,
+                       NULL };
+       guint8 num, i;
+
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_power_draw,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_num_chn_desc,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+
+       num = tvb_get_guint8(tvb, 1);
+
+       for (i = 0; i < num; i++) {
+               proto_tree_add_bitmask(tree, tvb, 2 + i * 5,
+                               hf_ipmi_picmg_linkinfo_dev, ett_ipmi_picmg_link_dev,
+                               amc_resource_type, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_ipmi_picmg_hpm_chn_mask,
+                               tvb, 3 + i * 5, 4, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Set ATCA Extended Management State
+ */
+static void
+rq43(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_ext_mgmt_state,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_polling_period,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get ATCA Extended Management State
+ */
+static void
+rs44(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_ext_mgmt_state,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
+static const value_string auth_pwr_states[] = {
+       { 0, "Normal. Full Payload Power." },
+       { 1, "Extended Management Power" },
+       { 0, NULL }
+};
+
+static const value_string amc_pwr_states[] = {
+       { 0, "Standard Management Power" },
+       { 1, "Extended Management Power" },
+       { 2, "Full Payload Power." },
+       { 0, NULL }
+};
+
+/* Set AMC Power State
+ */
+static void
+rq45(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_auth_pwr_state,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get AMC Power State
+ */
+static void
+rs46(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_auth_pwr_state,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg_hpm_amc_pwr_state,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+static const value_string picmg47_flags[] = {
+       { 0, "Assign Payload Instance." },
+       { 1, "Return Assigned Instance" },
+       { 0, NULL }
+};
+
+static const value_string picmg47_states[] = {
+       { 0, "No session currently opened on this System Serial Port." },
+       { 1, "A session already opened on this System Serial Port." },
+       { 0, NULL }
+};
+
+static const value_string cc47[] = {
+       { 0x80, "Payload Instance can not be assigned at this time." },
+       { 0, NULL }
+};
+
+/* Assign SOL Payload Instance
+ */
+static void
+rq47(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg47_port,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_ipmi_picmg47_flags,
+                       tvb, 1, 1, ENC_LITTLE_ENDIAN);
+
+}
+
+static void
+rs47(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint *byte1[] = {
+                       &hf_ipmi_picmg47_state,
+                       &hf_ipmi_picmg47_instance,
+                       NULL };
+
+       proto_tree_add_bitmask(tree, tvb, 0, hf_ipmi_picmg47_assignment,
+                       ett_ipmi_picmg_47_byte1, byte1, ENC_LITTLE_ENDIAN);
+}
+
+static const value_string picmg48_fru_types[] = {
+       { 0, "None" },
+       { 1, "IPMB-L address of subsidiary MMC" },
+       { 2, "IPMB-0 address of subsidiary EMMC" },
+       { 3, "FRU Device ID of subsidiary FRU" },
+       { 0, NULL }
+};
+
+static const value_string picmg48_ip_sources[] = {
+       { 0, "Not configured for HPM.3" },
+       { 2, "DHCP assigned" },
+       { 4, "DHCP Proxy assigned" },
+       { 0, NULL }
+};
+
+/* Get IP Address Source
+ */
+static void
+rq48(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg_01_rs_ipmbaddr,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 1) {
+               proto_tree_add_item(tree, hf_ipmi_picmg48_sub_fru_type,
+                               tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       }
+       if (tvb_captured_length(tvb) > 2) {
+               proto_tree_add_item(tree, hf_ipmi_picmg48_sub_fru_id,
+                               tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+static void
+rs48(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_ipmi_picmg48_ip_source,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
 static ipmi_cmd_t cmd_picmg[] = {
-  /* AdvancedTCA Commands */
-  { 0x00, NULL, rs00, NULL, NULL, "[ATCA] Get PICMG Properties", 0 },
-  { 0x01, rq01, rs01, NULL, NULL, "[ATCA] Get Address Info", 0 },
-  { 0x02, NULL, rs02, NULL, NULL, "[ATCA] Get Shelf Address Info", 0 },
-  { 0x03, rq03, NULL, NULL, NULL, "[ATCA] Set Shelf Address Info", 0 },
-  { 0x04, rq04, NULL, NULL, NULL, "[ATCA] FRU Control", 0 },
-  { 0x05, rq05, rs05, NULL, NULL, "[ATCA] Get FRU LED Properties", 0 },
-  { 0x06, rq06, rs06, NULL, NULL, "[ATCA] Get LED Color Capabilities", 0 },
-  { 0x07, rq07, NULL, NULL, NULL, "[ATCA] Set FRU LED State", 0 },
-  { 0x08, rq08, rs08, NULL, NULL, "[ATCA] Get FRU LED State", 0 },
-  { 0x09, rq09, NULL, NULL, NULL, "[ATCA] Set IPMB State", 0 },
-  { 0x0a, rq0a, NULL, NULL, NULL, "[ATCA] Set FRU Activation Policy", 0 },
-  { 0x0b, rq0b, rs0b, NULL, NULL, "[ATCA] Get FRU Activation Policy", 0 },
-  { 0x0c, rq0c, NULL, NULL, NULL, "[ATCA] Set FRU Activation", 0 },
-  { 0x0d, rq0d, rs0d, NULL, NULL, "[ATCA] Get Device Locator Record ID", 0 },
-  { 0x0e, rq0e, NULL, NULL, NULL, "[ATCA] Set Port State", 0 },
-  { 0x0f, rq0f, rs0f, NULL, NULL, "[ATCA] Get Port State", 0 },
-  { 0x10, rq10, rs10, NULL, NULL, "[ATCA] Compute Power Properties", 0 },
-  { 0x11, rq11, NULL, NULL, NULL, "[ATCA] Set Power Level", 0 },
-  { 0x12, rq12, rs12, NULL, NULL, "[ATCA] Get Power Level", 0 },
-  { 0x13, rq13, NULL, NULL, NULL, "[ATCA] Renegotiate Power", 0 },
-  { 0x14, rq14, rs14, NULL, NULL, "[ATCA] Get Fan Speed Properties", 0 },
-  { 0x15, rq15, NULL, NULL, NULL, "[ATCA] Set Fan Level", 0 },
-  { 0x16, rq16, rs16, NULL, NULL, "[ATCA] Get Fan Level", 0 },
-  { 0x17, rq17, rs17, NULL, NULL, "[ATCA] Bused Resource Control", CMD_CALLRQ },
-  { 0x18, rq18, rs18, NULL, NULL, "[ATCA] Get IPMB Link Info", 0 },
-  { 0x19, IPMI_TBD,   NULL, NULL, "[AMC.0] Set AMC Port State", 0 },
-  { 0x1a, IPMI_TBD,   NULL, NULL, "[AMC.0] Get AMC Port State", 0 },
-  { 0x1b, NULL, rs1b, NULL, NULL, "[ATCA] Get Shelf Manager IPMB Address", 0 },
-  { 0x1c, rq1c, NULL, NULL, NULL, "[ATCA] Set Fan Policy", 0 },
-  { 0x1d, rq1d, rs1d, NULL, NULL, "[ATCA] Get Fan Policy", 0 },
-  { 0x1e, rq1e, rs1e, NULL, NULL, "[ATCA] FRU Control Capabilities", 0 },
-  { 0x1f, rq1f, rs1f, cc1f, NULL, "[ATCA] FRU Inventory Device Lock Control", 0 },
-  { 0x20, rq20, rs20, cc20, NULL, "[ATCA] FRU Inventory Device Write", 0 },
-  { 0x21, rq21, rs21, NULL, NULL, "[ATCA] Get Shelf Manager IP Addresses", 0 },
-  { 0x22, rq22, rs22, NULL, NULL, "[ATCA] Get Shelf Power Allocation", CMD_CALLRQ },
-  { 0x23, IPMI_TBD,   NULL, NULL, "[uTCA] Get Location Information", 0 },
-  { 0x24, IPMI_TBD,   NULL, NULL, "[uTCA] Power Channel Control", 0 },
-  { 0x25, IPMI_TBD,   NULL, NULL, "[uTCA] Get Power Channel Status", 0 },
-  { 0x26, IPMI_TBD,   NULL, NULL, "[uTCA] PM Reset", 0 },
-  { 0x27, IPMI_TBD,   NULL, NULL, "[uTCA] Get PM Status", 0 },
-  { 0x28, IPMI_TBD,   NULL, NULL, "[uTCA] PM Heartbeat", 0 },
-  { 0x29, IPMI_TBD,   NULL, NULL, "[uTCA] Get Telco Alarm Capability", 0 },
-  { 0x2a, IPMI_TBD,   NULL, NULL, "[uTCA] Set Telco Alarm State", 0 },
-  { 0x2b, IPMI_TBD,   NULL, NULL, "[uTCA] Get Telco Alarm State", 0 },
-  { 0x2c, IPMI_TBD,   NULL, NULL, "[AMC.0] Set Clock State", 0 },
-  { 0x2d, IPMI_TBD,   NULL, NULL, "[AMC.0] Get Clock State", 0 },
-  { 0x2e, NULL, rs2e, cc2e, NULL, "[HPM.1] Get Target Upgrade Capabilities", 0 },
-  { 0x2f, rq2f, rs2f, cc2f, NULL, "[HPM.1] Get Component Properties", CMD_CALLRQ },
-  { 0x30, NULL, NULL, cc30, NULL, "[HPM.1] Abort Firmware Upgrade", 0 },
-  { 0x31, rq31, NULL, cc31, NULL, "[HPM.1] Initiate Upgrade Action", 0 },
-  { 0x32, rq32, rs32, cc32, NULL, "[HPM.1] Upload Firmware Block", 0 },
-  { 0x33, rq33, NULL, cc33, NULL, "[HPM.1] Finish Firmware Upload", 0 },
-  { 0x34, NULL, rs34, cc34, NULL, "[HPM.1] Get Upgrade Status", 0 },
-  { 0x35, rq35, NULL, cc35, NULL, "[HPM.1] Activate Firmware", 0 },
-  { 0x36, NULL, rs36, cc36, NULL, "[HPM.1] Query Self-test Results", 0 },
-  { 0x37, NULL, rs37, cc37, NULL, "[HPM.1] Query Rollback Status", 0 },
-  { 0x38, NULL, NULL, cc38, NULL, "[HPM.1] Initiate Manual Rollback", 0 },
+       /* AdvancedTCA Commands */
+       { 0x00, NULL, rs00, NULL, NULL, "[ATCA] Get PICMG Properties", 0 },
+       { 0x01, rq01, rs01, NULL, NULL, "[ATCA] Get Address Info", 0 },
+       { 0x02, NULL, rs02, NULL, NULL, "[ATCA] Get Shelf Address Info", 0 },
+       { 0x03, rq03, NULL, NULL, NULL, "[ATCA] Set Shelf Address Info", 0 },
+       { 0x04, rq04, NULL, NULL, NULL, "[ATCA] FRU Control", 0 },
+       { 0x05, rq05, rs05, NULL, NULL, "[ATCA] Get FRU LED Properties", 0 },
+       { 0x06, rq06, rs06, NULL, NULL, "[ATCA] Get LED Color Capabilities", 0 },
+       { 0x07, rq07, NULL, NULL, NULL, "[ATCA] Set FRU LED State", 0 },
+       { 0x08, rq08, rs08, NULL, NULL, "[ATCA] Get FRU LED State", 0 },
+       { 0x09, rq09, NULL, NULL, NULL, "[ATCA] Set IPMB State", 0 },
+       { 0x0a, rq0a, NULL, NULL, NULL, "[ATCA] Set FRU Activation Policy", 0 },
+       { 0x0b, rq0b, rs0b, NULL, NULL, "[ATCA] Get FRU Activation Policy", 0 },
+       { 0x0c, rq0c, NULL, NULL, NULL, "[ATCA] Set FRU Activation", 0 },
+       { 0x0d, rq0d, rs0d, NULL, NULL, "[ATCA] Get Device Locator Record ID", 0 },
+       { 0x0e, rq0e, NULL, NULL, NULL, "[ATCA] Set Port State", 0 },
+       { 0x0f, rq0f, rs0f, NULL, NULL, "[ATCA] Get Port State", 0 },
+       { 0x10, rq10, rs10, NULL, NULL, "[ATCA] Compute Power Properties", 0 },
+       { 0x11, rq11, NULL, NULL, NULL, "[ATCA] Set Power Level", 0 },
+       { 0x12, rq12, rs12, NULL, NULL, "[ATCA] Get Power Level", 0 },
+       { 0x13, rq13, NULL, NULL, NULL, "[ATCA] Renegotiate Power", 0 },
+       { 0x14, rq14, rs14, NULL, NULL, "[ATCA] Get Fan Speed Properties", 0 },
+       { 0x15, rq15, NULL, NULL, NULL, "[ATCA] Set Fan Level", 0 },
+       { 0x16, rq16, rs16, NULL, NULL, "[ATCA] Get Fan Level", 0 },
+       { 0x17, rq17, rs17, NULL, NULL, "[ATCA] Bused Resource Control", CMD_CALLRQ },
+       { 0x18, rq18, rs18, NULL, NULL, "[ATCA] Get IPMB Link Info", 0 },
+       { 0x19, rq19, NULL, NULL, NULL, "[AMC.0] Set AMC Port State", 0 },
+       { 0x1a, rq1a, rs1a, NULL, NULL, "[AMC.0] Get AMC Port State", 0 },
+       { 0x1b, NULL, rs1b, NULL, NULL, "[ATCA] Get Shelf Manager IPMB Address", 0 },
+       { 0x1c, rq1c, NULL, NULL, NULL, "[ATCA] Set Fan Policy", 0 },
+       { 0x1d, rq1d, rs1d, NULL, NULL, "[ATCA] Get Fan Policy", 0 },
+       { 0x1e, rq1e, rs1e, NULL, NULL, "[ATCA] FRU Control Capabilities", 0 },
+       { 0x1f, rq1f, rs1f, cc1f, NULL, "[ATCA] FRU Inventory Device Lock Control", 0 },
+       { 0x20, rq20, rs20, cc20, NULL, "[ATCA] FRU Inventory Device Write", 0 },
+       { 0x21, rq21, rs21, NULL, NULL, "[ATCA] Get Shelf Manager IP Addresses", 0 },
+       { 0x22, rq22, rs22, NULL, NULL, "[ATCA] Get Shelf Power Allocation", CMD_CALLRQ },
+       { 0x23, rq23, rs23, NULL, NULL, "[uTCA] Get Location Information", 0 },
+       { 0x24, rq24, NULL, NULL, NULL, "[uTCA] Power Channel Control", 0 },
+       { 0x25, rq25, rs25, NULL, NULL, "[uTCA] Get Power Channel Status", 0 },
+       { 0x26, rq26, NULL, NULL, NULL, "[uTCA] PM Reset", 0 },
+       { 0x27, rq26, rs27, NULL, NULL, "[uTCA] Get PM Status", 0 },
+       { 0x28, rq28, NULL, cc28, NULL, "[uTCA] PM Heartbeat", 0 },
+       { 0x29, rq05, rs29, NULL, NULL, "[uTCA] Get Telco Alarm Capability", 0 },
+       { 0x2a, rq2a, NULL, NULL, NULL, "[uTCA] Set Telco Alarm State", 0 },
+       { 0x2b, rq2b, rs2b, NULL, NULL, "[uTCA] Get Telco Alarm State", 0 },
+       { 0x2c, rq2c, NULL, NULL, NULL, "[AMC.0] Set Clock State", 0 },
+       { 0x2d, rq2d, rs2d, NULL, NULL, "[AMC.0] Get Clock State", 0 },
+       { 0x2e, NULL, rs2e, cc2e, NULL, "[HPM.1] Get Target Upgrade Capabilities", 0 },
+       { 0x2f, rq2f, rs2f, cc2f, NULL, "[HPM.1] Get Component Properties", CMD_CALLRQ },
+       { 0x30, NULL, NULL, cc30, NULL, "[HPM.1] Abort Firmware Upgrade", 0 },
+       { 0x31, rq31, NULL, cc31, NULL, "[HPM.1] Initiate Upgrade Action", 0 },
+       { 0x32, rq32, rs32, cc32, NULL, "[HPM.1] Upload Firmware Block", 0 },
+       { 0x33, rq33, NULL, cc33, NULL, "[HPM.1] Finish Firmware Upload", 0 },
+       { 0x34, NULL, rs34, cc34, NULL, "[HPM.1] Get Upgrade Status", 0 },
+       { 0x35, rq35, NULL, cc35, NULL, "[HPM.1] Activate Firmware", 0 },
+       { 0x36, NULL, rs36, cc36, NULL, "[HPM.1] Query Self-test Results", 0 },
+       { 0x37, NULL, rs37, cc37, NULL, "[HPM.1] Query Rollback Status", 0 },
+       { 0x38, NULL, NULL, cc38, NULL, "[HPM.1] Initiate Manual Rollback", 0 },
+       { 0x3e, rq3e, rs3e, NULL, NULL, "[HPM.2] Get HPM.x Capabilities", 0 },
+       { 0x3f, rq3f, rs3f, NULL, NULL, "[HPM.2] Get Dynamic Credentials", 0 },
+       { 0x40, rq40, rs40, cc40, NULL, "[HPM.2] Get Session Handle for Explicit LAN Bridging", 0 },
+       { 0x41, NULL, rs41, NULL, NULL, "[HPM.2] Get ATCA Extended Management Resources", 0 },
+       { 0x42, NULL, rs42, NULL, NULL, "[HPM.2] Get AMC Extended Management Resources", 0 },
+       { 0x43, rq43, NULL, NULL, NULL, "[HPM.2] Set ATCA Extended Management State", 0 },
+       { 0x44, NULL, rs44, NULL, NULL, "[HPM.2] Get ATCA Extended Management State", 0 },
+       { 0x45, rq45, NULL, NULL, NULL, "[HPM.2] Set AMC Power State", 0 },
+       { 0x46, NULL, rs46, NULL, NULL, "[HPM.2] Get AMC Power State", 0 },
+       { 0x47, rq47, rs47, cc47, NULL, "[HPM.2] Assign SOL Payload Instance", 0 },
+       { 0x48, rq48, rs48, NULL, NULL, "[HPM.3] Get IP Address Source", 0 }
 };
 
 void
@@ -1680,7 +2701,77 @@ ipmi_register_picmg(gint proto_ipmi)
                                "ipmi.linkinfo.chan", FT_UINT32, BASE_DEC, NULL, 0x0000003f, NULL, HFILL }},
                { &hf_ipmi_picmg_linkinfo_state,
                        { "State",
-                               "ipmi.picmg0e.state", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+                               "ipmi.linkinfo.state", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo,
+                       { "Link Info",
+                               "ipmi.linkinfo", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_amc_chan,
+                       { "Channel",
+                               "ipmi.linkinfo.chan", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_amc_ports,
+                       { "Ports",
+                               "ipmi.linkinfo.ports", FT_UINT24, BASE_HEX, VALS(linkinfo_ports_vals), 0x00000f, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_amc_type,
+                       { "Type",
+                               "ipmi.linkinfo.type", FT_UINT24, BASE_HEX, VALS(linkinfo_amc_type_vals), 0x000ff0, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_amc_type_ext,
+                       { "Type extension",
+                               "ipmi.linkinfo.type_ext", FT_UINT24, BASE_HEX, NULL, 0x00f000, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_amc_grpid,
+                       { "Grouping ID",
+                               "ipmi.linkinfo.grpid", FT_UINT24, BASE_DEC, NULL, 0xff0000, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_state_0,
+                       { "Enabled",
+                               "ipmi.linkinfo.state0", FT_BOOLEAN, 8, NULL, 0x1, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_state_1,
+                       { "Extended Management Link",
+                               "ipmi.linkinfo.state1", FT_BOOLEAN, 8, NULL, 0x2, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_dev,
+                       { "On-Carrier Device",
+                               "ipmi.linkinfo.dev", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_dev_type,
+                       { "Device Type",
+                               "ipmi.linkinfo.dev.type", FT_UINT8, BASE_DEC, VALS(amc_resource_types), 0x80, NULL, HFILL }},
+               { &hf_ipmi_picmg_linkinfo_dev_id,
+                       { "Device ID",
+                               "ipmi.linkinfo.dev.id", FT_UINT8, BASE_DEC_HEX, NULL, 0xF, NULL, HFILL }},
+
+               { &hf_ipmi_picmg_clock_id,
+                       { "Clock ID",
+                               "ipmi.clock.id", FT_UINT8, BASE_HEX, VALS(amc_clock_ids), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_cfg,
+                       { "Clock Configuration Descriptor Index",
+                               "ipmi.clock.cfg", FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_setting,
+                       { "Clock Setting",
+                               "ipmi.clock.setting", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_state,
+                       { "Clock State",
+                               "ipmi.clock.state", FT_UINT8, BASE_DEC, VALS(enable_vals), 0x8, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_dir,
+                       { "Clock Direction",
+                               "ipmi.clock.dir", FT_UINT8, BASE_DEC, VALS(amc_clock_dirs), 0x4, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_pll,
+                       { "PLL Control",
+                               "ipmi.clock.pll", FT_UINT8, BASE_DEC, VALS(amc_clock_plls), 0x3, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_family,
+                       { "Clock Family",
+                               "ipmi.clock.family", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(amc_clock_families), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_accuracy,
+                       { "Clock Accuracy",
+                               "ipmi.clock.accu", FT_UINT8, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_frequency,
+                       { "Clock Frequency",
+                               "ipmi.clock.freq", FT_UINT32, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_resource,
+                       { "Clock Resource ID",
+                               "ipmi.clock.res", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_resource_type,
+                       { "Resource Type",
+                               "ipmi.clock.res.type", FT_UINT8, BASE_HEX, VALS(amc_clock_resource_types), 0xC0, NULL, HFILL }},
+               { &hf_ipmi_picmg_clock_resource_dev,
+                       { "Device ID",
+                               "ipmi.clock.res.id", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
 
                { &hf_ipmi_picmg_00_version,
                        { "PICMG Extension Version",
@@ -1708,7 +2799,7 @@ ipmi_register_picmg(gint proto_ipmi)
                        { "Hardware Address",
                                "ipmi.picmg01.rs_hwaddr", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_picmg_01_rs_ipmbaddr,
-                       { "IPMB-0 Address",
+                       { "IPMB Address",
                                "ipmi.picmg01.rs_ipmbaddr", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_picmg_01_rs_rsrv,
                        { "Reserved (shall be 0xFF)",
@@ -1971,6 +3062,10 @@ ipmi_register_picmg(gint proto_ipmi)
                        { "Sensor Number",
                                "ipmi.picmg18.sensor_num", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
 
+               { &hf_ipmi_picmg_1a_flags,
+                       { "Extended Request Flags",
+                               "ipmi.picmg1a.flags", FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+
                { &hf_ipmi_picmg_1b_addr_active,
                        { "Active Shelf Manager IPMB Address",
                                "ipmi.picmg1b.addr_active", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
@@ -2272,10 +3367,312 @@ ipmi_register_picmg(gint proto_ipmi)
                        { "Estimated percentage complete",
                                "ipmi.picmg37.percent", FT_UINT8, BASE_CUSTOM, ipmi_fmt_percent, 0x7f, NULL, HFILL }},
 
+               { &hf_ipmi_picmg_hpm_id,
+                       { "HPM.x Identifier",
+                               "ipmi.picmg.hpm.id", FT_UINT8, BASE_HEX, VALS(hpm_x_ids), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_rev,
+                       { "HPM.x Revision Identifier",
+                               "ipmi.picmg.hpm.rev", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_mask,
+                       { "IPMI LAN Channel Mask",
+                               "ipmi.picmg.hpm2.mask", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_caps,
+                       { "HPM.2 Capabilities",
+                               "ipmi.picmg.hpm2.caps", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_dyn_ssn,
+                       { "Dynamic Sessions",
+                               "ipmi.picmg.hpm2.dynssn", FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_ver_chg,
+                       { "Version Change Sensor for LAN Configuration",
+                               "ipmi.picmg.hpm2.verchg", FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_ext_mgt,
+                       { "Extended Inactive State Management",
+                               "ipmi.picmg.hpm2.extmgt", FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_pkt_trc,
+                       { "IPMI Channel Packet Trace",
+                               "ipmi.picmg.hpm2.pkttrc", FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_sol_ext,
+                       { "SOL Extensions",
+                               "ipmi.picmg.hpm2.solext", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_oem_start,
+                       { "OEM LAN Parameters Start Location",
+                               "ipmi.picmg.hpm.oem.start", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_oem_rev,
+                       { "OEM LAN Parameters Blocks Revision Number",
+                               "ipmi.picmg.hpm.oem.rev", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_sol_oem_start,
+                       { "OEM SOL Parameters Start Location",
+                               "ipmi.picmg.hpm2.sol.oem.start", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm2_sol_oem_rev,
+                       { "OEM SOL Parameters Blocks Revision Number",
+                               "ipmi.picmg.hpm2.sol.oem.rev", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_cred_hnd,
+                       { "Credentials Handle",
+                               "ipmi.picmg.hpm.cred.hnd", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_func_sel,
+                       { "Function Selector",
+                               "ipmi.picmg.hpm.func.sel", FT_UINT8, BASE_DEC, VALS(hpm2_func_selectors), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_ipmi_rev,
+                       { "IPMI Revision",
+                               "ipmi.picmg.hpm.ipmi.rev", FT_UINT8, BASE_HEX, VALS(hpm2_ipmi_revs), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_auth_type,
+                       { "Authentication Type",
+                               "ipmi.picmg.hpm.auth.type", FT_UINT8, BASE_HEX, VALS(hpm2_auth_types), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_cipher_id,
+                       { "Cipher Suite ID",
+                               "ipmi.picmg.hpm.cipher", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_priv_level,
+                       { "Maximum Privilege Level",
+                               "ipmi.picmg.hpm.priv", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_chn_num,
+                       { "IPMI Lan Channel Number",
+                               "ipmi.picmg.hpm.chn.num", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_avail_time,
+                       { "Availability Time",
+                               "ipmi.picmg.hpm.avail", FT_UINT32, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_user_name,
+                       { "User Name",
+                               "ipmi.picmg.hpm.user.name", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_user_pwd,
+                       { "User Password",
+                               "ipmi.picmg.hpm.user.pwd", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_bmc_key,
+                       { "BMC Key",
+                               "ipmi.picmg.hpm.bmc.key", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_operation,
+                       { "Command Operation Mode",
+                               "ipmi.picmg.hpm.operation", FT_UINT8, BASE_DEC, VALS(picmg40_operations), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_ssn_hnd,
+                       { "Session Handle",
+                               "ipmi.picmg.hpm.ssn.hnd", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_power_draw,
+                       { "Extended Management Power Draw",
+                               "ipmi.picmg.hpm.pwr.draw", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_base_channels,
+                       { "Base Interface Channels",
+                               "ipmi.picmg.hpm.base.chn", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_fabric_channels,
+                       { "Fabric Interface Channels",
+                               "ipmi.picmg.hpm.base.chn", FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_update_channels,
+                       { "Update Channels",
+                               "ipmi.picmg.hpm.upd.chn", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_cross_channels,
+                       { "ShMC Cross-Connect Channels",
+                               "ipmi.picmg.hpm.cross.chn", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_num_chn_desc,
+                       { "Number of Channel Descriptors",
+                               "ipmi.picmg.hpm.num.chn.desc", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_chn_mask,
+                       { "Channel Bitmask",
+                               "ipmi.picmg.hpm.chn.mask", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_ext_mgmt_state,
+                       { "Extended Management State",
+                               "ipmi.picmg.hpm.ext.mgmt.state", FT_UINT8, BASE_DEC, VALS(enable_vals), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_polling_period,
+                       { "Polling Period",
+                               "ipmi.picmg.hpm.poll.period", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_auth_pwr_state,
+                       { "Authorized Power State",
+                               "ipmi.picmg.hpm.auth.pwr", FT_UINT8, BASE_DEC, VALS(auth_pwr_states), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_hpm_amc_pwr_state,
+                       { "Actual Power State",
+                               "ipmi.picmg.hpm.amc.pwr", FT_UINT8, BASE_DEC, VALS(amc_pwr_states), 0, NULL, HFILL }},
+
+               { &hf_ipmi_picmg47_port,
+                       { "System Serial Port Number",
+                               "ipmi.picmg47.port", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg47_flags,
+                       { "Flags",
+                               "ipmi.picmg47.flags", FT_UINT8, BASE_DEC, VALS(picmg47_flags), 0x01, NULL, HFILL }},
+               { &hf_ipmi_picmg47_assignment,
+                       { "Assigned Instance",
+                               "ipmi.picmg47.assign", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg47_state,
+                       { "Serial port assigned to instance state",
+                               "ipmi.picmg47.state", FT_UINT8, BASE_DEC, VALS(picmg47_states), 0x80, NULL, HFILL }},
+               { &hf_ipmi_picmg47_instance,
+                       { "Payload instance number",
+                               "ipmi.picmg47.instance", FT_UINT8, BASE_DEC, NULL, 0x0F, NULL, HFILL }},
+
+               { &hf_ipmi_picmg48_sub_fru_type,
+                       { "Subsidiary FRU Identifier Type",
+                               "ipmi.picmg48.fru.type", FT_UINT8, BASE_DEC, VALS(picmg48_fru_types), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg48_sub_fru_id,
+                       { "Subsidiary FRU Identifier",
+                               "ipmi.picmg48.fru.id", FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg48_ip_source,
+                       { "IP Address Source",
+                               "ipmi.picmg48.ip.source", FT_UINT8, BASE_DEC, VALS(picmg48_ip_sources), 0, NULL, HFILL }},
+
+               { &hf_ipmi_picmg_23_rq_byte2,
+                       { "Request Flags",
+                               "ipmi.picmg23.rq.flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_slot_sel,
+                       { "MCS",
+                               "ipmi.picmg23.rq.mcs", FT_UINT8, BASE_HEX, VALS(picmg_23_slot_selectors), 0xC0, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_carrier_num,
+                       { "Carrier Number",
+                               "ipmi.picmg23.carrier.num", FT_UINT8, BASE_DEC, NULL, 0x1F, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_slot_num,
+                       { "Slot Number",
+                               "ipmi.picmg23.slot.num", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_tier_num,
+                       { "Tier Number",
+                               "ipmi.picmg23.tier.num", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_rs_byte5,
+                       { "Orientation Flags",
+                               "ipmi.picmg23.rs.flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_slot_base,
+                       { "Slot Numbers",
+                               "ipmi.picmg23.slot.base", FT_UINT8, BASE_DEC, VALS(picmg_23_num_bases), 0x80, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_tier_base,
+                       { "Tier Numbers",
+                               "ipmi.picmg23.tier.base", FT_UINT8, BASE_DEC, VALS(picmg_23_num_bases), 0x40, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_orientation,
+                       { "Carrier Orientation",
+                               "ipmi.picmg23.orient", FT_UINT8, BASE_DEC, VALS(picmg_23_orientations), 0x20, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_origin_x,
+                       { "Origin X",
+                               "ipmi.picmg23.origin.x", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_23_origin_y,
+                       { "Origin Y",
+                               "ipmi.picmg23.origin.y", FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL }},
+
+               { &hf_ipmi_picmg_24_channel,
+                       { "Power Channel Number",
+                               "ipmi.picmg.pwr.channel", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_24_control,
+                       { "Power Channel Control",
+                               "ipmi.picmg.pwr.control", FT_UINT8, BASE_DEC, VALS(picmg_24_controls), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_24_current,
+                       { "Power Channel Current Limit",
+                               "ipmi.picmg.pwr.limit", FT_UINT8, BASE_CUSTOM, fmt_power_amps, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_24_primary_pm,
+                       { "Primary PM",
+                               "ipmi.picmg.primary.pm", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_24_backup_pm,
+                       { "Redundant PM",
+                               "ipmi.picmg.backup.pm", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+
+               { &hf_ipmi_picmg_25_start,
+                       { "Starting Power Channel Number",
+                               "ipmi.picmg25.start", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_count,
+                       { "Power Channel Count",
+                               "ipmi.picmg25.count", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_max,
+                       { "Max Power Channel Number",
+                               "ipmi.picmg25.max", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_gstatus,
+                       { "Global Status",
+                               "ipmi.picmg25.gstatus", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_fault,
+                       { "Unidentified Fault",
+                               "ipmi.picmg25.fault", FT_UINT8, BASE_DEC, VALS(picmg_25_fault_vals), 0x08, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_pwr_good,
+                       { "Payload Power is Good",
+                               "ipmi.picmg25.pwr.good", FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_mp_good,
+                       { "Management Power is Good",
+                               "ipmi.picmg25.mp.good", FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_role,
+                       { "Role",
+                         "ipmi.picmg25.fault", FT_BOOLEAN, 8, TFS(&picmg_25_roles), 0x01, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_cstatus,
+                       { "Power Channel Status",
+                               "ipmi.picmg25.cstatus", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_pwr_on,
+                       { "PWR_ON is asserted",
+                               "ipmi.picmg25.pwr.on", FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_pwr_ovr,
+                       { "Payload Power Overcurrent is detected",
+                               "ipmi.picmg25.pwr.ovr", FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_pwr,
+                       { "Payload Power is enabled",
+                               "ipmi.picmg25.pwr", FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_enable,
+                       { "ENABLE# is asserted",
+                               "ipmi.picmg25.enable", FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_mp_ovr,
+                       { "Management Power Overcurrent is detected",
+                               "ipmi.picmg25.mp.ovr", FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_mp,
+                       { "Management Power is enabled",
+                               "ipmi.picmg25.mp", FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+               { &hf_ipmi_picmg_25_ps1,
+                       { "PS1# is asserted",
+                               "ipmi.picmg25.ps1", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+
+               { &hf_ipmi_picmg_26_pm_site,
+                       { "PM Site Number",
+                               "ipmi.picmg26.pm.site", FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_27_rs_byte3,
+                       { "PM Status",
+                               "ipmi.picmg26.pm.status", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_27_pm_healthy,
+                       { "PM is present and healthy",
+                               "ipmi.picmg26.pm.hly", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+               { &hf_ipmi_picmg_28_timeout,
+                       { "Time-out",
+                               "ipmi.picmg28.timeout", FT_UINT8, BASE_CUSTOM, fmt_100ms, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_28_rq_byte3,
+                       { "Flags",
+                               "ipmi.picmg28.flags", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_28_mch2,
+                       { "Use MCH2 PS1# de-assertion to indicate Carrier Manager is extracted",
+                               "ipmi.picmg28.mch2", FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+               { &hf_ipmi_picmg_28_mch1,
+                       { "Use MCH1 PS1# de-assertion to indicate Carrier Manager is extracted",
+                               "ipmi.picmg28.mch1", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+
+               { &hf_ipmi_picmg_29_rs_byte3,
+                       { "Alarm Capabilities",
+                               "ipmi.picmg29.caps", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_29_maj_rst,
+                       { "Autonomous Major Reset",
+                               "ipmi.picmg29.maj.rst", FT_BOOLEAN, 8, TFS(&picmg_29_alarm_actions), 0x80, NULL, HFILL }},
+               { &hf_ipmi_picmg_29_min_rst,
+                       { "Autonomous Minor Reset",
+                         "ipmi.picmg29.min.rst", FT_BOOLEAN, 8, TFS(&picmg_29_alarm_actions), 0x40, NULL, HFILL }},
+               { &hf_ipmi_picmg_29_alarm_cut,
+                       { "Autonomous alarm cutoff",
+                               "ipmi.picmg29.alrm.cut", FT_BOOLEAN, 8, TFS(&picmg_29_alarm_actions), 0x20, NULL, HFILL }},
+               { &hf_ipmi_picmg_29_test_mode,
+                       { "Test Mode",
+                         "ipmi.picmg29.test.mode", FT_BOOLEAN, 8, TFS(&picmg_29_alarm_modes), 0x10, NULL, HFILL }},
+               { &hf_ipmi_picmg_29_pwr_alarm,
+                       { "Power Alarm",
+                               "ipmi.picmg29.pwr.alrm", FT_BOOLEAN, 8, TFS(&picmg_29_alarm_modes), 0x08, NULL, HFILL }},
+               { &hf_ipmi_picmg_29_minor_alarm,
+                       { "Minor Alarm",
+                               "ipmi.picmg29.min.alrm", FT_BOOLEAN, 8, TFS(&picmg_29_alarm_modes), 0x04, NULL, HFILL }},
+               { &hf_ipmi_picmg_29_major_alarm,
+                       { "Minor Alarm",
+                               "ipmi.picmg29.maj.alrm", FT_BOOLEAN, 8, TFS(&picmg_29_alarm_modes), 0x02, NULL, HFILL }},
+               { &hf_ipmi_picmg_29_crit_alarm,
+                       { "Critical Alarm",
+                               "ipmi.picmg29.crit.alrm", FT_BOOLEAN, 8, TFS(&picmg_29_alarm_modes), 0x01, NULL, HFILL }},
+
+               { &hf_ipmi_picmg_2a_alarm_id,
+                       { "Alarm ID",
+                               "ipmi.picmg29.alrm.id", FT_UINT8, BASE_HEX, VALS(picmg_2a_alarm_ids), 0, NULL, HFILL }},
+               { &hf_ipmi_picmg_2a_alarm_ctrl,
+                       { "Alarm Control",
+                               "ipmi.picmg29.alrm.ctrl", FT_UINT8, BASE_HEX, VALS(picmg_2a_alarm_ctrls), 0, NULL, HFILL }},
+
+               { &hf_ipmi_picmg_2b_alarm_state,
+                       { "Alarm State",
+                               "ipmi.picmg29.alrm.ctrl", FT_UINT8, BASE_HEX, VALS(picmg_2a_alarm_ctrls), 0, NULL, HFILL }},
+
        };
        static gint *ett[] = {
                &ett_ipmi_picmg_led_color,
                &ett_ipmi_picmg_link_info,
+               &ett_ipmi_picmg_link_state,
+               &ett_ipmi_picmg_link_dev,
+               &ett_ipmi_picmg_clock_setting,
+               &ett_ipmi_picmg_clock_res,
                &ett_ipmi_picmg_05_byte1,
                &ett_ipmi_picmg_06_byte1,
                &ett_ipmi_picmg_06_byte2,
@@ -2298,6 +3695,15 @@ ipmi_register_picmg(gint proto_ipmi)
                &ett_ipmi_picmg_34_byte3,
                &ett_ipmi_picmg_36_byte2,
                &ett_ipmi_picmg_37_byte2,
+               &ett_ipmi_picmg_hpm_caps,
+               &ett_ipmi_picmg_47_byte1,
+               &ett_ipmi_picmg_23_rq_byte2,
+               &ett_ipmi_picmg_23_rs_byte5,
+               &ett_ipmi_picmg_25_rs_byte4,
+               &ett_ipmi_picmg_25_rs_byte5,
+               &ett_ipmi_picmg_27_rs_byte3,
+               &ett_ipmi_picmg_28_rq_byte3,
+               &ett_ipmi_picmg_29_rs_byte3
        };
        static guint8 sig_picmg[1] = { 0 };
 
index 5d4a3c77c379a527d59aa3605ff6f61c7b5b2d56..f3d089018f7b34ba4d8bedae03dfb75e9514ce8f 100644 (file)
 #include "packet-ipmi.h"
 
 static ipmi_cmd_t cmd_pps[] = {
-  { 0x00, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Status", 0 },
-  { 0x01, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Serial Interface Properties", 0 },
-  { 0x02, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Serial Interface Properties", 0 },
-  { 0x03, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Debug Level", 0 },
-  { 0x04, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Debug Level", 0 },
-  { 0x05, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Hardware Address", 0 },
-  { 0x06, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Hardware Address", 0 },
-  { 0x07, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Handle Switch", 0 },
-  { 0x08, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Handle Switch", 0 },
-  { 0x09, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Payload Communication Timeout", 0 },
-  { 0x0a, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Payload Communication Timeout", 0 },
-  { 0x0b, IPMI_TBD,   NULL, NULL, "[PPS OEM] Enable Payload Control", 0 },
-  { 0x0c, IPMI_TBD,   NULL, NULL, "[PPS OEM] Disable Payload Control", 0 },
-  { 0x0d, IPMI_TBD,   NULL, NULL, "[PPS OEM] Reset IPMC", 0 },
-  { 0x0e, IPMI_TBD,   NULL, NULL, "[PPS OEM] Hang IPMC", 0 },
-  { 0x0f, IPMI_TBD,   NULL, NULL, "[PPS OEM] Bused Resource Control", 0 },
-  { 0x10, IPMI_TBD,   NULL, NULL, "[PPS OEM] Bused Resource Status", 0 },
-  { 0x11, IPMI_TBD,   NULL, NULL, "[PPS OEM] Graceful Reset", 0 },
-  { 0x12, IPMI_TBD,   NULL, NULL, "[PPS OEM] Diagnostic Interrupt Results", 0 },
-  { 0x13, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set/Clear Telco Alarm", 0 },
-  { 0x14, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Telco Alarm Sensor Number", 0 },
-  { 0x15, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Payload Shutdown Timeout", 0 },
-  { 0x16, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Payload Shutdown Timeout", 0 },
-  { 0x17, IPMI_TBD,   NULL, NULL, "[PPS OEM] Switch over Serial Debug", 0 },
-  { 0x18, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Local FRU LED State", 0 },
-  { 0x19, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Local FRU LED State", 0 },
-  { 0x1a, IPMI_TBD,   NULL, NULL, "[PPS OEM] Update Discrete Sensor", 0 },
-  { 0x1b, IPMI_TBD,   NULL, NULL, "[PPS OEM] Update Threshold Sensor", 0 },
-  { 0x1c, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Prepare", 0 },
-  { 0x1d, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Write", 0 },
-  { 0x1e, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Complete", 0 },
-  { 0x1f, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Start", 0 },
-  { 0x20, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Stop", 0 },
-  { 0x21, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Resume", 0 },
-  { 0x22, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Cease", 0 },
-  { 0x23, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Sensor Set", 0 },
-  { 0x24, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Notify", 0 },
-  { 0x25, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Get FRU State", 0 },
-  { 0x26, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Invalidate Hardware Address", 0 },
-  { 0x27, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Module Status", 0 },
-  { 0x28, IPMI_TBD,   NULL, NULL, "[PPS OEM] Enable AMC Site", 0 },
-  { 0x29, IPMI_TBD,   NULL, NULL, "[PPS OEM] Disable AMC Site", 0 },
-  { 0x2a, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Wait for Payload Notify", 0 },
-  { 0x2b, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Test Flags", 0 },
-  { 0x2c, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Geographic Address", 0 },
-  { 0x2d, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Geographic Address", 0 },
-  { 0x30, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set EEPROM Sensor Data", 0 },
-  { 0x31, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set EEPROM Sensor Hysteresis", 0 },
-  { 0x32, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set EEPROM Sensor Threshold", 0 },
-  { 0x33, IPMI_TBD,   NULL, NULL, "[PPS OEM] Reset EEPROM SDR Repository", 0 },
-  { 0x34, IPMI_TBD,   NULL, NULL, "[PPS OEM] Backend Power Control", 0 },
-  { 0x35, IPMI_TBD,   NULL, NULL, "[PPS OEM] Read CPLD Register", 0 },
-  { 0x36, IPMI_TBD,   NULL, NULL, "[PPS OEM] Write CPLD Register", 0 }
+       { 0x00, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Status", 0 },
+       { 0x01, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Serial Interface Properties", 0 },
+       { 0x02, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Serial Interface Properties", 0 },
+       { 0x03, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Debug Level", 0 },
+       { 0x04, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Debug Level", 0 },
+       { 0x05, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Hardware Address", 0 },
+       { 0x06, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Hardware Address", 0 },
+       { 0x07, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Handle Switch", 0 },
+       { 0x08, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Handle Switch", 0 },
+       { 0x09, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Payload Communication Timeout", 0 },
+       { 0x0a, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Payload Communication Timeout", 0 },
+       { 0x0b, IPMI_TBD,   NULL, NULL, "[PPS OEM] Enable Payload Control", 0 },
+       { 0x0c, IPMI_TBD,   NULL, NULL, "[PPS OEM] Disable Payload Control", 0 },
+       { 0x0d, IPMI_TBD,   NULL, NULL, "[PPS OEM] Reset IPMC", 0 },
+       { 0x0e, IPMI_TBD,   NULL, NULL, "[PPS OEM] Hang IPMC", 0 },
+       { 0x0f, IPMI_TBD,   NULL, NULL, "[PPS OEM] Bused Resource Control", 0 },
+       { 0x10, IPMI_TBD,   NULL, NULL, "[PPS OEM] Bused Resource Status", 0 },
+       { 0x11, IPMI_TBD,   NULL, NULL, "[PPS OEM] Graceful Reset", 0 },
+       { 0x12, IPMI_TBD,   NULL, NULL, "[PPS OEM] Diagnostic Interrupt Results", 0 },
+       { 0x13, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set/Clear Telco Alarm", 0 },
+       { 0x14, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Telco Alarm Sensor Number", 0 },
+       { 0x15, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Payload Shutdown Timeout", 0 },
+       { 0x16, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Payload Shutdown Timeout", 0 },
+       { 0x17, IPMI_TBD,   NULL, NULL, "[PPS OEM] Switch over Serial Debug", 0 },
+       { 0x18, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Local FRU LED State", 0 },
+       { 0x19, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Local FRU LED State", 0 },
+       { 0x1a, IPMI_TBD,   NULL, NULL, "[PPS OEM] Update Discrete Sensor", 0 },
+       { 0x1b, IPMI_TBD,   NULL, NULL, "[PPS OEM] Update Threshold Sensor", 0 },
+       { 0x1c, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Prepare", 0 },
+       { 0x1d, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Write", 0 },
+       { 0x1e, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Complete", 0 },
+       { 0x1f, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Start", 0 },
+       { 0x20, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Stop", 0 },
+       { 0x21, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Resume", 0 },
+       { 0x22, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Script Cease", 0 },
+       { 0x23, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Sensor Set", 0 },
+       { 0x24, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Notify", 0 },
+       { 0x25, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Get FRU State", 0 },
+       { 0x26, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Invalidate Hardware Address", 0 },
+       { 0x27, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Module Status", 0 },
+       { 0x28, IPMI_TBD,   NULL, NULL, "[PPS OEM] Enable AMC Site", 0 },
+       { 0x29, IPMI_TBD,   NULL, NULL, "[PPS OEM] Disable AMC Site", 0 },
+       { 0x2a, IPMI_TBD,   NULL, NULL, "[PPS OEM] BTI Wait for Payload Notify", 0 },
+       { 0x2b, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Test Flags", 0 },
+       { 0x2c, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get Geographic Address", 0 },
+       { 0x2d, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set Geographic Address", 0 },
+       { 0x30, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set EEPROM Sensor Data", 0 },
+       { 0x31, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set EEPROM Sensor Hysteresis", 0 },
+       { 0x32, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set EEPROM Sensor Threshold", 0 },
+       { 0x33, IPMI_TBD,   NULL, NULL, "[PPS OEM] Reset EEPROM SDR Repository", 0 },
+       { 0x34, IPMI_TBD,   NULL, NULL, "[PPS OEM] Backend Power Control", 0 },
+       { 0x35, IPMI_TBD,   NULL, NULL, "[PPS OEM] Read CPLD Register", 0 },
+       { 0x36, IPMI_TBD,   NULL, NULL, "[PPS OEM] Write CPLD Register", 0 },
+       { 0x37, IPMI_TBD,   NULL, NULL, "[PPS OEM] Calibrate A2F Temperature Sensor", 0 },
+       { 0x38, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get GPIO Signal State", 0 },
+       { 0x39, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set GPIO Signal State", 0 },
+       { 0x40, IPMI_TBD,   NULL, NULL, "[PPS OEM] Sensor AFS Dump MBX Page", 0 },
+       { 0x41, IPMI_TBD,   NULL, NULL, "[PPS OEM] Reset Non-Volatile Parameters and Reboot", 0 },
+       { 0x42, IPMI_TBD,   NULL, NULL, "[PPS OEM] Dump Profiling Data", 0 },
+       { 0x43, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get FPGA Design Version", 0 },
+       { 0x44, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get IPMB Trace Mask", 0 },
+       { 0x45, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set IPMB Trace Mask", 0 },
+       { 0x46, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get PWM DAC Level", 0 },
+       { 0x47, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set PWM DAC Level", 0 },
+       { 0x48, IPMI_TBD,   NULL, NULL, "[PPS OEM] Get FRU Info Write-Protect State", 0 },
+       { 0x49, IPMI_TBD,   NULL, NULL, "[PPS OEM] Set FRU Info Write-Protect State", 0 }
 };
 
 void
index def7398c462e15c8d8090663a6465301006f6c91..b464a003169adafab1fd0a6a368ae37f8d385dc9 100644 (file)
@@ -1837,7 +1837,7 @@ parse_platform_event(tvbuff_t *tvb, proto_tree *tree)
           fall back to "default" display in such weird cases.
        */
        reinit_statics();
-       if (tvb_length(tvb) <= 5) {
+       if (tvb_captured_length(tvb) <= 5) {
                return;
        }
 
@@ -1854,7 +1854,7 @@ parse_platform_event(tvbuff_t *tvb, proto_tree *tree)
        }
 
        /* Now the same for byte 3 */
-       if (tvb_length(tvb) <= 6) {
+       if (tvb_captured_length(tvb) <= 6) {
                return;
        }
 
@@ -2028,7 +2028,7 @@ cfgparam_13(tvbuff_t *tvb, proto_tree *tree)
 
        proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL, ett_ipmi_se_cp13_byte1, byte1, ENC_LITTLE_ENDIAN, 0);
        proto_tree_add_item(tree, hf_ipmi_se_cp13_blocksel, tvb, 1, 1, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_se_cp13_string, tvb, 2, tvb_length(tvb) - 2, ENC_ASCII|ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_se_cp13_string, tvb, 2, -1, ENC_ASCII|ENC_NA);
 }
 
 static void
@@ -2267,10 +2267,10 @@ rq12(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                        ipmi_dcd8(pno, 0x7f), desc, pno);
 
        if (pno < array_length(conf_params)) {
-               sub = tvb_new_subset(tvb, 1, tvb_length(tvb) - 1, tvb_length(tvb) - 1);
+               sub = tvb_new_subset_remaining(tvb, 1);
                conf_params[pno].intrp(sub, tree);
        } else {
-               proto_tree_add_none_format(tree, hf_ipmi_se_12_data, tvb, 1, tvb_length(tvb) - 1,
+               proto_tree_add_none_format(tree, hf_ipmi_se_12_data, tvb, 1, -1,
                                "Configuration parameter data: %s", desc);
        }
 }
@@ -2295,9 +2295,9 @@ rq13(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 
        pno = tvb_get_guint8(tvb, 0);
 
+       ipmi_set_data(pinfo, 0, pno);
        if (!tree) {
                /* Just cache parameter selector */
-               ipmi_setsaveddata(0, pno);
                return;
        }
 
@@ -2334,18 +2334,18 @@ rs13(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_bitmask_text(tree, tvb, 0, 1, "Parameter revision", NULL,
                        ett_ipmi_se_13_rev, byte1, ENC_LITTLE_ENDIAN, 0);
 
-       if (!ipmi_getsaveddata(0, &pno)) {
+       if (!ipmi_get_data(pinfo, 0, &pno)) {
                /* No request found - cannot parse further */
-               if (tvb_length(tvb) > 1) {
-                       proto_tree_add_item(tree, hf_ipmi_se_13_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+               if (tvb_captured_length(tvb) > 1) {
+                       proto_tree_add_item(tree, hf_ipmi_se_13_data, tvb, 1, -1, ENC_NA);
                }
                return;
        }
 
-       if ((pno & 0x80) && tvb_length(tvb) > 1) {
+       if ((pno & 0x80) && tvb_captured_length(tvb) > 1) {
                ti = proto_tree_add_text(tree, tvb, 0, 0, "Requested parameter revision; parameter data returned");
                PROTO_ITEM_SET_GENERATED(ti);
-       } else if (!(pno & 0x80) && tvb_length(tvb) == 1) {
+       } else if (!(pno & 0x80) && tvb_captured_length(tvb) == 1) {
                ti = proto_tree_add_text(tree, tvb, 0, 0, "Requested parameter data; only parameter version returned");
                PROTO_ITEM_SET_GENERATED(ti);
        }
@@ -2362,12 +2362,12 @@ rs13(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        ti = proto_tree_add_text(tree, tvb, 0, 0, "Parameter: %s", desc);
        PROTO_ITEM_SET_GENERATED(ti);
 
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                if (pno < array_length(conf_params)) {
-                       sub = tvb_new_subset(tvb, 1, tvb_length(tvb) - 1, tvb_length(tvb) - 1);
+                       sub = tvb_new_subset_remaining(tvb, 1);
                        conf_params[pno].intrp(sub, tree);
                } else {
-                       proto_tree_add_item(tree, hf_ipmi_se_13_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+                       proto_tree_add_item(tree, hf_ipmi_se_13_data, tvb, 1, -1, ENC_NA);
                }
        }
 }
@@ -2433,18 +2433,18 @@ rq16(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        static const gint *byte3[] = { &hf_ipmi_se_16_send_string, &hf_ipmi_se_16_string_sel, NULL };
        tvbuff_t *sub;
 
+       ipmi_set_data(pinfo, 0, (tvb_get_guint8(tvb, 1) & 0xc0) >> 6);
        if (!tree) {
                /* Save the operation */
-               ipmi_setsaveddata(0, (tvb_get_guint8(tvb, 1) & 0xc0) >> 6);
                return;
        }
 
        proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL, ett_ipmi_se_16_byte1, byte1, ENC_LITTLE_ENDIAN, 0);
        proto_tree_add_bitmask_text(tree, tvb, 1, 1, NULL, NULL, ett_ipmi_se_16_byte2, byte2, ENC_LITTLE_ENDIAN, 0);
        proto_tree_add_bitmask_text(tree, tvb, 2, 1, NULL, NULL, ett_ipmi_se_16_byte3, byte3, ENC_LITTLE_ENDIAN, 0);
-       if (tvb_length(tvb) > 3) {
+       if (tvb_captured_length(tvb) > 3) {
                proto_tree_add_item(tree, hf_ipmi_se_16_gen, tvb, 3, 1, ENC_LITTLE_ENDIAN);
-               sub = tvb_new_subset(tvb, 4, tvb_length(tvb) - 4, tvb_length(tvb) - 4);
+               sub = tvb_new_subset_remaining(tvb, 4);
                parse_platform_event(sub, tree);
        }
 }
@@ -2454,7 +2454,7 @@ rs16(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        guint32 val;
 
-       if (ipmi_getsaveddata(0, &val) && val == 0x01) {
+       if (ipmi_get_data(pinfo, 0, &val) && val == 0x01) {
                /* Operation == Get Alert Immediate Status */
                proto_tree_add_item(tree, hf_ipmi_se_16_status, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        }
@@ -2489,10 +2489,13 @@ rq20(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        static const int *byte1[] = { &hf_ipmi_se_20_rq_op, NULL };
 
-       if (tvb_length(tvb) > 0) {
-               proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL,
-                               ett_ipmi_se_20_rq_byte1, byte1, ENC_LITTLE_ENDIAN, 0);
-               ipmi_setsaveddata(0, tvb_get_guint8(tvb, 0) & 0x01);
+       if (tvb_captured_length(tvb) > 0) {
+               ipmi_set_data(pinfo, 0, tvb_get_guint8(tvb, 0) & 0x01);
+
+               if (tree) {
+                       proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL,
+                                       ett_ipmi_se_20_rq_byte1, byte1, ENC_LITTLE_ENDIAN, 0);
+               }
        }
 }
 
@@ -2503,7 +2506,7 @@ rs20(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                &hf_ipmi_se_20_rs_lun2, &hf_ipmi_se_20_rs_lun1, &hf_ipmi_se_20_rs_lun0, NULL };
        guint32 val;
 
-       if (ipmi_getsaveddata(0, &val) && val) {
+       if (ipmi_get_data(pinfo, 0, &val) && val) {
                proto_tree_add_item(tree, hf_ipmi_se_20_rs_sdr, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        } else {
                proto_tree_add_item(tree, hf_ipmi_se_20_rs_num, tvb, 0, 1, ENC_LITTLE_ENDIAN);
@@ -2537,7 +2540,7 @@ static void
 rs21(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_se_21_next, tvb, 0, 2, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_se_21_recdata, tvb, 2, tvb_length(tvb) - 2, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_se_21_recdata, tvb, 2, -1, ENC_NA);
 }
 
 static const value_string cc21[] = {
@@ -2727,7 +2730,7 @@ add_events(tvbuff_t *tvb, int offs, proto_tree *tree, const struct true_false_st
        static const int *tsel[] = { &ett_ipmi_se_XX_b1, &ett_ipmi_se_XX_b2, &ett_ipmi_se_XX_b3, &ett_ipmi_se_XX_b4 };
        proto_item *ti;
        proto_tree *s_tree;
-       int len = tvb_length(tvb);
+       int len = tvb_captured_length(tvb);
        int i, j, val, msk;
 
        for (i = 0; (offs < len) && (i < 4); i++, offs++) {
@@ -2833,7 +2836,7 @@ rs2d(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 
        proto_tree_add_item(tree, hf_ipmi_se_2d_reading, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_bitmask_text(tree, tvb, 1, 1, NULL, NULL, ett_ipmi_se_2d_byte2, byte2, ENC_LITTLE_ENDIAN, 0);
-       len = tvb_length(tvb);
+       len = tvb_captured_length(tvb);
        for (i = 0; i < 2 && i < len - 2; i++) {
                ti = proto_tree_add_text(tree, tvb, i + 2, 1, "Threshold comparisons/assertions (byte %d)", i);
                s_tree = proto_item_add_subtree(ti, *tsel[i]);
index b3f6e403ad154add0c6df612a7e001fcdf66a919..c04db04a9f8158a774bb425548ac30bdc6708398 100644 (file)
@@ -173,7 +173,7 @@ dissect_ipmi_session(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
        if (tree) {
                offset = 0;
                ti = proto_tree_add_protocol_format(tree, proto_ipmi_session,
-                               tvb, 0, tvb_length(tvb),
+                               tvb, 0, -1,
                                "IPMI v%s Session Wrapper, session ID 0x%x",
                                authtype == IPMI_AUTH_RMCPP ? "2.0+" : "1.5",
                                session_id);
@@ -251,12 +251,12 @@ dissect_ipmi_session(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *
                offset += msg_len;
 
                /* Show the rest of the session wrapper as binary data */
-               if (offset < tvb_length(tvb)) {
+               if (offset < tvb_captured_length(tvb)) {
                        proto_tree_add_item(sess_tree, hf_ipmi_session_trailer,
-                                       tvb, offset, tvb_length(tvb) - offset, ENC_NA);
+                                       tvb, offset, -1, ENC_NA);
                }
        }
-       return tvb_length(tvb);
+       return tvb_captured_length(tvb);
 }
 
 void
index 29f260235d14d39a19226b053ed3f13003542779..5f9d0ab6f9365ec7d59f0030c0d074d2043744bf 100644 (file)
@@ -268,7 +268,7 @@ static void
 rs11(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_stor_11_ret_count, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_stor_11_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_stor_11_data, tvb, 1, -1, ENC_NA);
 }
 
 static const value_string cc11[] = {
@@ -283,7 +283,7 @@ rq12(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_stor_12_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(tree, hf_ipmi_stor_12_offset, tvb, 1, 2, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_stor_12_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_stor_12_data, tvb, 3, -1, ENC_NA);
 }
 
 static void
@@ -354,7 +354,7 @@ static void
 rs23(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_stor_23_next, tvb, 0, 2, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_stor_23_data, tvb, 2, tvb_length(tvb) - 2, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_stor_23_data, tvb, 2, -1, ENC_NA);
 }
 
 /* Add SDR
@@ -362,7 +362,7 @@ rs23(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 static void
 rq24(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       proto_tree_add_item(tree, hf_ipmi_stor_24_data, tvb, 0, tvb_length(tvb), ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_stor_24_data, tvb, 0, -1, ENC_NA);
 }
 
 static void
@@ -383,7 +383,7 @@ rq25(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_item(tree, hf_ipmi_stor_25_offset, tvb, 4, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_bitmask_text(tree, tvb, 5, 1, NULL, NULL,
                        ett_ipmi_stor_25_byte6, byte6, ENC_LITTLE_ENDIAN, 0);
-       proto_tree_add_item(tree, hf_ipmi_stor_25_data, tvb, 6, tvb_length(tvb) - 6, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_stor_25_data, tvb, 6, -1, ENC_NA);
 }
 
 static void
@@ -532,7 +532,7 @@ static void
 rs43(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_stor_43_next, tvb, 0, 2, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_stor_43_data, tvb, 2, tvb_length(tvb) - 2, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_stor_43_data, tvb, 2, -1, ENC_NA);
 }
 
 static const value_string cc43[] = {
@@ -546,7 +546,7 @@ static const value_string cc43[] = {
 static void
 rq44(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
-       proto_tree_add_item(tree, hf_ipmi_stor_44_data, tvb, 0, tvb_length(tvb), ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_stor_44_data, tvb, 0, -1, ENC_NA);
 }
 
 static void
@@ -573,7 +573,7 @@ rq45(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_item(tree, hf_ipmi_stor_45_offset, tvb, 4, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_bitmask_text(tree, tvb, 5, 1, NULL, NULL,
                        ett_ipmi_stor_45_byte6, byte6, ENC_LITTLE_ENDIAN, 0);
-       proto_tree_add_item(tree, hf_ipmi_stor_45_data, tvb, 6, tvb_length(tvb) - 6, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_stor_45_data, tvb, 6, -1, ENC_NA);
 }
 
 static void
@@ -651,8 +651,8 @@ rq5a(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        static const int *byte1[] = { &hf_ipmi_stor_5a_log_type, NULL };
 
+       ipmi_set_data(pinfo, 0, tvb_get_guint8(tvb, 0) & 0x0f);
        if (!tree) {
-               ipmi_setsaveddata(0, tvb_get_guint8(tvb, 0) & 0x0f);
                return;
        }
 
@@ -665,8 +665,8 @@ rs5a(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        guint32 v;
 
-       if (!ipmi_getsaveddata(0, &v) || v > 2) {
-               proto_tree_add_item(tree, hf_ipmi_stor_5a_unknown, tvb, 0, tvb_length(tvb), ENC_NA);
+       if (!ipmi_get_data(pinfo, 0, &v) || v > 2) {
+               proto_tree_add_item(tree, hf_ipmi_stor_5a_unknown, tvb, 0, -1, ENC_NA);
                return;
        }
 
@@ -691,7 +691,7 @@ rq5b(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                        ett_ipmi_stor_5b_byte1, byte1, ENC_LITTLE_ENDIAN, 0);
 
        if (v > 2) {
-               proto_tree_add_item(tree, hf_ipmi_stor_5b_unknown, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+               proto_tree_add_item(tree, hf_ipmi_stor_5b_unknown, tvb, 1, -1, ENC_NA);
                return;
        }
 
diff --git a/epan/dissectors/packet-ipmi-trace.c b/epan/dissectors/packet-ipmi-trace.c
new file mode 100755 (executable)
index 0000000..fa5dc03
--- /dev/null
@@ -0,0 +1,479 @@
+/* packet-hpm2-trace.c
+ * Routines for HPM.2 Trace Data Block disassembly
+ * By Dmitry Bazhenov <dima_b@pigeonpoint.com>
+ * Copyright 2014 Pigeon Point Systems
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 "config.h"
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include <epan/dissectors/packet-ipmi.h>
+#include <wiretap/wtap.h>
+
+/*
+ * See
+ *
+ * http://www.picmg.org/v2internal/resourcepage2.cfm?id=12
+ */
+
+/* Trace data block types. */
+enum {
+       HPM2_TRACE_PACKET_DATA  = 0,
+       HPM2_CHN_STATE_NOTIFY   = 1,
+       HPM2_EMBED_ASCII_MSG    = 2
+};
+
+/* Data directions. */
+enum {
+       HPM2_TRACE_DATA_OUT     = 0,    /* From IPM controller */
+       HPM2_TRACE_DATA_IN      = 1             /* To IPM controller */
+};
+
+/* Redundant channel indicators. */
+enum {
+       HPM2_TRACE_1ST_CHN              = 0,
+       HPM2_TRACE_2ND_CHN              = 1
+};
+
+/* IPMB local status values. */
+enum {
+       HPM2_IPMB_S_OK                  = 0,
+       HPM2_IPMB_S_ERR_SCL_HI  = 1,
+       HPM2_IPMB_S_ERR_SDA_HI  = 2,
+       HPM2_IPMB_S_ERR_SCL_LO  = 3,
+       HPM2_IPMB_S_ERR_SDA_LO  = 4,
+       HPM2_IPMB_S_SCL_TIMEOUT = 5,
+       HPM2_IPMB_S_UNDER_TEST  = 6,
+       HPM2_IPMB_S_UNKNOWN_ERR = 7
+};
+
+/* IPMI channel protocol types. */
+enum {
+       IPMI_PROTO_IPMB_1_0             = 0x01,
+       IPMI_PROTO_ICMB_1_0             = 0x02,
+       IPMI_PROTO_IPMI_SMBUS   = 0x04,
+       IPMI_PROTO_KCS                  = 0x05,
+       IPMI_PROTO_SMIC                 = 0x06,
+       IPMI_PROTO_BT_10                = 0x07,
+       IPMI_PROTO_BT_15                = 0x08,
+       IPMI_PROTO_TMODE                = 0x09,
+       IPMI_PROTO_OEM_1                = 0x1C,
+       IPMI_PROTO_OEM_2                = 0x1D,
+       IPMI_PROTO_OEM_3                = 0x1E,
+       IPMI_PROTO_OEM_4                = 0x1F
+};
+
+/* IPMB override status values. */
+enum {
+       HPM2_IPMB_S_ISOLATED    = 0,
+       HPM2_IPMB_S_LOCAL_CTRL  = 1
+};
+
+void proto_register_ipmi_trace(void);
+void proto_reg_handoff_ipmi_trace(void);
+
+static int proto_ipmi_trace = -1;
+
+static dissector_handle_t data_dissector_handle;
+static dissector_table_t proto_dissector_table;
+
+static gint ett_ipmi_trace = -1;
+static gint ett_trace_block_type = -1;
+static gint ett_trace_timestamp = -1;
+static gint ett_trace_protocol_data = -1;
+static gint ett_trace_ipmb_state = -1;
+
+static gint hf_trace_block_type = -1;
+static gint hf_trace_channel_num = -1;
+static gint hf_trace_packet_type = -1;
+static gint hf_trace_timestamp = -1;
+static gint hf_trace_timestamp_sec = -1;
+static gint hf_trace_timestamp_msec = -1;
+static gint hf_trace_data_type = -1;
+static gint hf_trace_protocol_data = -1;
+static gint hf_trace_dir = -1;
+static gint hf_trace_ipmb_red_chn = -1;
+static gint hf_trace_ipmb_link_num = -1;
+static gint hf_trace_data_len = -1;
+static gint hf_trace_notify_format = -1;
+static gint hf_trace_ipmb_state = -1;
+static gint hf_trace_ipmb_ovr_state = -1;
+static gint hf_trace_ipmb_loc_state = -1;
+
+static const value_string str_packet_types[] = {
+       { 0, "IPMI Trace Packet Data" },
+       { 1, "Channel State Change Notification" },
+       { 2, "Embedded ASCII message" },
+       { 0, NULL }
+};
+
+static const value_string str_protocol_types[] = {
+       { 0,    "n/a" },
+       { 1,    "IPMB-1.0" },
+       { 2,    "ICMB-1.0" },
+       { 4,    "IPMI-SMBus" },
+       { 5,    "KCS" },
+       { 6,    "SMIC" },
+       { 7,    "BT-10" },
+       { 8,    "BT-15" },
+       { 9,    "TMode" },
+       { 0x1C, "OEM Protocol 1" },
+       { 0x1D, "OEM Protocol 2" },
+       { 0x1E, "OEM Protocol 3" },
+       { 0x1F, "OEM Protocol 4" },
+       { 0, NULL }
+};
+
+static const value_string str_redund_chns[] = {
+       { 0, "First channel" },
+       { 1, "Second channel" },
+       { 0, NULL }
+};
+
+static const value_string str_trace_dirs[] = {
+       { 0, "From IPM Controller" },
+       { 1, "To IPM Controller" },
+       { 0, NULL }
+};
+
+static const value_string str_ipmb_notify_formats[] = {
+       { 0, "Derived from PICMG 3.0" },
+       { 0, NULL }
+};
+
+static const value_string str_ipmb_ovr_statuses[] = {
+       { 0, "Override status, bus isolated" },
+       { 1, "Local Control State" },
+       { 0, NULL }
+};
+
+static const value_string str_ipmb_loc_statuses[] = {
+       { 0, "No Failure" },
+       { 1, "Unable to drive clock HI" },
+       { 2, "Unable to drive data HI" },
+       { 3, "Unable to drive clock LO" },
+       { 4, "Unable to drive data LO" },
+       { 5, "Clock low timeout" },
+       { 6, "Under test" },
+       { 7, "Undiagnosed Communications Failure" },
+       { 0, NULL }
+};
+
+static const gint * bits_trace_block_type[] = {
+       &hf_trace_channel_num,
+       &hf_trace_packet_type,
+       NULL
+};
+
+static const gint * bits_ipmb_protocol_data[] = {
+       &hf_trace_ipmb_link_num,
+       &hf_trace_ipmb_red_chn,
+       &hf_trace_dir,
+       NULL
+};
+
+static const gint * bits_host_protocol_data[] = {
+       &hf_trace_dir,
+       NULL
+};
+
+static const gint * bits_chn_state_info[] = {
+       &hf_trace_ipmb_ovr_state,
+       &hf_trace_ipmb_loc_state,
+       NULL
+};
+
+/* HPM.2 Trace Collection tree indices. */
+static gint * const ipmi_trace_ett[] = {
+       &ett_ipmi_trace,
+       &ett_trace_block_type,
+       &ett_trace_timestamp,
+       &ett_trace_protocol_data,
+       &ett_trace_ipmb_state
+};
+
+/* HPM.2 Trace Collection header fields. */
+static hf_register_info ipmi_trace_hf[] = {
+       {       &hf_trace_block_type, {
+                       "Trace Data Block Type", "hpm2.trace.block.type",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
+       {       &hf_trace_channel_num, {
+                       "IPMI Channel Number being traced", "hpm2.trace.chn.num",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0x0F, NULL, HFILL } },
+       {       &hf_trace_packet_type, {
+                       "Packet Type", "hpm2.trace.packet.type",
+                       FT_UINT8, BASE_DEC, VALS(str_packet_types), 0x30, NULL, HFILL } },
+       {       &hf_trace_timestamp, {
+                       "Timestamp", "hpm2.trace.stamp",
+                       FT_RELATIVE_TIME, BASE_NONE, NULL, 0, NULL, HFILL } },
+       {       &hf_trace_timestamp_sec, {
+                       "Seconds part", "hpm2.trace.stamp.sec",
+                       FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
+       {       &hf_trace_timestamp_msec, {
+                       "Milliseconds part", "hpm2.trace.stamp.msec",
+                       FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL } },
+       {       &hf_trace_data_type, {
+                       "Trace Data Type", "hpm2.trace.data.type",
+                       FT_UINT8, BASE_HEX, VALS(str_protocol_types), 0, NULL, HFILL } },
+       {       &hf_trace_protocol_data, {
+                       "Additional protocol specific data", "hpm2.trace.proto.data",
+                       FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL } },
+       {       &hf_trace_ipmb_link_num, {
+                       "Radial IPMB Link Number", "hpm2.trace.ipmb.link.num",
+                       FT_UINT16, BASE_DEC_HEX, NULL, 0x003F, NULL, HFILL } },
+       {       &hf_trace_ipmb_red_chn, {
+                       "Redundant Channel Indicator", "hpm2.trace.ipmb.red.chn",
+                       FT_UINT16, BASE_DEC, VALS(str_redund_chns), 0x0040, NULL, HFILL } },
+       {       &hf_trace_dir, {
+                       "Direction", "hpm2.trace.dir",
+                       FT_UINT16, BASE_DEC, VALS(str_trace_dirs), 0x0080, NULL, HFILL } },
+       {       &hf_trace_data_len, {
+                       "Data length", "hpm2.trace.data.len",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL } },
+       {       &hf_trace_notify_format, {
+                       "Data format", "hpm2.trace.data.format",
+                       FT_UINT8, BASE_HEX, VALS(str_ipmb_notify_formats), 0, NULL, HFILL } },
+       {       &hf_trace_ipmb_state, {
+                       "State Change Information", "hpm2.trace.ipmb.state",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL } },
+       {       &hf_trace_ipmb_ovr_state, {
+                       "IPMB Override status", "hpm2.trace.ipmb.state.ovr",
+                       FT_UINT8, BASE_DEC, VALS(str_ipmb_ovr_statuses), 0x8, NULL, HFILL } },
+       {       &hf_trace_ipmb_loc_state, {
+                       "IPMB Local status", "hpm2.trace.ipmb.state.loc",
+                       FT_UINT8, BASE_DEC, VALS(str_ipmb_loc_statuses), 0x7, NULL, HFILL } },
+};
+
+static void
+dissect_ipmb_state_notify(tvbuff_t * tvb, proto_tree * tree)
+{
+       /* add data format */
+       proto_tree_add_item(tree, hf_trace_notify_format,
+                       tvb, 0, 1, ENC_LITTLE_ENDIAN);
+
+       /* add host-specific data */
+       proto_tree_add_bitmask(tree, tvb, 1,
+                       hf_trace_ipmb_state, ett_trace_ipmb_state,
+                       bits_chn_state_info, ENC_LITTLE_ENDIAN);
+}
+
+static void
+dissect_ipmi_trace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       guint block_type, chn_num, data_type, tmp;
+       tvbuff_t * next_tvb;
+
+       if (tvb_captured_length(tvb) < 11) {
+               /* TODO: add expert info */
+               call_dissector(data_dissector_handle, tvb, pinfo, tree);
+               return;
+       }
+
+       /* get first byte */
+       tmp = tvb_get_guint8(tvb, 0);
+
+       /* get block type */
+       block_type = (tmp >> 4) & 3;
+
+       /* get channel number */
+       chn_num = tmp & 0xF;
+
+       /* get trace data type */
+       data_type = tvb_get_guint8(tvb, 7);
+
+
+       col_add_fstr(pinfo->cinfo, COL_DEF_SRC, "Channel %d", chn_num);
+       col_set_str(pinfo->cinfo, COL_PROTOCOL,
+                       val_to_str(data_type, str_protocol_types,
+                                       "Reserved (0x%02x)"));
+
+       col_clear(pinfo->cinfo, COL_INFO);
+
+       if (block_type == HPM2_TRACE_PACKET_DATA) {
+               col_set_str(pinfo->cinfo, COL_INFO, "Trace Packet Data");
+       } else if (block_type == HPM2_CHN_STATE_NOTIFY) {
+               col_set_str(pinfo->cinfo, COL_INFO,
+                               "Channel State Change Notification");
+       } else if (block_type == HPM2_EMBED_ASCII_MSG) {
+               char str[257];
+
+               /* get data length */
+               guint str_len = tvb_get_guint8(tvb, 10);
+
+               if (str_len) {
+                       /* copy string */
+                       tvb_memcpy(tvb, str, 11, str_len);
+
+                       /* pad with nul */
+                       str[str_len] = 0;
+
+                       /* print the string right inside the column */
+                       col_add_str(pinfo->cinfo, COL_INFO, str);
+               }
+       } else {
+               col_set_str(pinfo->cinfo, COL_INFO, "Reserved");
+       }
+
+
+       if ( tree ) {
+               proto_item * ti;
+               proto_tree * trace_tree;
+               proto_tree * stamp_tree;
+               nstime_t timestamp;
+
+               /* add protocol label */
+               ti = proto_tree_add_item(tree, proto_ipmi_trace, tvb, 0, -1, ENC_NA);
+
+               /* create protocol sub-tree */
+               trace_tree = proto_item_add_subtree(ti, ett_ipmi_trace);
+
+               /* add block type/channel bitmask */
+               proto_tree_add_bitmask(trace_tree, tvb, 0, hf_trace_block_type,
+                               ett_trace_block_type, bits_trace_block_type,
+                               ENC_LITTLE_ENDIAN);
+
+               /* get seconds part */
+               timestamp.secs = tvb_get_letohl(tvb, 1);
+
+               /* get milliseconds part */
+               timestamp.nsecs = (int) tvb_get_letohs(tvb, 5) * 1000000;
+
+               /* add timestamp */
+               ti = proto_tree_add_time(trace_tree, hf_trace_timestamp, tvb, 1,
+                               6, &timestamp);
+
+               /* create timestamp sub-tree */
+               stamp_tree = proto_item_add_subtree(ti, ett_trace_timestamp);
+
+               /* add seconds part */
+               proto_tree_add_item(stamp_tree, hf_trace_timestamp_sec,
+                               tvb, 1, 4, ENC_LITTLE_ENDIAN);
+
+               /* add milliseconds part */
+               proto_tree_add_item(stamp_tree, hf_trace_timestamp_msec,
+                               tvb, 5, 2, ENC_LITTLE_ENDIAN);
+
+               /* add trace data type */
+               proto_tree_add_item(trace_tree, hf_trace_data_type,
+                               tvb, 7, 1, ENC_LITTLE_ENDIAN);
+
+               if (data_type == IPMI_PROTO_IPMB_1_0) {
+                       /* add ipmb-specific data */
+                       proto_tree_add_bitmask(trace_tree, tvb, 8,
+                                       hf_trace_protocol_data, ett_trace_protocol_data,
+                                       bits_ipmb_protocol_data, ENC_LITTLE_ENDIAN);
+               } else if (data_type == IPMI_PROTO_KCS
+                               || data_type == IPMI_PROTO_SMIC
+                               || data_type == IPMI_PROTO_BT_10
+                               || data_type == IPMI_PROTO_BT_15) {
+                       /* add host-specific data */
+                       proto_tree_add_bitmask(trace_tree, tvb, 8,
+                                       hf_trace_protocol_data, ett_trace_protocol_data,
+                                       bits_host_protocol_data, ENC_LITTLE_ENDIAN);
+               } else {
+                       /* add protocol specific data */
+                       proto_tree_add_item(trace_tree, hf_trace_protocol_data, tvb,
+                                       8, 2, ENC_LITTLE_ENDIAN);
+               }
+
+               /* add data length*/
+               proto_tree_add_item(trace_tree, hf_trace_data_len, tvb,
+                               10, 1, ENC_LITTLE_ENDIAN);
+       }
+
+       /* get pointer to remaining data buffer */
+       next_tvb = tvb_new_subset_remaining(tvb, 11);
+
+       if (block_type == HPM2_TRACE_PACKET_DATA) {
+               ipmi_dissect_arg_t arg;
+
+               /* setup IPMI protocol argument */
+               arg.context = IPMI_E_NONE;
+               arg.channel = chn_num;
+               arg.flags       = tvb_get_guint8(tvb, 8);
+
+               if (!dissector_try_uint_new(proto_dissector_table,
+                               data_type, next_tvb, pinfo, tree, TRUE, &arg)) {
+                       call_dissector(data_dissector_handle, next_tvb,
+                                       pinfo, tree);
+               }
+       } else if (block_type == HPM2_CHN_STATE_NOTIFY
+                       && data_type == IPMI_PROTO_IPMB_1_0) {
+               dissect_ipmb_state_notify(next_tvb, tree);
+       } else {
+               call_dissector(data_dissector_handle, next_tvb, pinfo, tree);
+       }
+}
+
+void
+proto_register_ipmi_trace(void)
+{
+       /* register protocol for HPM.2 trace data block */
+       proto_ipmi_trace = proto_register_protocol("IPMI Trace Data Collection",
+                       "ipmi-trace", "ipmi-trace");
+
+       /* register HPM.2 header fields */
+       proto_register_field_array(proto_ipmi_trace, ipmi_trace_hf,
+                       array_length(ipmi_trace_hf));
+
+       /* register HPM.2 sub-tree indices */
+       proto_register_subtree_array(ipmi_trace_ett,
+                       array_length(ipmi_trace_ett));
+
+       /* register dissector table for IPMI messaging protocols */
+       proto_dissector_table = register_dissector_table("ipmi.protocol",
+                       "IPMI Channel Protocol Type", FT_UINT8, BASE_HEX);
+}
+
+void
+proto_reg_handoff_ipmi_trace(void)
+{
+       dissector_handle_t ipmi_trace_handle;
+
+       ipmi_trace_handle = create_dissector_handle(dissect_ipmi_trace,
+                       proto_ipmi_trace);
+
+       data_dissector_handle = find_dissector("data");
+
+       dissector_add_uint("wtap_encap", WTAP_ENCAP_IPMI_TRACE, ipmi_trace_handle);
+
+       dissector_add_uint("ipmi.protocol", IPMI_PROTO_IPMB_1_0,
+                       find_dissector("ipmb"));
+       dissector_add_uint("ipmi.protocol", IPMI_PROTO_KCS,
+                       find_dissector("kcs"));
+       dissector_add_uint("ipmi.protocol", IPMI_PROTO_TMODE,
+                       find_dissector("tmode"));
+}
+
+/*
+ * Editor modelines  -  http://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:
+ */
index 30591496b16f2589850945af2cb88226f8cfe736..acfa0bf97cc679a7d7f64e601f0ef23fb2c3d289 100644 (file)
@@ -868,7 +868,7 @@ lan_19(tvbuff_t *tvb, proto_tree *tree)
                return;
        }
 
-       proto_tree_add_item(tree, hf_ipmi_trn_lan19_address, tvb, 2, tvb_length(tvb) - 2, ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_trn_lan19_address, tvb, 2, -1, ENC_NA);
 }
 
 static void
@@ -956,7 +956,7 @@ lan_25(tvbuff_t *tvb, proto_tree *tree)
                                        byte34, ENC_LITTLE_ENDIAN, 0);
                        break;
                default:
-                       proto_tree_add_item(tree, hf_ipmi_trn_lan25_address, tvb, 2, tvb_length(tvb) - 2, ENC_LITTLE_ENDIAN);
+                       proto_tree_add_item(tree, hf_ipmi_trn_lan25_address, tvb, 2, -1, ENC_LITTLE_ENDIAN);
                        break;
        }
 }
@@ -1017,11 +1017,10 @@ rq01(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_uint_format_value(tree, hf_ipmi_trn_01_param, tvb, 1, 1,
                        pno, "%s (0x%02x)", desc, pno);
        if (pno < array_length(lan_options)) {
-               next = tvb_new_subset(tvb, 2, tvb_length(tvb) - 2, tvb_length(tvb) - 2);
+               next = tvb_new_subset_remaining(tvb, 2);
                lan_options[pno].intrp(next, tree);
        } else {
-               proto_tree_add_item(tree, hf_ipmi_trn_01_param_data, tvb, 2,
-                               tvb_length(tvb) - 2, ENC_NA);
+               proto_tree_add_item(tree, hf_ipmi_trn_01_param_data, tvb, 2, -1, ENC_NA);
        }
 }
 
@@ -1044,9 +1043,10 @@ rq02(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 
        pno = tvb_get_guint8(tvb, 1);
 
+       ipmi_set_data(pinfo, 0, pno);
+       ipmi_set_data(pinfo, 1, tvb_get_guint8(tvb, 0) & 0x80);
+
        if (!tree) {
-               ipmi_setsaveddata(0, pno);
-               ipmi_setsaveddata(1, tvb_get_guint8(tvb, 0) & 0x80);
                return;
        }
 
@@ -1078,18 +1078,18 @@ rs02(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL,
                        ett_ipmi_trn_02_rev, byte1, ENC_LITTLE_ENDIAN, 0);
 
-       if (!ipmi_getsaveddata(0, &pno) || !ipmi_getsaveddata(1, &req)) {
+       if (!ipmi_get_data(pinfo, 0, &pno) || !ipmi_get_data(pinfo, 1, &req)) {
                /* No request found - cannot parse further */
-               if (tvb_length(tvb) > 1) {
-                       proto_tree_add_item(tree, hf_ipmi_trn_02_param_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+               if (tvb_captured_length(tvb) > 1) {
+                       proto_tree_add_item(tree, hf_ipmi_trn_02_param_data, tvb, 1, -1, ENC_NA);
                };
                return;
        }
 
-       if ((req & 0x80) && tvb_length(tvb) > 1) {
+       if ((req & 0x80) && tvb_captured_length(tvb) > 1) {
                ti = proto_tree_add_text(tree, tvb, 0, 0, "Requested parameter revision; parameter data returned");
                PROTO_ITEM_SET_GENERATED(ti);
-       } else if (!(req & 0x80) && tvb_length(tvb) == 1) {
+       } else if (!(req & 0x80) && tvb_captured_length(tvb) == 1) {
                ti = proto_tree_add_text(tree, tvb, 0, 0, "Requested parameter data; only parameter version returned");
                PROTO_ITEM_SET_GENERATED(ti);
        }
@@ -1105,13 +1105,12 @@ rs02(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        ti = proto_tree_add_text(tree, tvb, 0, 0, "Parameter: %s", desc);
        PROTO_ITEM_SET_GENERATED(ti);
 
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                if (pno < array_length(lan_options)) {
-                       next = tvb_new_subset(tvb, 1, tvb_length(tvb) - 1, tvb_length(tvb) - 1);
+                       next = tvb_new_subset_remaining(tvb, 1);
                        lan_options[pno].intrp(next, tree);
                } else {
-                       proto_tree_add_item(tree, hf_ipmi_trn_02_param_data, tvb, 1,
-                                       tvb_length(tvb) - 1, ENC_NA);
+                       proto_tree_add_item(tree, hf_ipmi_trn_02_param_data, tvb, 1, -1, ENC_NA);
                }
        }
 }
@@ -1271,7 +1270,7 @@ static void
 serial_10(tvbuff_t *tvb, proto_tree *tree)
 {
        proto_tree_add_item(tree, hf_ipmi_trn_serial10_set_sel, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       proto_tree_add_item(tree, hf_ipmi_trn_serial10_init_str, tvb, 1, tvb_length(tvb) - 1, ENC_ASCII|ENC_NA);
+       proto_tree_add_item(tree, hf_ipmi_trn_serial10_init_str, tvb, 1, -1, ENC_ASCII|ENC_NA);
 }
 
 static void
@@ -1574,7 +1573,7 @@ serial_40(tvbuff_t *tvb, proto_tree *tree)
        int slen;
 
        proto_tree_add_item(tree, hf_ipmi_trn_serial40_acct_sel, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       slen = tvb_length(tvb) - 1;
+       slen = tvb_captured_length(tvb) - 1;
        if (slen > 16) {
                slen = 16;
        }
@@ -1587,7 +1586,7 @@ serial_41(tvbuff_t *tvb, proto_tree *tree)
        int slen;
 
        proto_tree_add_item(tree, hf_ipmi_trn_serial41_acct_sel, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       slen = tvb_length(tvb) - 1;
+       slen = tvb_captured_length(tvb) - 1;
        if (slen > 16) {
                slen = 16;
        }
@@ -1600,7 +1599,7 @@ serial_42(tvbuff_t *tvb, proto_tree *tree)
        int slen;
 
        proto_tree_add_item(tree, hf_ipmi_trn_serial42_acct_sel, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       slen = tvb_length(tvb) - 1;
+       slen = tvb_captured_length(tvb) - 1;
        if (slen > 16) {
                slen = 16;
        }
@@ -1655,7 +1654,7 @@ serial_49(tvbuff_t *tvb, proto_tree *tree)
        int slen;
 
        proto_tree_add_item(tree, hf_ipmi_trn_serial49_blockno, tvb, 0, 1, ENC_LITTLE_ENDIAN);
-       slen = tvb_length(tvb) - 1;
+       slen = tvb_captured_length(tvb) - 1;
        if (slen > 16) {
                slen = 16;
        }
@@ -1784,11 +1783,10 @@ rq10(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_uint_format_value(tree, hf_ipmi_trn_10_param, tvb, 1, 1,
                        pno, "%s (0x%02x)", desc, pno);
        if (pno < array_length(serial_options)) {
-               next = tvb_new_subset(tvb, 2, tvb_length(tvb) - 2, tvb_length(tvb) - 2);
+               next = tvb_new_subset_remaining(tvb, 2);
                serial_options[pno].intrp(next, tree);
        } else {
-               proto_tree_add_item(tree, hf_ipmi_trn_10_param_data, tvb, 2,
-                               tvb_length(tvb) - 2, ENC_NA);
+               proto_tree_add_item(tree, hf_ipmi_trn_10_param_data, tvb, 2, -1, ENC_NA);
        }
 }
 
@@ -1811,9 +1809,10 @@ rq11(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 
        pno = tvb_get_guint8(tvb, 1);
 
+       ipmi_set_data(pinfo, 0, pno);
+       ipmi_set_data(pinfo, 1, tvb_get_guint8(tvb, 0));
+
        if (!tree) {
-               ipmi_setsaveddata(0, pno);
-               ipmi_setsaveddata(1, tvb_get_guint8(tvb, 0));
                return;
        }
 
@@ -1845,10 +1844,10 @@ rs11(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL,
                        ett_ipmi_trn_11_rev, byte1, ENC_LITTLE_ENDIAN, 0);
 
-       if (!ipmi_getsaveddata(0, &pno) || !ipmi_getsaveddata(1, &req)) {
+       if (!ipmi_get_data(pinfo, 0, &pno) || !ipmi_get_data(pinfo, 1, &req)) {
                /* No request found - cannot parse further */
-               if (tvb_length(tvb) > 1) {
-                       proto_tree_add_item(tree, hf_ipmi_trn_11_param_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
+               if (tvb_captured_length(tvb) > 1) {
+                       proto_tree_add_item(tree, hf_ipmi_trn_11_param_data, tvb, 1, -1, ENC_NA);
                };
                return;
        }
@@ -1861,10 +1860,10 @@ rs11(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
                desc = "Reserved";
        }
 
-       if ((req & 0x80) && tvb_length(tvb) > 1) {
+       if ((req & 0x80) && tvb_captured_length(tvb) > 1) {
                ti = proto_tree_add_text(tree, tvb, 0, 0, "Requested parameter revision; parameter data returned");
                PROTO_ITEM_SET_GENERATED(ti);
-       } else if (!(req & 0x80) && tvb_length(tvb) == 1) {
+       } else if (!(req & 0x80) && tvb_captured_length(tvb) == 1) {
                ti = proto_tree_add_text(tree, tvb, 0, 0, "Requested parameter data; only parameter version returned");
                PROTO_ITEM_SET_GENERATED(ti);
        }
@@ -1872,13 +1871,12 @@ rs11(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        ti = proto_tree_add_text(tree, tvb, 0, 0, "Parameter: %s", desc);
        PROTO_ITEM_SET_GENERATED(ti);
 
-       if (tvb_length(tvb) > 1) {
+       if (tvb_captured_length(tvb) > 1) {
                if (pno < array_length(serial_options)) {
-                       next = tvb_new_subset(tvb, 1, tvb_length(tvb) - 1, tvb_length(tvb) - 1);
+                       next = tvb_new_subset_remaining(tvb, 1);
                        serial_options[pno].intrp(next, tree);
                } else {
-                       proto_tree_add_item(tree, hf_ipmi_trn_11_param_data, tvb, 1,
-                                       tvb_length(tvb) - 1, ENC_NA);
+                       proto_tree_add_item(tree, hf_ipmi_trn_11_param_data, tvb, 1, -1, ENC_NA);
                }
        }
 }
@@ -2001,9 +1999,9 @@ rq17(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
        static const gint *byte1[] = { &hf_ipmi_trn_17_chan, NULL };
        static const gint *byte2[] = { &hf_ipmi_trn_17_clear, &hf_ipmi_trn_17_block_num, NULL };
 
+       ipmi_set_data(pinfo, 0, tvb_get_guint8(tvb, 1) & 0x7f);
        if (!tree) {
                /* Save block number */
-               ipmi_setsaveddata(0, tvb_get_guint8(tvb, 1) & 0x7f);
                return;
        }
 
@@ -2018,12 +2016,12 @@ rs17(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
 {
        guint32 bno;
 
-       if (ipmi_getsaveddata(0, &bno) && bno == 0) {
+       if (ipmi_get_data(pinfo, 0, &bno) && bno == 0) {
                /* Request for length */
                proto_tree_add_item(tree, hf_ipmi_trn_17_size, tvb, 0, 2, ENC_LITTLE_ENDIAN);
        } else {
                proto_tree_add_item(tree, hf_ipmi_trn_17_data, tvb, 0,
-                               tvb_length(tvb) < 16 ? tvb_length(tvb) : 16, ENC_NA);
+                               tvb_captured_length(tvb) < 16 ? tvb_captured_length(tvb) : 16, ENC_NA);
        }
 }
 
diff --git a/epan/dissectors/packet-ipmi-vita.c b/epan/dissectors/packet-ipmi-vita.c
new file mode 100755 (executable)
index 0000000..d41b33d
--- /dev/null
@@ -0,0 +1,1325 @@
+/* packet-ipmi-vita.c
+ * Sub-dissectors for IPMI messages (netFn=Group, defining body = VSO)
+ * Copyright 2014, Dmitry Bazhenov, Pigeon Point Systems <dima_b@pigeonpoint.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 "config.h"
+
+#include <epan/packet.h>
+
+#include "packet-ipmi.h"
+
+/* Tree type identifiers.
+*/
+static gint ett_vita_ipmc = -1;
+static gint ett_vita_ipmb = -1;
+static gint ett_vita_vso = -1;
+static gint ett_vita_led_caps = -1;
+static gint ett_vita_led_color = -1;
+static gint ett_vita_led_flags = -1;
+static gint ett_vita_led_states = -1;
+static gint ett_vita_ipmb_state = -1;
+static gint ett_vita_fru_policy_bits = -1;
+static gint ett_vita_fan_properties = -1;
+static gint ett_vita_fru_control_caps = -1;
+static gint ett_vita_chassis_addr_type = -1;
+static gint ett_vita_chassis_addr = -1;
+static gint ett_vita_persistent_control_state = -1;
+static gint ett_vita_persistent_control_caps = -1;
+
+/* Field identifiers.
+*/
+static gint hf_vita_reserved = -1;
+static gint hf_vita_fruid = -1;
+static gint hf_vita_addr_key_type = -1;
+static gint hf_vita_addr_key = -1;
+static gint hf_vita_hw_addr = -1;
+static gint hf_vita_ipmb_addr = -1;
+static gint hf_vita_site_type = -1;
+static gint hf_vita_site_num = -1;
+static gint hf_vita_ipmbl_addr = -1;
+
+static gint hf_vita_ipmc = -1;
+static gint hf_vita_tier = -1;
+static gint hf_vita_layer = -1;
+static gint hf_vita_ipmb = -1;
+static gint hf_vita_ipmb_itfs = -1;
+static gint hf_vita_ipmb_freq = -1;
+static gint hf_vita_vso = -1;
+static gint hf_vita_vso_std = -1;
+static gint hf_vita_rev = -1;
+static gint hf_vita_max_fruid = -1;
+static gint hf_vita_ipmc_fruid = -1;
+static gint hf_vita_fru_control = -1;
+
+static gint hf_vita_led_count = -1;
+static gint hf_vita_led_id = -1;
+static gint hf_vita_led_caps = -1;
+static gint hf_vita_led_cap_blue = -1;
+static gint hf_vita_led_cap_red = -1;
+static gint hf_vita_led_cap_green = -1;
+static gint hf_vita_led_cap_amber = -1;
+static gint hf_vita_led_cap_orange = -1;
+static gint hf_vita_led_cap_white = -1;
+static gint hf_vita_led_def_loc_color = -1;
+static gint hf_vita_led_def_ovr_color = -1;
+static gint hf_vita_led_color = -1;
+static gint hf_vita_led_flags = -1;
+static gint hf_vita_led_flag_pwr = -1;
+static gint hf_vita_led_flag_hw_restrict = -1;
+static gint hf_vita_led_states = -1;
+static gint hf_vita_led_loc_func = -1;
+static gint hf_vita_led_loc_duration = -1;
+static gint hf_vita_led_loc_color = -1;
+static gint hf_vita_led_ovr_func = -1;
+static gint hf_vita_led_ovr_duration = -1;
+static gint hf_vita_led_ovr_color = -1;
+static gint hf_vita_led_lamp_test_duration = -1;
+static gint hf_vita_led_state_local = -1;
+static gint hf_vita_led_state_override = -1;
+static gint hf_vita_led_state_lamp_test = -1;
+static gint hf_vita_led_state_hw_restrict = -1;
+
+static gint hf_vita_ipmba_state = -1;
+static gint hf_vita_ipmbb_state = -1;
+static gint hf_vita_ipmb_state = -1;
+static gint hf_vita_ipmb_link_id = -1;
+
+static gint hf_vita_fru_policy_mask_bits = -1;
+static gint hf_vita_fru_policy_set_bits = -1;
+static gint hf_vita_fru_policy_bits = -1;
+static gint hf_vita_fru_activation_locked = -1;
+static gint hf_vita_fru_deactivation_locked = -1;
+static gint hf_vita_fru_commanded_deactivation_ignored = -1;
+static gint hf_vita_fru_default_activation_locked = -1;
+
+static gint hf_vita_fru_activation = -1;
+
+static gint hf_vita_record_id = -1;
+
+static gint hf_vita_fan_min_level = -1;
+static gint hf_vita_fan_max_level = -1;
+static gint hf_vita_fan_norm_level = -1;
+static gint hf_vita_fan_properties = -1;
+static gint hf_vita_fan_prop_local_control = -1;
+static gint hf_vita_fan_override_level = -1;
+static gint hf_vita_fan_local_level = -1;
+static gint hf_vita_fan_local_control = -1;
+
+static gint hf_vita_ipmb_link_key_type = -1;
+static gint hf_vita_ipmb_link_key_value = -1;
+static gint hf_vita_ipmb_link_number = -1;
+static gint hf_vita_ipmb_sensor_number = -1;
+
+static gint hf_vita_active_chmc_ipmb_addr = -1;
+static gint hf_vita_backup_chmc_ipmb_addr = -1;
+
+static gint hf_vita_fan_number = -1;
+static gint hf_vita_fan_policy = -1;
+static gint hf_vita_fan_policy_timeout = -1;
+static gint hf_vita_fan_coverage = -1;
+
+static gint hf_vita_fru_control_caps = -1;
+static gint hf_vita_fru_control_cap_cold = -1;
+static gint hf_vita_fru_control_cap_warm = -1;
+static gint hf_vita_fru_control_cap_grace = -1;
+static gint hf_vita_fru_control_cap_diag = -1;
+static gint hf_vita_fru_control_cap_pwr = -1;
+
+static gint hf_vita_fru_lock_operation = -1;
+static gint hf_vita_fru_lock_id = -1;
+static gint hf_vita_fru_lock_timestamp = -1;
+
+static gint hf_vita_fru_write_offset = -1;
+static gint hf_vita_fru_write_data = -1;
+static gint hf_vita_fru_write_count = -1;
+
+static gint hf_vita_chassis_addr_number = -1;
+static gint hf_vita_chassis_addr_timestamp = -1;
+static gint hf_vita_chassis_addr_count = -1;
+static gint hf_vita_chassis_max_unavail = -1;
+static gint hf_vita_chassis_addr_type = -1;
+static gint hf_vita_chassis_addr = -1;
+static gint hf_vita_chassis_addr_chmc = -1;
+static gint hf_vita_chassis_addr_format = -1;
+static gint hf_vita_ipv4_addr = -1;
+static gint hf_vita_rmcp_port = -1;
+
+static gint hf_vita_persistent_control_state = -1;
+static gint hf_vita_persistent_control_cold = -1;
+static gint hf_vita_persistent_control_warm = -1;
+static gint hf_vita_persistent_control_mask = -1;
+static gint hf_vita_persistent_control_set = -1;
+static gint hf_vita_persistent_control_caps = -1;
+static gint hf_vita_persistent_control_cap_cold = -1;
+static gint hf_vita_persistent_control_cap_warm = -1;
+
+static gint hf_vita_fru_state_sensor_num = -1;
+static gint hf_vita_fru_health_sensor_num = -1;
+static gint hf_vita_fru_voltage_sensor_num = -1;
+static gint hf_vita_fru_temp_sensor_num = -1;
+static gint hf_vita_payload_test_results_sensor_num = -1;
+static gint hf_vita_payload_test_status_sensor_num = -1;
+
+/* String values.
+*/
+static const value_string str_vita_ipmc_tiers[] = {
+       { 0x00, "Tier-1" },
+       { 0x01, "Tier-2" },
+       { 0x02, "Reserved" },
+       { 0x03, "Reserved" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_ipmc_layers[] = {
+       { 0x00, "IPMC" },
+       { 0x01, "Chassis Manager" },
+       { 0x02, "System Manager" },
+       { 0x03, "Reserved" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_ipmb_itfs[] = {
+       { 0x00, "1 IPMB interface" },
+       { 0x01, "2 IPMB interfaces" },
+       { 0x02, "Reserved" },
+       { 0x03, "Reserved" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_ipmb_freq[] = {
+       { 0x00, "100KHz" },
+       { 0x01, "400KHz" },
+       { 0x02, "Reserved" },
+       { 0x03, "Reserved" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_vso_std[] = {
+       { 0x00, "VITA 46.11" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_addr_key_types[] = {
+       { 0x00, "Hardware Address" },
+       { 0x01, "IPMB Address" },
+       { 0x02, "Reserved" },
+       { 0x03, "Physical Address" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_site_types[] = {
+       { 0x00, "Front Loading VPX Plug-In Module" },
+       { 0x01, "Power Entry Module" },
+       { 0x02, "Chassis FRU Information Module" },
+       { 0x03, "Dedicated ChMC" },
+       { 0x04, "Fan Tray" },
+       { 0x05, "Fan Tray Filter" },
+       { 0x06, "Alarm Panel" },
+       { 0x07, "XMC" },
+       { 0x08, "Reserved" },
+       { 0x09, "VPX Rear Transition Module" },
+       { 0x0A, "Reserved" },
+       { 0x0B, "Reserved" },
+       { 0x0C, "Power Supply" },
+       { 0x0D, "Reserved" },
+       { 0x0E, "Reserved" },
+       { 0x0F, "FMC" },
+       { 0xC0, "OEM" },
+       { 0xC1, "OEM" },
+       { 0xC2, "OEM" },
+       { 0xC3, "OEM" },
+       { 0xC4, "OEM" },
+       { 0xC5, "OEM" },
+       { 0xC6, "OEM" },
+       { 0xC7, "OEM" },
+       { 0xC8, "OEM" },
+       { 0xC9, "OEM" },
+       { 0xCA, "OEM" },
+       { 0xCB, "OEM" },
+       { 0xCC, "OEM" },
+       { 0xCD, "OEM" },
+       { 0xCE, "OEM" },
+       { 0xCF, "OEM" },
+       { 0, NULL }
+};
+
+static value_string_ext str_vita_site_types_ext = VALUE_STRING_EXT_INIT(str_vita_site_types);
+
+static const value_string str_vita_fru_controls[] = {
+       { 0x00, "Cold Reset" },
+       { 0x01, "Warm Reset" },
+       { 0x02, "Graceful Reboot" },
+       { 0x03, "Diagnostic Interrupt" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_led_colors[] = {
+       { 0x00, "Reserved (Control not supported)" },
+       { 0x01, "BLUE" },
+       { 0x02, "RED" },
+       { 0x03, "GREEN" },
+       { 0x04, "AMBER" },
+       { 0x05, "ORANGE" },
+       { 0x06, "WHITE" },
+       { 0x0E, "Do not change" },
+       { 0x0F, "Use default" },
+       { 0, NULL }
+};
+
+static const range_string str_vita_led_func[] = {
+       { 0x00, 0x00, "LED off" },
+       { 0x01, 0xFA, "LED BLINKING (off duration)" },
+       { 0xFB, 0xFB, "LAMP TEST" },
+       { 0xFC, 0xFC, "LED restored to Local Control state" },
+       { 0xFF, 0xFF, "LED on" },
+       { 0, 0, NULL }
+};
+
+static const range_string str_vita_ipmb_state[] = {
+       { 0x0, 0xFE, "System IPMB state" },
+       { 0xFF, 0xFF, "Do not change current state" },
+       { 0, 0, NULL }
+};
+
+static const true_false_string str_vita_ipmb_override = {
+       "Local Control State",
+       "Override state - Isolate(disable)"
+};
+
+static const range_string str_vita_ipmb_link_id[] = {
+       { 0x00, 0x00, "Select all System IPMB Links" },
+       { 0x01, 0x5F, "System IPMB Link Number" },
+       { 0x60, 0x7F, "Reserved" },
+       { 0, 0, NULL }
+};
+
+static const value_string str_vita_fru_activation[] = {
+       { 0x00, "Deactivate FRU" },
+       { 0x01, "Activate FRU" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_fan_levels[] = {
+       { 0xFE, "Shut Down" },
+       { 0xFF, "Local Control" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_fan_local_control[] = {
+       { 0x00, "Disabled" },
+       { 0x01, "Enabled" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_ipmb_link_key_types[] = {
+       { 0x00, "Key is IPMB Link Number" },
+       { 0x01, "Key is IPMB Sensor Number" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_fan_policies[] = {
+       { 0x00, "Disable" },
+       { 0x01, "Enable" },
+       { 0xFF, "Indeterminate" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_fan_policy_timeouts[] = {
+       { 0xFF, "Infinite" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_fan_coverages[] = {
+       { 0x00, "Not Covered" },
+       { 0x01, "Covered" },
+       { 0, NULL }
+};
+
+static const value_string str_vita_fru_lock_operations[] = {
+       { 0x00, "Get Last Commit Timestamp" },
+       { 0x01, "Lock" },
+       { 0x02, "Unlock and Discard" },
+       { 0x03, "Unlock and Commit      " },
+       { 0, NULL }
+};
+
+static const range_string str_vita_chassis_addr_formats[] = {
+       { 0x00, 0x00, "IPv4 Address" },
+       { 0x01, 0x5F, "Reserved" },
+       { 0x60, 0x7F, "OEM" },
+       { 0, 0, NULL }
+};
+
+
+static const value_string cc1F[] = {
+       { 0x80, "Invalid FRU Information" },
+       { 0x81, "Lock Failed" },
+       { 0, NULL }
+};
+
+static const value_string cc20[] = {
+       { 0x80, "Invalid Lock ID" },
+       { 0, NULL }
+};
+
+
+/* Array of sub-tree identifiers (needed for registration).
+*/
+static gint * const ett_ipmi_vita[] = {
+       &ett_vita_ipmc,
+       &ett_vita_ipmb,
+       &ett_vita_vso,
+       &ett_vita_led_caps,
+       &ett_vita_led_color,
+       &ett_vita_led_flags,
+       &ett_vita_led_states,
+       &ett_vita_ipmb_state,
+       &ett_vita_fru_policy_bits,
+       &ett_vita_fan_properties,
+       &ett_vita_fru_control_caps,
+       &ett_vita_chassis_addr_type,
+       &ett_vita_chassis_addr,
+       &ett_vita_persistent_control_state,
+       &ett_vita_persistent_control_caps
+};
+
+static const int * bits_vita_led_color[] = {
+       &hf_vita_led_color,
+       NULL
+};
+
+static const int * bits_vita_fru_policy_bits[] = {
+       &hf_vita_fru_activation_locked,
+       &hf_vita_fru_deactivation_locked,
+       &hf_vita_fru_commanded_deactivation_ignored,
+       &hf_vita_fru_default_activation_locked,
+       NULL
+};
+
+static const int * bits_vita_persistent_control_state[] = {
+       &hf_vita_persistent_control_cold,
+       &hf_vita_persistent_control_warm,
+       NULL
+};
+
+/* Array of field descriptors.
+*/
+static hf_register_info hf_ipmi_vita[] = {
+       { &hf_vita_ipmc,
+               { "IPMC Identifier", "ipmi.vita.ipmc",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_tier,
+               { "Tier Functionality", "ipmi.vita.ipmc.tier",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_ipmc_tiers), 0x3, NULL, HFILL }},
+       { &hf_vita_layer,
+               { "Layer Functionality", "ipmi.vita.ipmc.tier",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_ipmc_layers), 0x30, NULL, HFILL }},
+       { &hf_vita_ipmb,
+               { "IPMB Capabilities", "ipmi.vita.ipmb",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_ipmb_itfs,
+               { "Number of supported interfaces", "ipmi.vita.ipmc.itfs",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_ipmb_itfs), 0x3, NULL, HFILL }},
+       { &hf_vita_ipmb_freq,
+               { "Maximum operating frequency", "ipmi.vita.ipmc.freq",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_ipmb_freq), 0x30, NULL, HFILL }},
+       { &hf_vita_vso,
+               { "VSO Standard", "ipmi.vita.vso",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_vso_std,
+               { "VSO Standard", "ipmi.vita.vso.std",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_vso_std), 0x3, NULL, HFILL }},
+       { &hf_vita_rev,
+               { "VSO Specification Revision", "ipmi.vita.vso.rev",
+                       FT_UINT8, BASE_CUSTOM, ipmi_fmt_version, 0, NULL, HFILL }},
+       { &hf_vita_max_fruid,
+               { "Max FRU Device ID", "ipmi.vita.max.fruid",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_ipmc_fruid,
+               { "FRU Device ID for IPMC", "ipmi.vita.ipmc.fruid",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fruid,
+               { "FRU Device ID", "ipmi.vita.fruid",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_addr_key_type,
+               { "Address Key Type", "ipmi.vita.key.type",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_addr_key_types), 0, NULL, HFILL }},
+       { &hf_vita_addr_key,
+               { "Address Key", "ipmi.vita.key",
+                       FT_UINT8, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_site_type,
+               { "Site Type", "ipmi.vita.site.type",
+                       FT_UINT8, BASE_HEX|BASE_EXT_STRING, &str_vita_site_types_ext, 0, NULL, HFILL }},
+       { &hf_vita_hw_addr,
+               { "Hardware Address", "ipmi.vita.hwaddr",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_ipmb_addr,
+               { "IPMB Address", "ipmi.vita.ipmb.addr",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_site_num,
+               { "Site Number", "ipmi.vita.site.num",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_ipmbl_addr,
+               { "Address on IPMI Channel 7", "ipmi.vita.ipmbl.addr",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_reserved,
+               { "Reserved", "ipmi.vita.reserved",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_control,
+               { "FRU Control", "ipmi.vita.fru.control",
+                       FT_UINT8, BASE_DEC, VALS(str_vita_fru_controls), 0, NULL, HFILL }},
+       { &hf_vita_led_count,
+               { "LED Count", "ipmi.vita.led.count",
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_id,
+               { "LED ID", "ipmi.vita.led.id",
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_caps,
+               { "LED Color Capabilities", "ipmi.vita.led.caps",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_cap_blue,
+               { "LED supports BLUE", "ipmi.vita.led.cap.blue",
+                       FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+       { &hf_vita_led_cap_red,
+               { "LED supports RED", "ipmi.vita.led.cap.red",
+                       FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }},
+       { &hf_vita_led_cap_green,
+               { "LED supports GREEN", "ipmi.vita.led.cap.green",
+                       FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }},
+       { &hf_vita_led_cap_amber,
+               { "LED supports AMBER", "ipmi.vita.led.cap.amber",
+                       FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }},
+       { &hf_vita_led_cap_orange,
+               { "LED supports ORANGE", "ipmi.vita.led.cap.orange",
+                       FT_BOOLEAN, 8, NULL, 0x20, NULL, HFILL }},
+       { &hf_vita_led_cap_white,
+               { "LED supports WHITE", "ipmi.vita.led.cap.white",
+                       FT_BOOLEAN, 8, NULL, 0x40, NULL, HFILL }},
+       { &hf_vita_led_def_loc_color,
+               { "Default LED Color in Local Control State", "ipmi.vita.led.def.loc.color",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_def_ovr_color,
+               { "Default LED Color in Override State", "ipmi.vita.led.def.ovr.color",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_flags,
+               { "LED Flags", "ipmi.vita.led.flags",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_flag_pwr,
+               { "LED is powered from Payload power", "ipmi.vita.led.flag.pwr",
+                       FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+       { &hf_vita_led_flag_hw_restrict,
+               { "LED has other hardware restrictions", "ipmi.vita.led.flag.hw.restrict",
+                       FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+       { &hf_vita_led_color,
+               { "LED Color Value", "ipmi.vita.led.color",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_led_colors), 0x0F, NULL, HFILL }},
+       { &hf_vita_led_ovr_func,
+               { "Override State LED Function", "ipmi.vita.led.ovr.func",
+                       FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(str_vita_led_func), 0, NULL, HFILL }},
+       { &hf_vita_led_ovr_duration,
+               { "Override State On-Duration", "ipmi.vita.led.ovr.diration",
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_ovr_color,
+               { "Override State Color", "ipmi.vita.led.ovr.color",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_lamp_test_duration,
+               { "Lamp Test Duration", "ipmi.vita.led.lamp.duration",
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_loc_func,
+               { "Local Control LED Function", "ipmi.vita.led.loc.func",
+                       FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(str_vita_led_func), 0, NULL, HFILL }},
+       { &hf_vita_led_loc_duration,
+               { "Local Control On-Duration", "ipmi.vita.led.loc.diration",
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_loc_color,
+               { "Local Control Color", "ipmi.vita.led.loc.color",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_states,
+               { "LED States", "ipmi.vita.led.states",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_led_state_local,
+               { "Local Control State", "ipmi.vita.led.state.loc",
+                       FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+       { &hf_vita_led_state_override,
+               { "Override State", "ipmi.vita.led.state.ovr",
+                       FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+       { &hf_vita_led_state_lamp_test,
+               { "Lamp Test", "ipmi.vita.led.state.lamp",
+                       FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }},
+       { &hf_vita_led_state_hw_restrict,
+               { "Hardware Restriction", "ipmi.vita.led.state.hw",
+                       FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }},
+       { &hf_vita_ipmba_state,
+               { "IPMB-A State", "ipmi.vita.ipmba.state",
+                       FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(str_vita_ipmb_state), 0, NULL, HFILL }},
+       { &hf_vita_ipmbb_state,
+               { "IPMB-B State", "ipmi.vita.ipmbb.state",
+                       FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(str_vita_ipmb_state), 0, NULL, HFILL }},
+       { &hf_vita_ipmb_state,
+               { "IPMB State", "ipmi.vita.ipmb.ovr",
+                       FT_BOOLEAN, 8, TFS(&str_vita_ipmb_override), 0x01, NULL, HFILL }},
+       { &hf_vita_ipmb_link_id,
+               { "IPMB Link ID", "ipmi.vita.ipmb.link.id",
+                       FT_UINT8, BASE_DEC_HEX|BASE_RANGE_STRING, RVALS(str_vita_ipmb_link_id), 0xFE, NULL, HFILL }},
+       { &hf_vita_fru_policy_mask_bits,
+               { "FRU Activation Policy Mask Bits", "ipmi.vita.fru.policy.mask",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_policy_set_bits,
+               { "FRU Activation Policy Set Bits", "ipmi.vita.fru.policy.set",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_policy_bits,
+               { "FRU Activation Policies", "ipmi.vita.fru.policy.bits",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_activation_locked,
+               { "Activation Locked", "ipmi.vita.fru.policy.al",
+                       FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+       { &hf_vita_fru_deactivation_locked,
+               { "Deactivation Locked", "ipmi.vita.fru.policy.dl",
+                       FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+       { &hf_vita_fru_commanded_deactivation_ignored,
+               { "Commanded Deactivation Ignored", "ipmi.vita.fru.policy.cdi",
+                       FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }},
+       { &hf_vita_fru_default_activation_locked,
+               { "Default Activation Locked", "ipmi.vita.fru.policy.dal",
+                       FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }},
+       { &hf_vita_fru_activation,
+               { "FRU Activation/Deactivation", "ipmi.vita.fru.activation",
+                       FT_UINT8, BASE_DEC, VALS(str_vita_fru_activation), 0, NULL, HFILL }},
+       { &hf_vita_record_id,
+               { "Record ID", "ipmi.vita.record.id",
+                       FT_UINT16, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fan_min_level,
+               { "Minimum Speed Level", "ipmi.vita.fan.min",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fan_max_level,
+               { "Maximum Speed Level", "ipmi.vita.fan.max",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fan_norm_level,
+               { "Normal Operating Level", "ipmi.vita.fan.norm",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fan_properties,
+               { "Fan Tray Properties", "ipmi.vita.fan.props",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fan_prop_local_control,
+               { "Local Control Supported", "ipmi.vita.fan.prop.lc",
+                       FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }},
+       { &hf_vita_fan_override_level,
+               { "Override Fan Level", "ipmi.vita.fan.ovr",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_fan_levels), 0, NULL, HFILL }},
+       { &hf_vita_fan_local_level,
+               { "Local Control Fan Level", "ipmi.vita.fan.loc",
+                       FT_UINT8, BASE_HEX, VALS(str_vita_fan_levels), 0, NULL, HFILL }},
+       { &hf_vita_fan_local_control,
+               { "Local Control Enable State", "ipmi.vita.fan.lc",
+                       FT_UINT8, BASE_DEC, VALS(str_vita_fan_local_control), 0, NULL, HFILL }},
+       { &hf_vita_ipmb_link_key_type,
+               { "IPMB Link Info Key Type", "ipmi.vita.ipmb.link.key.type",
+                       FT_UINT8, BASE_DEC, VALS(str_vita_ipmb_link_key_types), 0, NULL, HFILL }},
+       { &hf_vita_ipmb_link_key_value,
+               { "IPMB Link Info Key", "ipmi.vita.ipmb.link.key.value",
+                               FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_ipmb_link_number,
+               { "IPMB Link Number", "ipmi.vita.ipmb.link.number",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_ipmb_sensor_number,
+               { "IPMB Sensor Number", "ipmi.vita.ipmb.sensor.number",
+                       FT_UINT8, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_active_chmc_ipmb_addr,
+               { "Active Chassis Manager IPMB Address", "ipmi.vita.active.chmc.ipmb.addr",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_backup_chmc_ipmb_addr,
+               { "Backup Chassis Manager IPMB Address", "ipmi.vita.backup.chmc.ipmb.addr",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fan_number,
+               { "Fan Tray Site Number", "ipmi.vita.fan.num",
+                       FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fan_policy,
+               { "Fan Enable State", "ipmi.vita.fan.policy",
+                       FT_UINT8, BASE_DEC, VALS(str_vita_fan_policies), 0, NULL, HFILL }},
+       { &hf_vita_fan_policy_timeout,
+               { "Fan Policy Timeout", "ipmi.vita.fan.policy.timeout",
+                       FT_UINT8, BASE_DEC, VALS(str_vita_fan_policy_timeouts), 0, NULL, HFILL }},
+       { &hf_vita_fan_coverage,
+               { "Coverage", "ipmi.vita.fan.coverage",
+                       FT_UINT8, BASE_DEC, VALS(str_vita_fan_coverages), 0, NULL, HFILL }},
+       { &hf_vita_fru_control_caps,
+               { "FRU Control Capabilities Mask", "ipmi.vita.fru.control.caps",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_control_cap_cold,
+               { "Capable of issuing a cold reset", "ipmi.vita.fru.control.cap.cold",
+                       FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+       { &hf_vita_fru_control_cap_warm,
+               { "Capable of issuing a warm reset", "ipmi.vita.fru.control.cap.warm",
+                       FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+       { &hf_vita_fru_control_cap_grace,
+               { "Capable of issuing a graceful reboot", "ipmi.vita.fru.control.cap.grace",
+                       FT_BOOLEAN, 8, NULL, 0x04, NULL, HFILL }},
+       { &hf_vita_fru_control_cap_diag,
+               { "Capable of issuing a diagnostic interrupt", "ipmi.vita.fru.control.cap.diag",
+                       FT_BOOLEAN, 8, NULL, 0x08, NULL, HFILL }},
+       { &hf_vita_fru_control_cap_pwr,
+               { "Capable of controlling payload power", "ipmi.vita.fru.control.cap.pwr",
+                       FT_BOOLEAN, 8, NULL, 0x10, NULL, HFILL }},
+       { &hf_vita_fru_lock_operation,
+               { "FRU Inventory Device Lock Operation", "ipmi.vita.fru.lock.op",
+                       FT_UINT8, BASE_DEC, VALS(str_vita_fru_lock_operations), 0, NULL, HFILL }},
+       { &hf_vita_fru_lock_id,
+               { "FRU Inventory Device Lock ID", "ipmi.vita.fru.lock.id",
+                       FT_UINT16, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_lock_timestamp,
+               { "FRU Inventory Device Last Commit Timestamp", "ipmi.vita.fru.lock.stamp",
+                       FT_UINT32, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_write_offset,
+               { "FRU Inventory offset to write", "ipmi.vita.fru.write.offset",
+                       FT_UINT16, BASE_DEC_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_write_data,
+               { "Data to write", "ipmi.vita.fru.write.data",
+                       FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_write_count,
+               { "Written byte count", "ipmi.vita.fru.write.count",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_chassis_addr_number,
+               { "Address Number", "ipmi.vita.chassis.addr.num",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_chassis_addr_timestamp,
+               { "Chassis IP Address Last Change Timestamp", "ipmi.vita.chassis.stamp",
+                       FT_UINT32, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_chassis_addr_count,
+               { "Address Count", "ipmi.vita.chassis.addr.count",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_chassis_max_unavail,
+               { "Maximum Unavailable Time", "ipmi.vita.chassis.max.unavail",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_chassis_addr_type,
+               { "Address Type", "ipmi.vita.chassis.addr.type",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_chassis_addr,
+               { "Address", "ipmi.vita.chassis.addr",
+                       FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
+       { &hf_vita_chassis_addr_chmc,
+               { "Chassis Manager IP Address", "ipmi.vita.chassis.addr.chmc",
+                       FT_BOOLEAN, 8, NULL, 0x80, NULL, HFILL }},
+       { &hf_vita_chassis_addr_format,
+               { "Address Type", "ipmi.vita.chassis.addr.format",
+                       FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(str_vita_chassis_addr_formats), 0x7F, NULL, HFILL }},
+       { &hf_vita_ipv4_addr,
+               { "IPv4 Address", "ipmi.vita.ipv4.addr",
+                       FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL }},
+       { &hf_vita_rmcp_port,
+               { "RMCP Port", "ipmi.vita.rmcp.port",
+                       FT_UINT16, BASE_HEX_DEC, NULL, 0, NULL, HFILL }},
+       { &hf_vita_persistent_control_state,
+               { "FRU Persistent Control Current State", "ipmi.vita.pers.state",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_persistent_control_cold,
+               { "Persistent Cold Reset State", "ipmi.vita.pers.state.cold",
+                       FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+       { &hf_vita_persistent_control_warm,
+               { "Persistent Warm Reset State", "ipmi.vita.pers.state.warm",
+                       FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+       { &hf_vita_persistent_control_mask,
+               { "FRU Persistent Control Selection Mask", "ipmi.vita.pers.mask",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_persistent_control_set,
+               { "FRU Persistent Control Selection", "ipmi.vita.pers.set",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_persistent_control_caps,
+               { "FRU Persistent Control Capabilities Mask", "ipmi.vita.pers.caps",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_persistent_control_cap_cold,
+               { "Capable of asserting a persistent cold reset", "ipmi.vita.pers.cap.cold",
+                       FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL }},
+       { &hf_vita_persistent_control_cap_warm,
+               { "Capable of asserting a persistent warm reset", "ipmi.vita.pers.cap.warm",
+                       FT_BOOLEAN, 8, NULL, 0x02, NULL, HFILL }},
+       { &hf_vita_fru_state_sensor_num,
+               { "FRU State Sensor Number", "ipmi.vita.sensor.fru.state",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_health_sensor_num,
+               { "FRU Health Sensor Number", "ipmi.vita.sensor.fru.health",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_voltage_sensor_num,
+               { "FRU Voltage Sensor Number", "ipmi.vita.sensor.fru.voltage",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_fru_temp_sensor_num,
+               { "FRU Temperature Sensor Number", "ipmi.vita.sensor.fru.temp",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_payload_test_results_sensor_num,
+               { "Payload Test Results Sensor Number", "ipmi.vita.sensor.payload.test.res",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
+       { &hf_vita_payload_test_status_sensor_num,
+               { "Payload Test Status Sensor Number", "ipmi.vita.sensor.payload.test.status",
+                       FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }}
+};
+
+/* Get VSO Capabilities (response).
+ */
+static void
+cmd00_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint * bits_vita_ipmc[] = {
+               &hf_vita_tier, &hf_vita_layer, NULL
+       };
+       static const gint * bits_vita_ipmb[] = {
+               &hf_vita_ipmb_itfs, &hf_vita_ipmb_freq, NULL
+       };
+       static const gint * bits_vita_vso[] = {
+               &hf_vita_vso_std, NULL
+       };
+
+       proto_tree_add_bitmask(tree, tvb, 0, hf_vita_ipmc,
+                       ett_vita_ipmc, bits_vita_ipmc, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 1, hf_vita_ipmb,
+                       ett_vita_ipmb, bits_vita_ipmb, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 2, hf_vita_vso,
+                       ett_vita_vso, bits_vita_vso, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_rev, tvb, 3, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_max_fruid, tvb, 4, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_ipmc_fruid, tvb, 5, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get Chassis Address Table Info (request).
+*/
+static void
+cmd01_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       guint len = tvb_captured_length(tvb);
+
+       if (len > 0) {
+               proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       }
+       if (len > 1) {
+               proto_tree_add_item(tree, hf_vita_addr_key_type, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       }
+       if (len > 2) {
+               proto_tree_add_item(tree, hf_vita_addr_key, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+       if (len > 3) {
+               proto_tree_add_item(tree, hf_vita_site_type, tvb, 3, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get Chassis Address Table Info (response).
+ */
+static void
+cmd01_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_hw_addr, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_ipmb_addr, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_reserved, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 3, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_site_num, tvb, 4, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_site_type, tvb, 5, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 7) {
+               proto_tree_add_item(tree, hf_vita_reserved, tvb, 6, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_vita_ipmbl_addr, tvb, 7, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get Chassis Identifier (response), Set Chassis Identifier (request)
+*/
+static void
+cmd02_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       ipmi_add_typelen(tree, "Chassis Identifier", tvb, 0, TRUE);
+}
+
+/* FRU Control (request)
+*/
+static void
+cmd04_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_control, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get FRU LED Properties (request)
+*/
+static void
+cmd05_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get FRU LED Properties (response)
+*/
+static void
+cmd05_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_reserved, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_led_count, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get LED Color Capabilities (request)
+*/
+static void
+cmd06_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_led_id, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get LED Color Capabilities (response)
+*/
+static void
+cmd06_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const gint * bits_vita_led_caps[] = {
+               &hf_vita_led_cap_white, &hf_vita_led_cap_orange,
+               &hf_vita_led_cap_amber, &hf_vita_led_cap_green,
+               &hf_vita_led_cap_red, &hf_vita_led_cap_blue,
+               NULL
+       };
+       static const int * bits_vita_led_flags[] = {
+               &hf_vita_led_flag_pwr,
+               &hf_vita_led_flag_hw_restrict,
+               NULL
+       };
+
+       proto_tree_add_bitmask(tree, tvb, 0, hf_vita_led_caps,
+                       ett_vita_led_caps, bits_vita_led_caps, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 1, hf_vita_led_def_loc_color,
+                       ett_vita_led_color, bits_vita_led_color, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 2, hf_vita_led_def_ovr_color,
+                       ett_vita_led_color, bits_vita_led_color, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 3, hf_vita_led_flags,
+                       ett_vita_led_flags, bits_vita_led_flags, ENC_LITTLE_ENDIAN);
+}
+
+/* Set FRU LED State (request)
+*/
+static void
+cmd07_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_led_id, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_led_ovr_func, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_led_ovr_duration, tvb, 3, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 4, hf_vita_led_ovr_color,
+                       ett_vita_led_color, bits_vita_led_color, ENC_LITTLE_ENDIAN);
+}
+
+/* Get FRU LED State (response)
+*/
+static void
+cmd08_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const int * bits_vita_led_states[] = {
+               &hf_vita_led_state_local,
+               &hf_vita_led_state_override,
+               &hf_vita_led_state_lamp_test,
+               &hf_vita_led_state_hw_restrict,
+               NULL
+       };
+       proto_tree_add_bitmask(tree, tvb, 0, hf_vita_led_states,
+                       ett_vita_led_states, bits_vita_led_states, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_led_loc_func, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_led_loc_duration, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 3, hf_vita_led_loc_color,
+                       ett_vita_led_color, bits_vita_led_color, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 4) {
+               proto_tree_add_item(tree, hf_vita_led_ovr_func, tvb, 4, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_vita_led_ovr_duration, tvb, 5, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_bitmask(tree, tvb, 6, hf_vita_led_ovr_color,
+                       ett_vita_led_color, bits_vita_led_color, ENC_LITTLE_ENDIAN);
+       }
+       if (tvb_captured_length(tvb) > 7) {
+               proto_tree_add_item(tree, hf_vita_led_lamp_test_duration, tvb, 7, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Set IPMB State (request)
+*/
+static void
+cmd09_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const int * bits_vita_ipmb_state[] = {
+               &hf_vita_ipmb_state,
+               &hf_vita_ipmb_link_id,
+               NULL
+       };
+       proto_tree_add_bitmask(tree, tvb, 0, hf_vita_ipmba_state,
+                       ett_vita_ipmb_state, bits_vita_ipmb_state, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 1, hf_vita_ipmbb_state,
+                       ett_vita_ipmb_state, bits_vita_ipmb_state, ENC_LITTLE_ENDIAN);
+}
+
+/* Set FRU State Policy Bits (request)
+*/
+static void
+cmd0A_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 1, hf_vita_fru_policy_mask_bits,
+                       ett_vita_fru_policy_bits, bits_vita_fru_policy_bits,
+                       ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 2, hf_vita_fru_policy_set_bits,
+                       ett_vita_fru_policy_bits, bits_vita_fru_policy_bits,
+                       ENC_LITTLE_ENDIAN);
+}
+
+/* Get FRU State Policy Bits (response)
+*/
+static void
+cmd0B_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_bitmask(tree, tvb, 0, hf_vita_fru_policy_bits,
+                       ett_vita_fru_policy_bits, bits_vita_fru_policy_bits,
+                       ENC_LITTLE_ENDIAN);
+}
+
+/* Set FRU Activation (request)
+*/
+static void
+cmd0C_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_activation, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get FRU Device Locator Record ID (response)
+*/
+static void
+cmd0D_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_record_id, tvb, 0, 2, ENC_LITTLE_ENDIAN);
+}
+
+/* Get FAN Speed Properties (response)
+*/
+static void
+cmd14_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const int * bits_vita_fan_properties[] = {
+               &hf_vita_fan_prop_local_control,
+               NULL
+       };
+       proto_tree_add_item(tree, hf_vita_fan_min_level, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fan_max_level, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fan_norm_level, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 3, hf_vita_fan_properties,
+                       ett_vita_fan_properties, bits_vita_fan_properties, ENC_LITTLE_ENDIAN);
+}
+
+/* Set FAN Level (request)
+*/
+static void
+cmd15_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fan_override_level, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 2) {
+               proto_tree_add_item(tree, hf_vita_fan_local_control, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get FAN Level (response)
+*/
+static void
+cmd16_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fan_override_level, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 1) {
+               proto_tree_add_item(tree, hf_vita_fan_local_level, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       }
+       if (tvb_captured_length(tvb) > 2) {
+               proto_tree_add_item(tree, hf_vita_fan_local_control, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get IPMB Link Info (request)
+*/
+static void
+cmd18_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_ipmb_link_key_type, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_ipmb_link_key_value, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get IPMB Link Info (response)
+*/
+static void
+cmd18_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_ipmb_link_number, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_ipmb_sensor_number, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get Chassis Manager IPMB Address (response)
+*/
+static void
+cmd1B_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_active_chmc_ipmb_addr, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_backup_chmc_ipmb_addr, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Set FAN Policy (request)
+*/
+static void
+cmd1C_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fan_number, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fan_policy, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 2) {
+               proto_tree_add_item(tree, hf_vita_fan_policy_timeout, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+       if (tvb_captured_length(tvb) > 3) {
+               proto_tree_add_item(tree, hf_vita_site_num, tvb, 3, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_vita_site_type, tvb, 4, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get FAN Policy (request)
+*/
+static void
+cmd1D_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fan_number, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 1) {
+               proto_tree_add_item(tree, hf_vita_site_num, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+               proto_tree_add_item(tree, hf_vita_site_type, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* Get FAN Policy (response)
+*/
+static void
+cmd1D_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fan_policy, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       if (tvb_captured_length(tvb) > 1) {
+               proto_tree_add_item(tree, hf_vita_fan_coverage, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       }
+}
+
+/* FRU Control Capabilities (response)
+*/
+static void
+cmd1E_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const int * bits_vita_fru_control_caps[] = {
+               &hf_vita_fru_control_cap_cold,
+               &hf_vita_fru_control_cap_warm,
+               &hf_vita_fru_control_cap_grace,
+               &hf_vita_fru_control_cap_diag,
+               &hf_vita_fru_control_cap_pwr,
+               NULL
+       };
+       proto_tree_add_bitmask(tree, tvb, 0, hf_vita_fru_control_caps,
+                       ett_vita_fru_control_caps, bits_vita_fru_control_caps, ENC_LITTLE_ENDIAN);
+}
+
+/* FRU Inventory Device Lock Control (request)
+*/
+static void
+cmd1F_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_lock_operation, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_lock_id, tvb, 2, 2, ENC_LITTLE_ENDIAN);
+}
+
+/* FRU Inventory Device Lock Control (response)
+*/
+static void
+cmd1F_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fru_lock_id, tvb, 0, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_lock_timestamp, tvb, 2, 4, ENC_LITTLE_ENDIAN);
+}
+
+/* FRU Inventory Device Write (request)
+*/
+static void
+cmd20_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_lock_id, tvb, 1, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_write_offset, tvb, 3, 2, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_write_data, tvb, 5,
+                       tvb_captured_length(tvb) - 5, ENC_NA);
+}
+
+/* FRU Inventory Device Write (response)
+*/
+static void
+cmd20_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fru_write_count, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get Chassis Manager IP Address (request)
+*/
+static void
+cmd21_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_chassis_addr_number, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Get Chassis Manager IP Address (response)
+*/
+static void
+cmd21_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_item * item;
+       static const int * bits_vita_chassis_addr_type[] = {
+               &hf_vita_chassis_addr_chmc,
+               &hf_vita_chassis_addr_format,
+               NULL
+       };
+       proto_tree_add_item(tree, hf_vita_chassis_addr_timestamp, tvb, 0, 4, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_chassis_addr_count, tvb, 4, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_site_type, tvb, 5, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_site_num, tvb, 6, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_chassis_max_unavail, tvb, 7, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 8, hf_vita_chassis_addr_type,
+                       ett_vita_chassis_addr_type, bits_vita_chassis_addr_type,
+                       ENC_LITTLE_ENDIAN);
+       item = proto_tree_add_item(tree, hf_vita_chassis_addr, tvb, 8, -1, ENC_NA);
+
+       if (!(tvb_get_guint8(tvb, 8) & 0x7f)) {
+               proto_tree * sub = proto_item_add_subtree(item, ett_vita_chassis_addr);
+               proto_tree_add_item(sub, hf_vita_ipv4_addr, tvb, 9, 4, ENC_BIG_ENDIAN);
+               proto_tree_add_item(sub, hf_vita_rmcp_port, tvb, 13, 2, ENC_BIG_ENDIAN);
+       }
+}
+
+/* Get FRU Persistent Control (response)
+*/
+static void
+cmd41_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_bitmask(tree, tvb, 0, hf_vita_persistent_control_state,
+                       ett_vita_persistent_control_state,
+                       bits_vita_persistent_control_state,
+                       ENC_LITTLE_ENDIAN);
+}
+
+/* Set FRU Persistent Control (request)
+*/
+static void
+cmd42_rq(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fruid, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 1, hf_vita_persistent_control_mask,
+                       ett_vita_persistent_control_state,
+                       bits_vita_persistent_control_state,
+                       ENC_LITTLE_ENDIAN);
+       proto_tree_add_bitmask(tree, tvb, 2, hf_vita_persistent_control_set,
+                       ett_vita_persistent_control_state,
+                       bits_vita_persistent_control_state,
+                       ENC_LITTLE_ENDIAN);
+}
+
+/* FRU Persistent Control capabilities (response)
+*/
+static void
+cmd43_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       static const int * bits_vita_persistent_control_caps[] = {
+               &hf_vita_persistent_control_cap_cold,
+               &hf_vita_persistent_control_cap_warm,
+               NULL
+       };
+       proto_tree_add_bitmask(tree, tvb, 0, hf_vita_persistent_control_caps,
+                       ett_vita_persistent_control_caps,
+                       bits_vita_persistent_control_caps,
+                       ENC_LITTLE_ENDIAN);
+}
+
+/* Get Mandatory Sensor Numbers (response)
+*/
+static void
+cmd44_rs(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
+{
+       proto_tree_add_item(tree, hf_vita_fru_state_sensor_num, tvb, 0, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_health_sensor_num, tvb, 1, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_voltage_sensor_num, tvb, 2, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_fru_temp_sensor_num, tvb, 3, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_payload_test_results_sensor_num, tvb, 4, 1, ENC_LITTLE_ENDIAN);
+       proto_tree_add_item(tree, hf_vita_payload_test_status_sensor_num, tvb, 5, 1, ENC_LITTLE_ENDIAN);
+}
+
+/* Array of VITA 46.11 command descriptors.
+*/
+static ipmi_cmd_t cmd_vita[] = {
+       { 0x00, NULL,           cmd00_rs,       NULL, NULL, "[VITA] Get VSO Capabilities", 0 },
+       { 0x01, cmd01_rq,       cmd01_rs,       NULL, NULL, "[VITA] Get Chassis Address Table Info", 0 },
+       { 0x02, NULL,           cmd02_rs,       NULL, NULL, "[VITA] Get Chassis Identifier", 0 },
+       { 0x03, cmd02_rs,       NULL,           NULL, NULL, "[VITA] Set Chassis Identifier", 0 },
+       { 0x04, cmd04_rq,       NULL,           NULL, NULL, "[VITA] FRU Control", 0 },
+       { 0x05, cmd05_rq,       cmd05_rs,       NULL, NULL, "[VITA] Get FRU LED Properties", 0 },
+       { 0x06, cmd06_rq,       cmd06_rs,       NULL, NULL, "[VITA] Get LED Color Capabilities", 0 },
+       { 0x07, cmd07_rq,       NULL,           NULL, NULL, "[VITA] Set FRU LED State", 0 },
+       { 0x08, cmd06_rq,       cmd08_rs,       NULL, NULL, "[VITA] Get FRU LED State", 0 },
+       { 0x09, cmd09_rq,       NULL,           NULL, NULL, "[VITA] Set IPMB State", 0 },
+       { 0x0A, cmd0A_rq,       NULL,           NULL, NULL, "[VITA] Set FRU State Policy Bits", 0 },
+       { 0x0B, cmd05_rq,       cmd0B_rs,       NULL, NULL, "[VITA] Get FRU State Policy Bits", 0 },
+       { 0x0C, cmd0C_rq,       NULL,           NULL, NULL, "[VITA] Set FRU Activation", 0 },
+       { 0x0D, cmd05_rq,       cmd0D_rs,       NULL, NULL, "[VITA] Get Device Locator Record ID", 0 },
+       { 0x14, cmd05_rq,       cmd14_rs,       NULL, NULL, "[VITA] Get Fan Speed Properties", 0 },
+       { 0x15, cmd15_rq,       NULL,           NULL, NULL, "[VITA] Set Fan Level", 0 },
+       { 0x16, cmd05_rq,       cmd16_rs,       NULL, NULL, "[VITA] Get Fan Level", 0 },
+       { 0x18, cmd18_rq,       cmd18_rs,       NULL, NULL, "[VITA] Get IPMB Link Info", 0 },
+       { 0x1B, NULL,           cmd1B_rs,       NULL, NULL, "[VITA] Get Chassis Manager IPMB Address", 0 },
+       { 0x1C, cmd1C_rq,       NULL,           NULL, NULL, "[VITA] Set Fan Policy", 0 },
+       { 0x1D, cmd1D_rq,       cmd1D_rs,       NULL, NULL, "[VITA] Get Fan Policy", 0 },
+       { 0x1E, cmd05_rq,       cmd1E_rs,       NULL, NULL, "[VITA] FRU Control Capabilities", 0 },
+       { 0x1F, cmd1F_rq,       cmd1F_rs,       cc1F, NULL, "[VITA] FRU Inventory Device Lock Control", 0 },
+       { 0x20, cmd20_rq,       cmd20_rs,       cc20, NULL, "[VITA] FRU Inventory Device Write", 0 },
+       { 0x21, cmd21_rq,       cmd21_rs,       NULL, NULL, "[VITA] Get Chassis Manager IP Address", 0 },
+       { 0x40, cmd01_rq,       cmd01_rs,       NULL, NULL, "[VITA] Get FRU Address Info", 0 },
+       { 0x41, cmd05_rq,       cmd41_rs,       NULL, NULL, "[VITA] Get FRU Persistent Control", 0 },
+       { 0x42, cmd42_rq,       NULL,           NULL, NULL, "[VITA] Set FRU Persistent Control", 0 },
+       { 0x43, cmd05_rq,       cmd43_rs,       NULL, NULL, "[VITA] FRU Persistent Control Capabilities", 0 },
+       { 0x44, cmd05_rq,       cmd44_rs,       NULL, NULL, "[VITA] Get Mandatory Sensor Numbers", 0 }
+};
+
+/* VITA 46.11 command set registrator
+*/
+void
+ipmi_register_vita(gint proto_ipmi)
+{
+       static const guint8 sig_vita[1] = { 3 };
+
+       proto_register_field_array(proto_ipmi, hf_ipmi_vita,
+                       array_length(hf_ipmi_vita));
+       proto_register_subtree_array(ett_ipmi_vita,
+                       array_length(ett_ipmi_vita));
+       ipmi_register_netfn_cmdtab(IPMI_GROUP_REQ, IPMI_OEM_NONE,
+                       sig_vita, 1, "VITA", cmd_vita, array_length(cmd_vita));
+}
+
+
+/*
+ * Editor modelines  -  http://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:
+ */
index 62f71049d3719f276f70df832d9e2de3dd2a2915..54cc8ca17494671b7434f3efa93deeb0a6b5047e 100644 (file)
@@ -24,8 +24,8 @@
 #include "config.h"
 
 #include <string.h>
-#include <time.h>
-#include <math.h>
+
+#include <stdio.h>
 
 #include <epan/packet.h>
 #include <epan/conversation.h>
@@ -54,24 +54,6 @@ struct ipmi_netfn_root {
        guint32 siglen;
 };
 
-#define NSAVED_DATA 2
-
-/* We need more than a conversation. Over the same RMCP session
-   (or IPMB), there may be several addresses/SWIDs. Thus, in a single
-   Wireshark-maintained conversation we might need to find our own... */
-struct ipmi_saved_data {
-       guint32 set_data;
-       guint32 saved_data[NSAVED_DATA];
-};
-
-enum {
-       RQ = 0,
-       RS,
-       RS2,
-
-       MAX_RQRS_FRAMES
-};
-
 enum {
        MSGFMT_NONE = 0,
        MSGFMT_IPMB,
@@ -79,35 +61,84 @@ enum {
        MSGFMT_GUESS
 };
 
-struct ipmi_reqresp {
-       struct ipmi_reqresp *next;
-       struct ipmi_saved_data *data;
-       int (*whichresponse)(struct ipmi_header *hdr, struct ipmi_reqresp *rr);
-       struct {
-               guint32 num;
-               nstime_t time;
-       } frames[MAX_RQRS_FRAMES];
-       guint8 netfn;
-       guint8 cmd;
-};
-
-struct ipmi_keyhead {
-       struct ipmi_reqresp *rr;
-};
-
-struct ipmi_keytree {
-       wmem_tree_t *heads;
-};
-
 struct ipmi_parse_typelen {
        void (*get_len)(guint *, guint *, tvbuff_t *, guint, guint, gboolean);
        void (*parse)(char *, tvbuff_t *, guint, guint);
        const char *desc;
 };
 
-struct ipmi_header *ipmi_current_hdr;
+/* IPMI parsing context */
+typedef struct {
+       ipmi_header_t   hdr;
+       guint                   hdr_len;
+       guint                   flags;
+       guint8                  cks1;
+       guint8                  cks2;
+} ipmi_context_t;
+
+/* Temporary request-response matching data. */
+typedef struct {
+       /* Request header */
+       ipmi_header_t   hdr;
+       /* Frame number where the request resides */
+       guint32                 frame_num;
+       /* Nest level of the request in the frame */
+       guint8                  nest_level;
+} ipmi_request_t;
+
+/* List of request-response matching data */
+typedef wmem_list_t ipmi_request_list_t;
+
+#define NSAVED_DATA 2
+
+/* Per-command data */
+typedef struct {
+       guint32         matched_frame_num;
+       guint32         saved_data[NSAVED_DATA];
+} ipmi_cmd_data_t;
+
+/* Per-frame data */
+typedef struct {
+       ipmi_cmd_data_t *       cmd_data[3];
+       nstime_t                        ts;
+} ipmi_frame_data_t;
+
+/* RB tree of frame data */
+typedef wmem_tree_t ipmi_frame_tree_t;
+
+/* cached dissector data */
+typedef struct {
+       /* tree of cached frame data */
+       ipmi_frame_tree_t *             frame_tree;
+       /* list of cached requests */
+       ipmi_request_list_t *   request_list;
+       /* currently dissected frame number */
+       guint32                                 curr_frame_num;
+       /* currently dissected frame */
+       ipmi_frame_data_t *             curr_frame;
+       /* current nesting level */
+       guint8                                  curr_level;
+       /* subsequent nesting level */
+       guint8                                  next_level;
+       /* top level message channel */
+       guint8                                  curr_channel;
+       /* top level message direction */
+       guint8                                  curr_dir;
+       /* pointer to current command */
+       const ipmi_header_t *   curr_hdr;
+       /* current completion code */
+       guint8                                  curr_ccode;
+} ipmi_packet_data_t;
+
+/* Maximum nest level where it worth caching data */
+#define MAX_NEST_LEVEL 3
+
+static dissector_handle_t data_dissector;
 
 static gint proto_ipmi = -1;
+static gint proto_ipmb = -1;
+static gint proto_kcs = -1;
+static gint proto_tmode = -1;
 
 static gboolean fru_langcode_is_english = TRUE;
 static guint response_after_req = 5000;
@@ -115,15 +146,14 @@ static guint response_before_req = 0;
 static guint message_format = MSGFMT_GUESS;
 static guint selected_oem = IPMI_OEM_NONE;
 
-static gint hf_ipmi_message = -1;
 static gint hf_ipmi_session_handle = -1;
-static gint hf_ipmi_header_broadcast = -1;
 static gint hf_ipmi_header_trg = -1;
 static gint hf_ipmi_header_trg_lun = -1;
 static gint hf_ipmi_header_netfn = -1;
 static gint hf_ipmi_header_crc = -1;
 static gint hf_ipmi_header_src = -1;
 static gint hf_ipmi_header_src_lun = -1;
+static gint hf_ipmi_header_bridged = -1;
 static gint hf_ipmi_header_sequence = -1;
 static gint hf_ipmi_header_command = -1;
 static gint hf_ipmi_header_completion = -1;
@@ -132,7 +162,6 @@ static gint hf_ipmi_data_crc = -1;
 static gint hf_ipmi_response_to = -1;
 static gint hf_ipmi_response_in = -1;
 static gint hf_ipmi_response_time = -1;
-static gint hf_ipmi_bad_checksum = -1;
 
 static gint ett_ipmi = -1;
 static gint ett_header = -1;
@@ -141,375 +170,660 @@ static gint ett_header_byte_4 = -1;
 static gint ett_data = -1;
 static gint ett_typelen = -1;
 
-static guint nest_level;
-static struct ipmi_saved_data *current_saved_data;
 static struct ipmi_netfn_root ipmi_cmd_tab[IPMI_NETFN_MAX];
 
-/* Debug support */
-static void
-debug_printf(const gchar *fmt _U_, ...)
+static ipmi_packet_data_t *
+get_packet_data(packet_info * pinfo)
 {
-#if defined(IPMI_DEBUG)
-       va_list ap;
+       ipmi_packet_data_t * data;
 
-       va_start(ap, fmt);
-       vfprintf(stderr, fmt, ap);
-       va_end(ap);
-#endif
-}
+       /* get conversation data */
+       conversation_t * conv = find_or_create_conversation(pinfo);
 
-/* ----------------------------------------------------------------
-   Support for request-response caching.
----------------------------------------------------------------- */
+       /* get protocol-specific data */
+       data = (ipmi_packet_data_t *)
+                       conversation_get_proto_data(conv, proto_ipmi);
+
+       if (!data) {
+               /* allocate per-packet data */
+               data = wmem_new0(wmem_file_scope(), ipmi_packet_data_t);
+
+               /* allocate request list and frame tree */
+               data->frame_tree = wmem_tree_new(wmem_file_scope());
+               data->request_list = wmem_list_new(wmem_file_scope());
+
+               /* add protocol data */
+               conversation_add_proto_data(conv, proto_ipmi, data);
+       }
+
+       /* check if packet has changed */
+       if (pinfo->fd->num != data->curr_frame_num) {
+               data->curr_level = 0;
+               data->next_level = 0;
+       }
+
+       return data;
+}
 
-/* Key generation; returns the same key for requests and responses */
-static guint32
-makekey(struct ipmi_header *hdr)
+static ipmi_frame_data_t *
+get_frame_data(ipmi_packet_data_t * data, guint32 frame_num)
 {
-       guint32 trg, src, res;
+       ipmi_frame_data_t * frame = (ipmi_frame_data_t *)
+                       wmem_tree_lookup32(data->frame_tree, frame_num);
+
+       if (frame == NULL) {
+               frame = wmem_new0(wmem_file_scope(), ipmi_frame_data_t);
 
-       trg = (hdr->trg_sa << 2) | hdr->trg_lun;
-       src = (hdr->src_sa << 2) | hdr->src_lun;
-       res = trg < src ? (trg << 10) | src : (src << 10) | trg;
-       return (hdr->seq << 20) | res;
+               wmem_tree_insert32(data->frame_tree, frame_num, frame);
+       }
+       return frame;
 }
 
-static struct ipmi_reqresp *
-key_lookup_reqresp(struct ipmi_keyhead *kh, struct ipmi_header *hdr, frame_data *fd)
+static ipmi_request_t *
+get_matched_request(ipmi_packet_data_t * data, const ipmi_header_t * rs_hdr,
+               guint flags)
 {
-       struct ipmi_reqresp *rr, *best_rr = NULL;
-       nstime_t delta;
-       double d, best_d = (double)(2 * response_after_req);
-       guint8 netfn = hdr->netfn & 0x3e;       /* disregard 'response' bit */
-       guint8 is_resp = hdr->netfn & 0x01;
-       int i;
+       wmem_list_frame_t * iter = wmem_list_head(data->request_list);
+       ipmi_header_t rq_hdr;
+
+       /* reset message context */
+       rq_hdr.context = 0;
+
+       /* copy channel */
+       rq_hdr.channel = data->curr_channel;
+
+       /* toggle packet direction */
+       rq_hdr.dir = rs_hdr->dir ^ 1;
+
+       /* swap responder address/lun */
+       rq_hdr.rs_sa = rs_hdr->rq_sa;
+       rq_hdr.rs_lun = rs_hdr->rq_lun;
+
+       /* remove reply flag */
+       rq_hdr.netfn = rs_hdr->netfn & ~1;
+
+       /* swap requester address/lun */
+       rq_hdr.rq_sa = rs_hdr->rs_sa;
+       rq_hdr.rq_lun = rs_hdr->rs_lun;
+
+       /* copy sequence */
+       rq_hdr.rq_seq = rs_hdr->rq_seq;
+
+       /* copy command */
+       rq_hdr.cmd = rs_hdr->cmd;
+
+       /* TODO: copy prefix bytes */
+
+#ifdef DEBUG
+       fprintf(stderr, "%d, %d: rq_hdr : {\n"
+                       "\tchannel=%d\n"
+                       "\tdir=%d\n"
+                       "\trs_sa=%x\n"
+                       "\trs_lun=%d\n"
+                       "\tnetfn=%x\n"
+                       "\trq_sa=%x\n"
+                       "\trq_lun=%d\n"
+                       "\trq_seq=%x\n"
+                       "\tcmd=%x\n}\n",
+                       data->curr_frame_num, data->curr_level,
+                       rq_hdr.channel, rq_hdr.dir, rq_hdr.rs_sa, rq_hdr.rs_lun,
+                       rq_hdr.netfn, rq_hdr.rq_sa, rq_hdr.rq_lun, rq_hdr.rq_seq,
+                       rq_hdr.cmd);
+#endif
 
-       /* Source/target SA/LUN and sequence number are assumed to match; wmem_tree*
-          ensure that. While checking for "being here", we can't rely on flags.visited,
-          as we may have more than one IPMI message in a single frame. */
-       for (rr = kh->rr; rr; rr = rr->next) {
-               if (rr->netfn != netfn || rr->cmd != hdr->cmd) {
-                       continue;
-               }
+       while (iter) {
+               ipmi_request_t * rq = (ipmi_request_t *) wmem_list_frame_data(iter);
 
-               for (i = 0; i < MAX_RQRS_FRAMES; i++) {
-                       /* RQ=0 - 0th element is request frame number; RS/RS2 -
-                          responses are non zero */
-                       if (((!i) ^ is_resp) && rr->frames[i].num == fd->num) {
-                               /* Already been here */
-                               return rr;
-                       }
+               /* check if in Get Message context */
+               if (rs_hdr->context == IPMI_E_GETMSG && !(flags & IPMI_D_TRG_SA)) {
+                       /* diregard rsSA */
+                       rq_hdr.rq_sa = rq->hdr.rq_sa;
                }
 
-               /* Reject responses before requests or more than 5 seconds ahead */
-               if (is_resp) {
-                       nstime_delta(&delta, &fd->abs_ts, &rr->frames[RQ].time);
-               } else {
-                       /* Use RS here, not RS2 - frames[RS] is always filled if we had
-                          at least one response */ /* TBD */
-                       nstime_delta(&delta, &rr->frames[RS].time, &fd->abs_ts);
-               }
-               d = nstime_to_msec(&delta);
-               if (d < -(double)response_before_req || d > (double)response_after_req) {
-                       continue;
+               /* compare command headers */
+               if (!memcmp(&rq_hdr, &rq->hdr, sizeof(rq_hdr))) {
+                       return rq;
                }
 
-               if (fabs(d) < best_d) {
-                       best_rr = rr;
-                       best_d = fabs(d);
-               }
+               /* proceed to next request */
+               iter = wmem_list_frame_next(iter);
        }
 
-       return best_rr;
+       return NULL;
 }
 
 static void
-key_insert_reqresp(struct ipmi_keyhead *kh, struct ipmi_reqresp *rr)
+remove_old_requests(ipmi_packet_data_t * data, const nstime_t * curr_time)
 {
-       /* Insert to head, so that the search would find most recent response */
-       rr->next = kh->rr;
-       kh->rr = rr;
-}
+       wmem_list_frame_t * iter = wmem_list_head(data->request_list);
 
-static inline gboolean
-set_framenums(struct ipmi_header *hdr, struct ipmi_reqresp *rr, frame_data *fd)
-{
-       int which = hdr->netfn & 0x01 ? rr->whichresponse ? rr->whichresponse(hdr, rr) : RS : RQ;
+       while (iter) {
+               ipmi_request_t * rq = (ipmi_request_t *) wmem_list_frame_data(iter);
+               ipmi_frame_data_t * frame = get_frame_data(data, rq->frame_num);
+               nstime_t delta;
 
-       if (rr->frames[which].num && rr->frames[which].num != fd->num) {
-               return FALSE;
+               /* calculate time delta */
+               nstime_delta(&delta, curr_time, &frame->ts);
+
+               if (nstime_to_msec(&delta) > response_after_req) {
+                       wmem_list_frame_t * del = iter;
+
+                       /* proceed to next request */
+                       iter = wmem_list_frame_next(iter);
+
+                       /* free request data */
+                       wmem_free(wmem_file_scope(), rq);
+
+                       /* remove list item */
+                       wmem_list_remove_frame(data->request_list, del);
+               } else {
+                       break;
+               }
        }
-       rr->frames[which].num = fd->num;
-       rr->frames[which].time = fd->abs_ts;
-       return TRUE;
 }
 
-#define        IS_SENDMSG(hdr) (((hdr)->netfn & 0x3e) == IPMI_APP_REQ && (hdr)->cmd == 0x34)
-
-int
-ipmi_sendmsg_whichresponse(struct ipmi_header *hdr, struct ipmi_reqresp *rr)
+static void
+match_request_response(ipmi_packet_data_t * data, const ipmi_header_t * hdr,
+               guint flags)
 {
-       if (!IS_SENDMSG(hdr)) {
-               /* Not a Send Message: just a simple response */
-               return RS;
-       }
+       /* get current frame */
+       ipmi_frame_data_t * rs_frame = data->curr_frame;
 
-       if (hdr->data_len > 0) {
-               /* Trivial case: response with non-null data can only be a
-                  response in AMC.0 style */
-               return RS2;
-       }
-       /* Otherwise, we need to somehow determine 1st and 2nd responses. Note
-          that both them may lack the data - in case that the embedded response
-          returned with error. Thus, employ the following algo:
-          - First, assign to [RS] frame (this also won't conflict with full response
-            received - it could only happen if send message succeeded)
-          - In case we see another data-less response, see that we assign the one
-            with success completion code to [RS] and with non-success code to [RS2].
-
-          We assume that we can't receive 2 responses with non-successful completion
-          (if the outmost Send Message failed, how was the embedded one sent?)
-       */
-       if (!rr->frames[RS].num) {
-               return RS;
-       }
+       /* get current command data */
+       ipmi_cmd_data_t * rs_data = rs_frame->cmd_data[data->curr_level];
+
+       /* check if parse response for the first time */
+       if (!rs_data) {
+               ipmi_request_t * rq;
+
+               /* allocate command data */
+               rs_data = wmem_new0(wmem_file_scope(), ipmi_cmd_data_t);
 
-       /* In case we received "success", move the other response to [RS2] */
-       if (!hdr->ccode) {
-               if (!rr->frames[RS2].num) {
-                       rr->frames[RS2] = rr->frames[RS];
+               /* search for matching request */
+               rq = get_matched_request(data, hdr, flags);
+
+               /* check if matching request is found */
+               if (rq) {
+                       /* get request frame data */
+                       ipmi_frame_data_t * rq_frame =
+                                       get_frame_data(data, rq->frame_num);
+
+                       /* get command data */
+                       ipmi_cmd_data_t * rq_data = rq_frame->cmd_data[rq->nest_level];
+
+                       /* save matched frame numbers */
+                       rq_data->matched_frame_num = data->curr_frame_num;
+                       rs_data->matched_frame_num = rq->frame_num;
+
+                       /* copy saved command data information */
+                       rs_data->saved_data[0] = rq_data->saved_data[0];
+                       rs_data->saved_data[1] = rq_data->saved_data[1];
+
+                       /* remove request from the list */
+                       wmem_list_remove(data->request_list, rq);
+
+                       /* delete request data */
+                       wmem_free(wmem_file_scope(), rq);
                }
-               return RS;
-       }
 
-       /* [RS] occupied, non-successful */
-       return RS2;
+               /* save command data pointer in frame */
+               rs_frame->cmd_data[data->curr_level] = rs_data;
+       }
 }
 
-int
-ipmi_sendmsg_otheridx(struct ipmi_header *hdr)
+static void
+add_request(ipmi_packet_data_t * data, const ipmi_header_t * hdr)
 {
-       return IS_SENDMSG(hdr) ? nest_level : RS;
+       /* get current frame */
+       ipmi_frame_data_t * rq_frame = data->curr_frame;
+
+       /* get current command data */
+       ipmi_cmd_data_t * rq_data = rq_frame->cmd_data[data->curr_level];
+
+       /* check if parse response for the first time */
+       if (!rq_data) {
+               ipmi_request_t * rq;
+
+               /* allocate command data */
+               rq_data = wmem_new0(wmem_file_scope(), ipmi_cmd_data_t);
+
+               /* set command data pointer */
+               rq_frame->cmd_data[data->curr_level] = rq_data;
+
+               /* allocate request data */
+               rq = wmem_new0(wmem_file_scope(), ipmi_request_t);
+
+               /* copy request header */
+               memcpy(&rq->hdr, hdr, sizeof(rq->hdr));
+
+               /* override context, channel and direction */
+               rq->hdr.context = 0;
+               rq->hdr.channel = data->curr_channel;
+               rq->hdr.dir = data->curr_dir;
+
+               /* set request frame number */
+               rq->frame_num = data->curr_frame_num;
+
+               /* set command nest level */
+               rq->nest_level = data->curr_level;
+
+               /* append request to list */
+               wmem_list_append(data->request_list, rq);
+
+#ifdef DEBUG
+       fprintf(stderr, "%d, %d: hdr : {\n"
+                       "\tchannel=%d\n"
+                       "\tdir=%d\n"
+                       "\trs_sa=%x\n"
+                       "\trs_lun=%d\n"
+                       "\tnetfn=%x\n"
+                       "\trq_sa=%x\n"
+                       "\trq_lun=%d\n"
+                       "\trq_seq=%x\n"
+                       "\tcmd=%x\n}\n",
+                       data->curr_frame_num, data->curr_level,
+                       rq->hdr.channel, rq->hdr.dir, rq->hdr.rs_sa, rq->hdr.rs_lun,
+                       rq->hdr.netfn, rq->hdr.rq_sa, rq->hdr.rq_lun, rq->hdr.rq_seq,
+                       rq->hdr.cmd);
+#endif
+       }
 }
 
-struct ipmi_header *
-ipmi_sendmsg_getheaders(struct ipmi_header *base, void *arg, guint i)
+static void
+add_command_info(packet_info *pinfo, ipmi_cmd_t * cmd,
+               gboolean resp, guint8 cc_val, const char * cc_str, gboolean broadcast)
 {
-       static struct ipmi_header hdr;
-       struct ipmi_header *wrapper = (struct ipmi_header *)arg;
-
-       /* The problem stems from the fact that the original IPMI
-          specification (before errata came) did not specify the response
-          to Send Message (and even the fact that there are 2 responses -
-          to Send Message and to embedded command). Even then, there is
-          one vagueness remaining - whether the response should use
-          the sequence number from the wrapper or from the embedded message.
-
-          Thus, there are 3 types of responses to Send Message
-
-          * AMC.0-style: the response is embedded in a normal Send Message
-            response. Easiest case: such responses will be correctly detected
-            with the default code in ipmi_do_dissect.
-
-          * IPMI-style, with both variants of sequence numbers. Note that
-            most tools dealing with Send Message (e.g. ipmitool) circumvent
-            this vagueness by using the same sequence number in both wrapper
-            and embedded messages. If we detect such "smart" messages, we
-            provide only one extra header. For correctness, we have to provide
-            for both variants, however.
-       */
-
-       if (i >= 2 || (i == 1 && wrapper->seq == base->seq)) {
-               return NULL;
+       if (resp) {
+               col_add_fstr(pinfo->cinfo, COL_INFO, "Rsp, %s, %s (%02xh)",
+                               cmd->desc, cc_str, cc_val);
+       } else {
+               col_add_fstr(pinfo->cinfo, COL_INFO, "Req, %s%s",
+                               broadcast ? "Broadcast " : "", cmd->desc);
        }
-
-       /* Construct hybrid header */
-       hdr.trg_sa = wrapper->trg_sa;
-       hdr.trg_lun = wrapper->trg_lun;
-       hdr.src_sa = wrapper->src_sa;
-       hdr.src_lun = wrapper->src_lun;
-       hdr.netfn = base->netfn;
-       hdr.cmd = base->cmd;
-       hdr.seq = i ? base->seq : wrapper->seq;
-       hdr.ccode = base->ccode;
-       hdr.data_len = base->data_len;
-       return &hdr;
 }
 
-static void
-maybe_insert_reqresp(packet_info *pinfo, ipmi_dissect_format_t *dfmt, struct ipmi_header *hdr)
+int dissect_ipmi_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+               gint hf_parent_item, gint ett_tree, const ipmi_context_t * ctx)
 {
-       conversation_t *cnv;
-       struct ipmi_keytree *kt;
-       struct ipmi_keyhead *kh;
-       struct ipmi_reqresp *rr;
-       guint32 key, i;
-
-       cnv = find_or_create_conversation(pinfo);
-
-       kt = (struct ipmi_keytree *)conversation_get_proto_data(cnv, proto_ipmi);
-       if (!kt) {
-               kt = wmem_new(wmem_file_scope(), struct ipmi_keytree);
-               kt->heads = wmem_tree_new(wmem_file_scope());
-               conversation_add_proto_data(cnv, proto_ipmi, kt);
+       ipmi_packet_data_t * data;
+       ipmi_netfn_t * cmd_list;
+       ipmi_cmd_t * cmd;
+       proto_item * ti;
+       proto_tree * cmd_tree = NULL, * tmp_tree;
+       guint8 prev_level, cc_val;
+       guint offset, siglen, is_resp;
+       const char * cc_str, * netfn_str;
+
+       /* get packet data */
+       data = get_packet_data(pinfo);
+       if (!data) {
+               return 0;
+       }
+
+       /* get prefix length */
+       siglen = ipmi_getsiglen(ctx->hdr.netfn);
+
+       /* get response flag */
+       is_resp = ctx->hdr.netfn & 1;
+
+       /* check message length */
+       if (tvb_captured_length(tvb) < ctx->hdr_len + siglen + is_resp
+                       + !(ctx->flags & IPMI_D_NO_CKS)) {
+               /* don bother with anything */
+               return call_dissector(data_dissector, tvb, pinfo, tree);
        }
 
-       debug_printf("--> maybe_insert_reqresp( %d )\n", pinfo->fd->num);
-       i = 0;
-       do {
-               debug_printf("Checking [ (%02x,%1x <-> %02x,%1x : %02x) %02x %02x ]\n",
-                               hdr->trg_sa, hdr->trg_lun, hdr->src_sa, hdr->src_lun, hdr->seq,
-                               hdr->netfn, hdr->cmd);
-               key = makekey(hdr);
-               kh = (struct ipmi_keyhead *)wmem_tree_lookup32(kt->heads, key);
-               if (!kh) {
-                       kh = wmem_new0(wmem_file_scope(), struct ipmi_keyhead);
-                       wmem_tree_insert32(kt->heads, key, kh);
+       /* save nest level */
+       prev_level = data->curr_level;
+
+       /* assign next nest level */
+       data->curr_level = data->next_level;
+
+       /* increment next nest level */
+       data->next_level++;
+
+       /* check for the first invocation */
+       if (!data->curr_level) {
+               /* get current frame data */
+               data->curr_frame = get_frame_data(data, pinfo->fd->num);
+               data->curr_frame_num = pinfo->fd->num;
+
+               /* copy frame timestamp */
+               memcpy(&data->curr_frame->ts, &pinfo->fd->abs_ts, sizeof(nstime_t));
+
+               /* cache channel and direction */
+               data->curr_channel = ctx->hdr.channel;
+               data->curr_dir = ctx->hdr.dir;
+
+               /* remove requests which are too old */
+               remove_old_requests(data, &pinfo->fd->abs_ts);
+       }
+
+       if (data->curr_level < MAX_NEST_LEVEL) {
+               if (ctx->hdr.netfn & 1) {
+                       /* perform request/response matching */
+                       match_request_response(data, &ctx->hdr, ctx->flags);
+               } else {
+                       /* add request to the list for later matching */
+                       add_request(data, &ctx->hdr);
                }
-               if ((rr = key_lookup_reqresp(kh, hdr, pinfo->fd)) != NULL) {
-                       /* Already recorded - set frame number and be done. Look no
-                          further - even if there are several responses, we have
-                          found the right one. */
-                       debug_printf("Found existing [ <%d,%d,%d> (%02x,%1x <-> %02x,%1x : %02x) %02x %02x ]\n",
-                                       rr->frames[0].num, rr->frames[1].num, rr->frames[2].num,
-                                       hdr->trg_sa, hdr->trg_lun, hdr->src_sa, hdr->src_lun, hdr->seq,
-                                       rr->netfn, rr->cmd);
-                       if (!rr->whichresponse) {
-                               rr->whichresponse = dfmt->whichresponse;
+       }
+
+       /* get command list by network function code */
+       cmd_list = ipmi_getnetfn(ctx->hdr.netfn,
+                       tvb_get_ptr(tvb, ctx->hdr_len + is_resp, siglen));
+
+       /* get command descriptor */
+       cmd = ipmi_getcmd(cmd_list, ctx->hdr.cmd);
+
+       /* check if response */
+       if (is_resp) {
+               /* get completion code */
+               cc_val = tvb_get_guint8(tvb, ctx->hdr_len);
+
+               /* get completion code desc */
+               cc_str = ipmi_get_completion_code(cc_val, cmd);
+       } else {
+               cc_val = 0;
+               cc_str = NULL;
+       }
+
+       /* check if not inside a message */
+       if (!data->curr_level) {
+               /* add packet info */
+               add_command_info(pinfo, cmd, is_resp, cc_val, cc_str,
+                               ctx->flags & IPMI_D_BROADCAST ? TRUE : FALSE);
+       }
+
+       if (tree) {
+               /* add parent node */
+               if (!data->curr_level) {
+                       ti = proto_tree_add_item(tree, hf_parent_item, tvb, 0, -1, ENC_NA);
+               } else {
+                       char str[ITEM_LABEL_LENGTH];
+
+                       if (is_resp) {
+                               g_snprintf(str, ITEM_LABEL_LENGTH, "Rsp, %s, %s",
+                                               cmd->desc, cc_str);
+                       } else {
+                               g_snprintf(str, ITEM_LABEL_LENGTH, "Req, %s", cmd->desc);
                        }
-                       if (set_framenums(hdr, rr, pinfo->fd)) {
-                               debug_printf("Set frames     [ <%d,%d,%d> (%02x,%1x <-> %02x,%1x : %02x) %02x %02x ]\n",
-                                               rr->frames[0].num, rr->frames[1].num, rr->frames[2].num,
-                                               hdr->trg_sa, hdr->trg_lun, hdr->src_sa, hdr->src_lun, hdr->seq,
-                                               rr->netfn, rr->cmd);
-                               current_saved_data = rr->data;
-                               return;
+
+                       ti = proto_tree_add_string(tree, hf_parent_item, tvb, 0, -1, str);
+               }
+
+               /* add message sub-tree */
+               cmd_tree = proto_item_add_subtree(ti, ett_tree);
+
+               if (data->curr_level < MAX_NEST_LEVEL) {
+                       /* check if response */
+                       if (ctx->hdr.netfn & 1) {
+                               /* get current command data */
+                               ipmi_cmd_data_t * rs_data =
+                                               data->curr_frame->cmd_data[data->curr_level];
+
+                               if (rs_data->matched_frame_num) {
+                                       nstime_t ns;
+
+                                       /* add "Request to:" field */
+                                       ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_to,
+                                                       tvb, 0, 0, rs_data->matched_frame_num);
+
+                                       /* mark field as a generated one */
+                                       PROTO_ITEM_SET_GENERATED(ti);
+
+                                       /* calculate delta time */
+                                       nstime_delta(&ns, &pinfo->fd->abs_ts,
+                                                       &get_frame_data(data,
+                                                                       rs_data->matched_frame_num)->ts);
+
+                                       /* add "Response time" field */
+                                       ti = proto_tree_add_time(cmd_tree, hf_ipmi_response_time,
+                                                       tvb, 0, 0, &ns);
+
+                                       /* mark field as a generated one */
+                                       PROTO_ITEM_SET_GENERATED(ti);
+                                       }
+                       } else {
+                               /* get current command data */
+                               ipmi_cmd_data_t * rq_data =
+                                               data->curr_frame->cmd_data[data->curr_level];
+
+                               if (rq_data->matched_frame_num) {
+                                       /* add "Response in:" field  */
+                                       ti = proto_tree_add_uint(cmd_tree, hf_ipmi_response_in,
+                                                       tvb, 0, 0, rq_data->matched_frame_num);
+
+                                       /* mark field as a generated one */
+                                       PROTO_ITEM_SET_GENERATED(ti);
+                               }
                        }
+               }
+
+               /* set starting offset */
+               offset = 0;
 
-                       /* Found, but already occupied. Fall through to allocating the structures */
-                       current_saved_data = NULL;
+               /* check if message is broadcast */
+               if (ctx->flags & IPMI_D_BROADCAST) {
+                       /* skip first byte */
+                       offset++;
                }
-               /* Not found; allocate new structures */
-               if (!current_saved_data) {
-                       /* One 'ipmi_saved_data' for all 'ipmi_req_resp' allocated */
-                       current_saved_data = wmem_new0(wmem_file_scope(), struct ipmi_saved_data);
+
+               /* check if session handle is specified */
+               if (ctx->flags & IPMI_D_SESSION_HANDLE) {
+                       /* add session handle field */
+                       proto_tree_add_item(cmd_tree, hf_ipmi_session_handle,
+                                       tvb, offset++, 1, ENC_LITTLE_ENDIAN);
                }
-               rr = wmem_new0(wmem_file_scope(), struct ipmi_reqresp);
-               rr->whichresponse = dfmt->whichresponse;
-               rr->netfn = hdr->netfn & 0x3e;
-               rr->cmd = hdr->cmd;
-               rr->data = current_saved_data;
-               set_framenums(hdr, rr, pinfo->fd);
-               key_insert_reqresp(kh, rr);
-               debug_printf("Inserted [ <%d,%d,%d> (%02x,%1x <-> %02x,%1x : %02x) %02x %02x ]\n",
-                               rr->frames[0].num, rr->frames[1].num, rr->frames[2].num,
-                               hdr->trg_sa, hdr->trg_lun, hdr->src_sa, hdr->src_lun, hdr->seq,
-                               rr->netfn, rr->cmd);
-
-               /* Do we have other headers to insert? */
-               hdr = dfmt->getmoreheaders ? dfmt->getmoreheaders(hdr, dfmt->arg, i++) : NULL;
-       } while (hdr);
-}
 
-static void
-add_reqresp_info(ipmi_dissect_format_t *dfmt, struct ipmi_header *hdr, proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo)
-{
-       conversation_t *cnv;
-       struct ipmi_keytree *kt;
-       struct ipmi_keyhead *kh;
-       struct ipmi_reqresp *rr = NULL;
-       guint32 key, i, other_idx;
-       proto_item *ti;
-       nstime_t ns;
+               /* check if responder address is specified */
+               if (ctx->flags & IPMI_D_TRG_SA) {
+                       /* add response address field */
+                       proto_tree_add_item(cmd_tree, hf_ipmi_header_trg, tvb,
+                                       offset++, 1, ENC_LITTLE_ENDIAN);
+               }
 
-       debug_printf("--> add_reqresp_info( %d )\n", pinfo->fd->num);
+               /* get NetFn string */
+               netfn_str = ipmi_getnetfnname(ctx->hdr.netfn, cmd_list);
 
-       /* [0] is request; [1..MAX_RS_LEVEL] are responses */
-       other_idx = (hdr->netfn & 0x01) ? RQ : dfmt->otheridx ? dfmt->otheridx(hdr) : RS;
+               /* Network function + target LUN */
+               ti = proto_tree_add_text(cmd_tree, tvb, offset, 1,
+                               "Target LUN: 0x%02x, NetFN: %s %s (0x%02x)",
+                               ctx->hdr.rs_lun, netfn_str,
+                               is_resp ? "Response" : "Request", ctx->hdr.netfn);
+
+               /* make a sub-tree */
+               tmp_tree = proto_item_add_subtree(ti, ett_header_byte_1);
+
+               /* add Net Fn */
+               proto_tree_add_uint_format(tmp_tree, hf_ipmi_header_netfn, tvb,
+                               offset, 1, ctx->hdr.netfn << 2,
+                               "NetFn: %s %s (0x%02x)", netfn_str,
+                               is_resp ? "Response" : "Request", ctx->hdr.netfn);
+
+               proto_tree_add_item(tmp_tree, hf_ipmi_header_trg_lun, tvb,
+                               offset++, 1, ENC_LITTLE_ENDIAN);
+
+               /* check if cks1 is specified */
+               if (!(ctx->flags & IPMI_D_NO_CKS)) {
+                       guint8 cks = tvb_get_guint8(tvb, offset);
+
+                       /* Header checksum */
+                       if (ctx->cks1) {
+                               guint8 correct = cks - ctx->cks1;
+
+                               proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc,
+                                               tvb, offset++, 1, cks,
+                                               "0x%02x (incorrect, expected 0x%02x)", cks, correct);
+                       } else {
+                               proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_crc,
+                                               tvb, offset++, 1, cks,
+                                               "0x%02x (correct)", cks);
+                       }
+               }
 
-       if (other_idx >= MAX_RQRS_FRAMES) {
-               /* No chance; we don't look that deep into nested Send Message.
-                  Note that we'll use the other_idx value to distinguish
-                  request from response. */
-               goto fallback;
-       }
+               /* check if request address is specified */
+               if (!(ctx->flags & IPMI_D_NO_RQ_SA)) {
+                       /* add request address field */
+                       proto_tree_add_item(cmd_tree, hf_ipmi_header_src, tvb,
+                                       offset++, 1, ENC_LITTLE_ENDIAN);
+               }
 
-       /* Here, we don't try to create any object - everything is assumed
-          to be created in maybe_insert_reqresp() */
-       if ((cnv = find_conversation(pinfo->fd->num, &pinfo->src,
-                       &pinfo->dst, pinfo->ptype,
-                       pinfo->srcport, pinfo->destport, 0)) == NULL) {
-               goto fallback;
-       }
-       if ((kt = (struct ipmi_keytree *)conversation_get_proto_data(cnv, proto_ipmi)) == NULL) {
-               goto fallback;
+               /* check if request sequence is specified */
+               if (!(ctx->flags & IPMI_D_NO_SEQ)) {
+                       /* Sequence number + source LUN */
+                       ti = proto_tree_add_text(cmd_tree, tvb, offset, 1,
+                                       "%s: 0x%02x, SeqNo: 0x%02x",
+                                       (ctx->flags & IPMI_D_TMODE) ? "Bridged" : "Source LUN",
+                                                       ctx->hdr.rq_lun, ctx->hdr.rq_seq);
+
+                       /* create byte 4 sub-tree */
+                       tmp_tree = proto_item_add_subtree(ti, ett_header_byte_4);
+
+                       if (ctx->flags & IPMI_D_TMODE) {
+                               proto_tree_add_item(tmp_tree, hf_ipmi_header_bridged,
+                                               tvb, offset, 1, ENC_LITTLE_ENDIAN);
+                       } else {
+                               proto_tree_add_item(tmp_tree, hf_ipmi_header_src_lun,
+                                               tvb, offset, 1, ENC_LITTLE_ENDIAN);
+                       }
+
+                       /* print seq no */
+                       proto_tree_add_item(tmp_tree, hf_ipmi_header_sequence, tvb,
+                                       offset++, 1, ENC_LITTLE_ENDIAN);
+               }
+
+               /* command code */
+               proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_header_command,
+                               tvb, offset++, 1, ctx->hdr.cmd, "%s (0x%02x)",
+                               cmd->desc, ctx->hdr.cmd);
+
+               if (is_resp) {
+                       /* completion code */
+                       proto_tree_add_uint_format_value(cmd_tree,
+                                       hf_ipmi_header_completion, tvb, offset++, 1,
+                                       cc_val, "%s (0x%02x)", cc_str, cc_val);
+               }
+
+               if (siglen) {
+                       /* command prefix (if present) */
+                       ti = proto_tree_add_item(cmd_tree, hf_ipmi_header_sig, tvb,
+                                       offset, siglen, ENC_NA);
+                       proto_item_append_text(ti, " (%s)", netfn_str);
+               }
        }
 
-       i = 0;
-       while (1) {
-               debug_printf("Looking for [ (%02x,%1x <-> %02x,%1x : %02x) %02x %02x ]\n",
-                               hdr->trg_sa, hdr->trg_lun, hdr->src_sa, hdr->src_lun, hdr->seq,
-                               hdr->netfn, hdr->cmd);
-               key = makekey(hdr);
-               if ((kh = (struct ipmi_keyhead *)wmem_tree_lookup32(kt->heads, key)) != NULL &&
-                               (rr = key_lookup_reqresp(kh, hdr, pinfo->fd)) != NULL) {
-                       debug_printf("Found [ <%d,%d,%d> (%02x,%1x <-> %02x,%1x : %02x) %02x %02x ]\n",
-                                       rr->frames[0].num, rr->frames[1].num, rr->frames[2].num,
-                                       hdr->trg_sa, hdr->trg_lun, hdr->src_sa, hdr->src_lun, hdr->seq,
-                                       rr->netfn, rr->cmd);
-                       if (rr->frames[other_idx].num) {
-                               break;
+       if (tree || (cmd->flags & CMD_CALLRQ)) {
+               /* calculate message data length */
+               guint data_len = tvb_captured_length(tvb)
+                               - ctx->hdr_len
+                               - siglen
+                               - (is_resp ? 1 : 0)
+                               - !(ctx->flags & IPMI_D_NO_CKS);
+
+               /* create data subset */
+               tvbuff_t * data_tvb = tvb_new_subset_length(tvb,
+                               ctx->hdr_len + siglen + (is_resp ? 1 : 0), data_len);
+
+               /* Select sub-handler */
+               ipmi_cmd_handler_t hnd = is_resp ? cmd->parse_resp : cmd->parse_req;
+
+               if (hnd && tvb_captured_length(data_tvb)) {
+                       if (tree) {
+                               /* create data field */
+                               ti = proto_tree_add_text(cmd_tree, data_tvb, 0, -1, "Data");
+
+                               /* create data sub-tree */
+                               tmp_tree = proto_item_add_subtree(ti, ett_data);
+                       } else {
+                               tmp_tree = NULL;
                        }
-               }
 
-               /* Do we have other headers to check? */
-               hdr = dfmt->getmoreheaders ? dfmt->getmoreheaders(hdr, dfmt->arg, i++) : NULL;
-               if (!hdr) {
-                       goto fallback;
+                       /* save current command */
+                       data->curr_hdr = &ctx->hdr;
+
+                       /* save current completion code */
+                       data->curr_ccode = cc_val;
+
+                       /* call command parser */
+                       hnd(data_tvb, pinfo, tmp_tree);
                }
        }
 
-       if (hdr->netfn & 0x01) {
-               /* Response */
-               ti = proto_tree_add_uint(tree, hf_ipmi_response_to,
-                               tvb, 0, 0, rr->frames[RQ].num);
-               PROTO_ITEM_SET_GENERATED(ti);
-               nstime_delta(&ns, &pinfo->fd->abs_ts, &rr->frames[RQ].time);
-               ti = proto_tree_add_time(tree, hf_ipmi_response_time,
-                               tvb, 0, 0, &ns);
-               PROTO_ITEM_SET_GENERATED(ti);
-       } else {
-               /* Request */
-               ti = proto_tree_add_uint(tree, hf_ipmi_response_in,
-                               tvb, 0, 0, rr->frames[other_idx].num);
-               PROTO_ITEM_SET_GENERATED(ti);
+       /* check if cks2 is specified */
+       if (tree && !(ctx->flags & IPMI_D_NO_CKS)) {
+               guint8 cks;
+
+               /* get cks2 offset */
+               offset = tvb_captured_length(tvb) - 1;
+
+               /* get cks2 */
+               cks = tvb_get_guint8(tvb, offset);
+
+               /* Header checksum */
+               if (ctx->cks2) {
+                       guint8 correct = cks - ctx->cks2;
+
+                       proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc,
+                                       tvb, offset, 1, cks,
+                                       "0x%02x (incorrect, expected 0x%02x)", cks, correct);
+               } else {
+                       proto_tree_add_uint_format_value(cmd_tree, hf_ipmi_data_crc,
+                                       tvb, offset, 1, cks,
+                                       "0x%02x (correct)", cks);
+               }
        }
-       return;
 
-fallback:
-       ti = proto_tree_add_text(tree, tvb, 0, 0, "No corresponding %s",
-                       other_idx ? "response" : "request");
-       PROTO_ITEM_SET_GENERATED(ti);
+       /* decrement next nest level */
+       data->next_level = data->curr_level;
+
+       /* restore previous nest level */
+       data->curr_level = prev_level;
+
+       return tvb_captured_length(tvb);
 }
 
-/* Save data in request, retrieve in response */
-void
-ipmi_setsaveddata(guint idx, guint32 val)
+/* Get currently parsed message header */
+const ipmi_header_t * ipmi_get_hdr(packet_info * pinfo)
 {
-       DISSECTOR_ASSERT(idx < NSAVED_DATA);
-       current_saved_data->saved_data[idx] = val;
-       current_saved_data->set_data |= (1 << idx);
+       ipmi_packet_data_t * data = get_packet_data(pinfo);
+       return data->curr_hdr;
 }
 
-gboolean
-ipmi_getsaveddata(guint idx, guint32 *pval)
+/* Get completion code for currently parsed message */
+guint8 ipmi_get_ccode(packet_info * pinfo)
 {
-       DISSECTOR_ASSERT(idx < NSAVED_DATA);
-       if (current_saved_data->set_data & (1 << idx)) {
-               *pval = current_saved_data->saved_data[idx];
-               return TRUE;
+       ipmi_packet_data_t * data = get_packet_data(pinfo);
+       return data->curr_ccode;
+}
+
+/* Save request data for later use in response */
+void ipmi_set_data(packet_info *pinfo, guint idx, guint32 value)
+{
+       ipmi_packet_data_t * data = get_packet_data(pinfo);
+
+       /* check bounds */
+       if (data->curr_level >= MAX_NEST_LEVEL || idx >= NSAVED_DATA ) {
+               return;
+       }
+
+       /* save data */
+       data->curr_frame->cmd_data[data->curr_level]->saved_data[idx] = value;
+}
+
+/* Get saved request data */
+gboolean ipmi_get_data(packet_info *pinfo, guint idx, guint32 * value)
+{
+       ipmi_packet_data_t * data = get_packet_data(pinfo);
+
+       /* check bounds */
+       if (data->curr_level >= MAX_NEST_LEVEL || idx >= NSAVED_DATA ) {
+               return FALSE;
        }
-       return FALSE;
+
+       /* get data */
+       *value = data->curr_frame->cmd_data[data->curr_level]->saved_data[idx];
+       return TRUE;
 }
 
 /* ----------------------------------------------------------------
@@ -814,15 +1128,11 @@ ipmi_register_netfn_cmdtab(guint32 netfn, guint oem_selector,
 
        netfn >>= 1;    /* Requests and responses grouped together */
        if (netfn >= IPMI_NETFN_MAX) {
-               g_warning("NetFn too large: %x", netfn * 2);
                return;
        }
 
        inr = &ipmi_cmd_tab[netfn];
        if (inr->siglen != siglen) {
-               /* All handlers per netFn should have the same signature length */
-               g_warning("NetFn %d: different signature lengths: %d vs %d",
-                               netfn * 2, inr->siglen, siglen);
                return;
        }
 
@@ -1047,331 +1357,388 @@ ipmi_get_completion_code(guint8 completion, ipmi_cmd_t *cmd)
        return val_to_str_const(completion, std_completion_codes, "Unknown");
 }
 
-/* Guess the parsing flags for a message
- */
-int
-ipmi_guess_dissect_flags(tvbuff_t *tvb)
+static int
+dissect_tmode(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
-       int i;
-       guint8 buf[6];
-
-       switch (message_format) {
-       case MSGFMT_NONE:
-               return IPMI_D_NONE;
-       case MSGFMT_IPMB:
-               return IPMI_D_TRG_SA;
-       case MSGFMT_LAN:
-               return IPMI_D_TRG_SA|IPMI_D_SESSION_HANDLE;
+       ipmi_dissect_arg_t * arg = (ipmi_dissect_arg_t *) data;
+       ipmi_context_t ctx;
+       guint tvb_len = tvb_captured_length(tvb);
+       guint8 tmp;
+
+       /* TMode message is at least 3 bytes length */
+       if (tvb_len < 3) {
+               return 0;
        }
 
-       /* Try to guess the format */
-       DISSECTOR_ASSERT(message_format == MSGFMT_GUESS);
+       memset(&ctx, 0, sizeof(ctx));
 
-       /* 6 is shortest message - Get Message with empty data */
-       if (tvb_length(tvb) < 6) {
-               return IPMI_D_NONE;
-       }
+       /* get Net Fn/RS LUN field */
+       tmp = tvb_get_guint8(tvb, 0);
 
-       /* Fetch the beginning */
-       for (i = 0; i < 6; i++) {
-               buf[i] = tvb_get_guint8(tvb, i);
-       }
+       /* set Net Fn */
+       ctx.hdr.netfn = tmp >> 2;
 
-       if ((buf[0] + buf[1] + buf[2]) % 0x100 == 0) {
-               /* Looks like IPMB: first 3 bytes are zero module 256 */
-               return IPMI_D_TRG_SA;
-       }
+       /*
+        * NOTE: request/response matching code swaps RQ LUN with RS LUN
+        * fields in IPMB-like manner in order to find corresponding request
+        * so, we set both RS LUN and RQ LUN here for correct
+        * request/response matching
+        */
+       ctx.hdr.rq_lun = tmp & 3;
+       ctx.hdr.rs_lun = tmp & 3;
+
+       /* get RQ Seq field */
+       ctx.hdr.rq_seq = tvb_get_guint8(tvb, 1) >> 2;
 
-       if ((buf[1] + buf[2] + buf[3]) % 0x100 == 0) {
-               /* Looks like LAN: like IPMB, prepended with extra byte (session handle) */
-               return IPMI_D_TRG_SA|IPMI_D_SESSION_HANDLE;
+       /*
+        * NOTE: bridge field is ignored in request/response matching
+        */
+
+       /* get command code */
+       ctx.hdr.cmd = tvb_get_guint8(tvb, 2);
+
+       /* set dissect flags */
+       ctx.flags = IPMI_D_TMODE|IPMI_D_NO_CKS|IPMI_D_NO_RQ_SA;
+
+       /* set header length */
+       ctx.hdr_len = 3;
+
+       /* copy channel number and direction */
+       ctx.hdr.context = arg ? arg->context : IPMI_E_NONE;
+       ctx.hdr.channel = arg ? arg->channel : 0;
+       ctx.hdr.dir = arg ? arg->flags >> 7 : ctx.hdr.netfn & 1;
+
+       if (ctx.hdr.context == IPMI_E_NONE) {
+               /* set source column */
+               col_set_str(pinfo->cinfo, COL_DEF_SRC,
+                               ctx.hdr.dir ? "Console" : "BMC");
+
+               /* set destination column */
+               col_set_str(pinfo->cinfo, COL_DEF_DST,
+                               ctx.hdr.dir ? "BMC" : "Console");
        }
 
-       /* Can't guess */
-       return IPMI_D_NONE;
+       /* dissect IPMI command */
+       return dissect_ipmi_cmd(tvb, pinfo, tree, proto_tmode, ett_ipmi, &ctx);
 }
 
-/* Print out IPMB packet.
- */
-void
-ipmi_do_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ipmi_tree, ipmi_dissect_format_t *dfmt)
+static int
+dissect_kcs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
-       proto_tree *hdr_tree, *data_tree, *s_tree;
-       proto_item *ti;
-       tvbuff_t *data_tvb;
-       ipmi_netfn_t *in = NULL;
-       ipmi_cmd_t *ic = NULL;
-       ipmi_cmd_handler_t hnd = NULL;
-       struct ipmi_saved_data *saved_saved_data;
-       struct ipmi_header hdr, *saved_hdr;
-       guint8 hdr_crc, hdr_exp_crc, data_crc, data_exp_crc;
-       guint8 is_resp, is_broadcast = 0, tmp;
-       guint i, len, siglen, hdrlen, offs, data_chk_offs;
-       const char *bcast, *ndesc, *cdesc, *ccdesc;
-
-       if (dfmt->flags & IPMI_D_NONE) {
-               /* No parsing requested */
-               g_snprintf(dfmt->info, ITEM_LABEL_LENGTH, "Unknown message (not parsed)");
-               proto_tree_add_item(ipmi_tree, hf_ipmi_message, tvb, 0, tvb_length(tvb), ENC_NA);
-               return;
+       ipmi_dissect_arg_t * arg = (ipmi_dissect_arg_t *) data;
+       ipmi_context_t ctx;
+       guint tvb_len = tvb_captured_length(tvb);
+       guint8 tmp;
+
+       /* KCS message is at least 2 bytes length */
+       if (tvb_len < 2) {
+               return 0;
        }
 
-       nest_level++;
-       offs = 0;
-       memset(&hdr, 0, sizeof(hdr));
-       debug_printf("--> do_dissect(%d, nl %u, tree %s null)\n",
-                       pinfo->fd->num, nest_level, ipmi_tree ? "IS NOT" : "IS");
+       memset(&ctx, 0, sizeof(ctx));
+
+       /* get Net Fn/RS LUN field */
+       tmp = tvb_get_guint8(tvb, 0);
+
+       /* set Net Fn */
+       ctx.hdr.netfn = tmp >> 2;
+
+       /*
+        * NOTE: request/response matching code swaps RQ LUN with RS LUN
+        * fields in IPMB-like manner in order to find corresponding request
+        * so, we set both RS LUN and RQ LUN here for correct
+        * request/response matching
+        */
+       ctx.hdr.rq_lun = tmp & 3;
+       ctx.hdr.rs_lun = tmp & 3;
+
+       /* get command code */
+       ctx.hdr.cmd = tvb_get_guint8(tvb, 1);
+
+       /* set dissect flags */
+       ctx.flags = IPMI_D_NO_CKS|IPMI_D_NO_RQ_SA|IPMI_D_NO_SEQ;
 
-       /* Optional byte: in Send Message targeted to session-based channels */
-       if (dfmt->flags & IPMI_D_SESSION_HANDLE) {
-               offs++;
+       /* set header length */
+       ctx.hdr_len = 2;
+
+       /* copy channel number and direction */
+       ctx.hdr.context = arg ? arg->context : 0;
+       ctx.hdr.channel = arg ? arg->channel : 0;
+       ctx.hdr.dir = arg ? arg->flags >> 7 : ctx.hdr.netfn & 1;
+
+       if (ctx.hdr.context == IPMI_E_NONE) {
+               /* set source column */
+               col_set_str(pinfo->cinfo, COL_DEF_SRC, ctx.hdr.dir ? "HOST" : "BMC");
+
+               /* set destination column */
+               col_set_str(pinfo->cinfo, COL_DEF_DST, ctx.hdr.dir ? "BMC" : "HOST");
        }
 
-       /* Optional byte: 00 indicates General Call address - broadcast message */
-       if ((dfmt->flags & IPMI_D_BROADCAST) && tvb_get_guint8(tvb, offs) == 0x00) {
-               is_broadcast = 1;
-               offs++;
+       /* dissect IPMI command */
+       return dissect_ipmi_cmd(tvb, pinfo, tree, proto_kcs, ett_ipmi, &ctx);
+}
+
+static guint8 calc_cks(guint8 start, tvbuff_t * tvb, guint off, guint len)
+{
+       while (len--) {
+               start += tvb_get_guint8(tvb, off++);
        }
 
-       /* Byte 1: target slave address, may be absent (in Get Message) */
-       hdr.trg_sa = (dfmt->flags & IPMI_D_TRG_SA) ? tvb_get_guint8(tvb, offs++) : 0;
-
-       /* Byte 2: network function + target LUN */
-       tmp = tvb_get_guint8(tvb, offs++);
-       hdr.trg_lun = tmp & 0x03;
-       hdr.netfn = (tmp >> 2) & 0x3f;
-       hdr_exp_crc = (0 - hdr.trg_sa - tmp) & 0xff;
-
-       /* Byte 3: header checksum */
-       hdr_crc = tvb_get_guint8(tvb, offs++);
-
-       /* Byte 4: source slave address */
-       hdr.src_sa = tvb_get_guint8(tvb, offs++);
-
-       /* Byte 5: sequence number + source LUN */
-       tmp = tvb_get_guint8(tvb, offs++);
-       hdr.src_lun = tmp & 0x03;
-       hdr.seq = (tmp >> 2) & 0x3f;
-
-       /* Byte 6: command code */
-       hdr.cmd = tvb_get_guint8(tvb, offs++);
-
-       /* Byte 7: completion code (in response) */
-       is_resp = (hdr.netfn & 0x1) ? 1 : 0;
-       hdr.ccode = is_resp ? tvb_get_guint8(tvb, offs++) : 0;
-
-       /* 0-3 bytes: signature of the defining body */
-       siglen = ipmi_getsiglen(hdr.netfn);
-       in = ipmi_getnetfn(hdr.netfn, tvb_get_ptr(tvb, offs, siglen));
-       offs += siglen;
-
-       /* Save header length */
-       hdrlen = offs;
-       hdr.data_len = tvb_length(tvb) - hdrlen - 1;
-
-       /* Get some text descriptions */
-       ic = ipmi_getcmd(in, hdr.cmd);
-       ndesc = ipmi_getnetfnname(hdr.netfn, in);
-       cdesc = ic->desc;
-       ccdesc = ipmi_get_completion_code(hdr.ccode, ic);
-       if (!is_broadcast) {
-               bcast = "";
-       } else if (ic->flags & CMD_MAYBROADCAST) {
-               bcast = " (BROADCAST: command may not be broadcast)";
+       return start;
+}
+
+static gboolean guess_imb_format(tvbuff_t *tvb, guint8 env,
+               guint8 channel, guint * imb_flags, guint8 * cks1, guint8 * cks2)
+{
+       gboolean check_bc = FALSE;
+       gboolean check_sh = FALSE;
+       gboolean check_sa = FALSE;
+       guint tvb_len;
+       guint sh_len;
+       guint sa_len;
+       guint rs_sa;
+
+       if (message_format == MSGFMT_NONE) {
+               return FALSE;
+       } else if (message_format == MSGFMT_IPMB) {
+               *imb_flags = IPMI_D_TRG_SA;
+       } else if (message_format == MSGFMT_LAN) {
+               *imb_flags = IPMI_D_TRG_SA|IPMI_D_SESSION_HANDLE;
+       /* channel 0 is primary IPMB */
+       } else if (!channel) {
+               /* check for broadcast if not in send message command */
+               if (env == IPMI_E_NONE) {
+                       /* check broadcast */
+                       check_bc = 1;
+
+                       /* slave address must be present */
+                       *imb_flags = IPMI_D_TRG_SA;
+               /* check if in send message command */
+               } else if (env != IPMI_E_GETMSG) {
+                       /* slave address must be present */
+                       *imb_flags = IPMI_D_TRG_SA;
+               } else /* IPMI_E_GETMSG */ {
+                       *imb_flags = 0;
+               }
+       /* channel 15 is System Interface */
+       } else if (channel == 15) {
+               /* slave address must be present */
+               *imb_flags = IPMI_D_TRG_SA;
+
+               /* check if in get message command */
+               if (env == IPMI_E_GETMSG) {
+                       /* session handle must be present */
+                       *imb_flags |= IPMI_D_SESSION_HANDLE;
+               }
+       /* for other channels */
        } else {
-               bcast = " (BROADCAST)";
+               if (env == IPMI_E_NONE) {
+                       /* check broadcast */
+                       check_bc = 1;
+
+                       /* slave address must be present */
+                       *imb_flags = IPMI_D_TRG_SA;
+               } else if (env == IPMI_E_SENDMSG_RQ) {
+                       /* check session handle */
+                       check_sh = 1;
+
+                       /* slave address must be present */
+                       *imb_flags = IPMI_D_TRG_SA;
+               } else if (env == IPMI_E_SENDMSG_RS) {
+                       /* slave address must be present */
+                       *imb_flags = IPMI_D_TRG_SA;
+               } else /* IPMI_E_GETMSG */ {
+                       /* check session handle */
+                       check_sh = 1;
+
+                       /* check slave address presence */
+                       check_sa = 1;
+
+                       /* no pre-requisites */
+                       *imb_flags = 0;
+               }
+       }
+
+       /* get message length */
+       tvb_len = tvb_captured_length(tvb);
+
+       /*
+        * broadcast message starts with null,
+        * does not contain session handle
+        * but contains responder address
+        */
+       if (check_bc
+                       && tvb_len >= 8
+                       && !tvb_get_guint8(tvb, 0)
+                       && !calc_cks(0, tvb, 1, 3)
+                       && !calc_cks(0, tvb, 4, tvb_len - 4)) {
+               *imb_flags = IPMI_D_BROADCAST|IPMI_D_TRG_SA;
+               *cks1 = 0;
+               *cks2 = 0;
+               return TRUE;
        }
 
+       /*
+        * message with the starts with session handle
+        * and contain responder address
+        */
+       if (check_sh
+                       && tvb_len >= 8
+                       && !calc_cks(0, tvb, 1, 3)
+                       && !calc_cks(0, tvb, 4, tvb_len - 4)) {
+               *imb_flags = IPMI_D_SESSION_HANDLE|IPMI_D_TRG_SA;
+               *cks1 = 0;
+               *cks2 = 0;
+               return TRUE;
+       }
 
-       /* Save globals - we may be called recursively */
-       saved_hdr = ipmi_current_hdr;
-       ipmi_current_hdr = &hdr;
-       saved_saved_data = current_saved_data;
-       current_saved_data = NULL;
+       /*
+        * message with responder address
+        */
+       if (check_sa
+                       && tvb_len >= 7
+                       && !calc_cks(0, tvb, 0, 3)
+                       && !calc_cks(0, tvb, 3, tvb_len - 3)) {
+               *imb_flags = IPMI_D_TRG_SA;
+               *cks1 = 0;
+               *cks2 = 0;
+               return TRUE;
+       }
 
-       /* Select sub-handler */
-       hnd = is_resp ? ic->parse_resp : ic->parse_req;
 
-       /* Start new conversation if needed */
-       if (!is_resp && (ic->flags & CMD_NEWCONV)) {
-               conversation_new(pinfo->fd->num, &pinfo->src,
-                               &pinfo->dst, pinfo->ptype,
-                               pinfo->srcport, pinfo->destport, 0);
+       if (*imb_flags & IPMI_D_SESSION_HANDLE) {
+               sh_len = 1;
+               sa_len = 1;
+               rs_sa = 0;
+       } else if (*imb_flags & IPMI_D_TRG_SA) {
+               sh_len = 0;
+               sa_len = 1;
+               rs_sa = 0;
+       } else {
+               sh_len = 0;
+               sa_len = 0;
+               rs_sa = 0x20;
        }
 
-       /* Check if we need to insert request-response pair */
-       maybe_insert_reqresp(pinfo, dfmt, &hdr);
+       /* check message length */
+       if (tvb_len < 6 + sh_len + sa_len) {
+               return FALSE;
+       }
 
-       /* Create data subset: all but header and last byte (checksum) */
-       data_tvb = tvb_new_subset(tvb, hdrlen, hdr.data_len, hdr.data_len);
+       /* calculate checksum deltas */
+       *cks1 = calc_cks(rs_sa, tvb, sh_len, sa_len + 2);
+       *cks2 = calc_cks(0, tvb, sh_len + sa_len + 2,
+                       tvb_len - sh_len - sa_len - 2);
 
-       /* Brief description of a packet */
-       g_snprintf(dfmt->info, ITEM_LABEL_LENGTH, "%s, %s, seq 0x%02x%s%s%s",
-                       is_resp ? "Rsp" : "Req", cdesc, hdr.seq, bcast,
-                       hdr.ccode ? ", " : "", hdr.ccode ? ccdesc : "");
+       return TRUE;
+}
 
-       if (!is_resp && (ic->flags & CMD_CALLRQ)) {
-               hnd(data_tvb, pinfo, NULL);
-       }
+int
+do_dissect_ipmb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+               gint hf_parent_item, gint ett_tree, ipmi_dissect_arg_t * arg)
+{
+       ipmi_context_t ctx;
+       guint offset = 0;
+       guint8 tmp;
 
-       if (ipmi_tree) {
-               add_reqresp_info(dfmt, &hdr, ipmi_tree, tvb, pinfo);
+       memset(&ctx, 0, sizeof(ctx));
 
-               ti = proto_tree_add_text(ipmi_tree, tvb, 0, hdrlen,
-                               "Header: %s (%s) from 0x%02x to 0x%02x%s", cdesc,
-                               is_resp ? "Response" : "Request", hdr.src_sa, hdr.trg_sa, bcast);
-               hdr_tree = proto_item_add_subtree(ti, ett_header);
+       /* copy message context and channel */
+       ctx.hdr.context = arg ? arg->context : 0;
+       ctx.hdr.channel = arg ? arg->channel : 0;
 
-               offs = 0;
+       /* guess IPMB message format */
+       if (!guess_imb_format(tvb, ctx.hdr.context, ctx.hdr.channel,
+                       &ctx.flags, &ctx.cks1, &ctx.cks2)) {
+               return 0;
+       }
 
-               if (dfmt->flags & IPMI_D_SESSION_HANDLE) {
-                       proto_tree_add_item(hdr_tree, hf_ipmi_session_handle,
-                                       tvb, offs++, 1, ENC_LITTLE_ENDIAN);
-               }
+       /* check if message is broadcast */
+       if (ctx.flags & IPMI_D_BROADCAST) {
+               /* skip first byte */
+               offset++;
+       }
 
-               /* Broadcast byte (optional) */
-               if (is_broadcast) {
-                       proto_tree_add_uint_format(hdr_tree, hf_ipmi_header_broadcast,
-                                       tvb, offs++, 1, 0x00, "Broadcast message");
-               }
+       /* check is session handle is specified */
+       if (ctx.flags & IPMI_D_SESSION_HANDLE) {
+               ctx.hdr.session = tvb_get_guint8(tvb, offset++);
+       }
 
-               /* Target SA, if present */
-               if (dfmt->flags & IPMI_D_TRG_SA) {
-                       proto_tree_add_item(hdr_tree, hf_ipmi_header_trg, tvb, offs++, 1, ENC_LITTLE_ENDIAN);
-               }
+       /* check is response address is specified */
+       if (ctx.flags & IPMI_D_TRG_SA) {
+               ctx.hdr.rs_sa = tvb_get_guint8(tvb, offset++);
+       } else {
+               ctx.hdr.rs_sa = 0x20;
+       }
 
-               /* Network function + target LUN */
-               ti = proto_tree_add_text(hdr_tree, tvb, offs, 1,
-                               "Target LUN: 0x%02x, NetFN: %s %s (0x%02x)", hdr.trg_lun,
-                               ndesc, is_resp ? "Response" : "Request", hdr.netfn);
-               s_tree = proto_item_add_subtree(ti, ett_header_byte_1);
-
-               proto_tree_add_item(s_tree, hf_ipmi_header_trg_lun, tvb, offs, 1, ENC_LITTLE_ENDIAN);
-               proto_tree_add_uint_format(s_tree, hf_ipmi_header_netfn, tvb, offs, 1,
-                               hdr.netfn << 2, "%sNetFn: %s %s (0x%02x)",
-                               ipmi_dcd8(hdr.netfn << 2, 0xfc),
-                               ndesc, is_resp ? "Response" : "Request", hdr.netfn);
-               offs++;
+       /* get Net Fn/RS LUN field */
+       tmp = tvb_get_guint8(tvb, offset++);
 
-               /* Header checksum */
-               if (hdr_crc == hdr_exp_crc) {
-                       proto_tree_add_uint_format_value(hdr_tree, hf_ipmi_header_crc, tvb, offs++, 1,
-                                       hdr_crc, "0x%02x (correct)", hdr_crc);
-               }
-               else {
-                       ti = proto_tree_add_boolean(hdr_tree, hf_ipmi_bad_checksum, tvb, 0, 0, TRUE);
-                       PROTO_ITEM_SET_HIDDEN(ti);
-                       proto_tree_add_uint_format_value(hdr_tree, hf_ipmi_header_crc, tvb, offs++, 1,
-                                       hdr_crc, "0x%02x (incorrect, expected 0x%02x)",
-                                       hdr_crc, hdr_exp_crc);
-               }
+       /* set Net Fn  and RS LUN */
+       ctx.hdr.netfn = tmp >> 2;
+       ctx.hdr.rs_lun = tmp & 3;
 
-               /* Remember where chk2 bytes start */
-               data_chk_offs = offs;
+       /* skip cks1 */
+       offset++;
 
-               /* Source SA */
-               proto_tree_add_item(hdr_tree, hf_ipmi_header_src, tvb, offs++, 1, ENC_LITTLE_ENDIAN);
+       /* get RQ SA */
+       ctx.hdr.rq_sa = tvb_get_guint8(tvb, offset++);
 
-               /* Sequence number + source LUN */
-               ti = proto_tree_add_text(hdr_tree, tvb, offs, 1,
-                               "Source LUN: 0x%02x, SeqNo: 0x%02x",
-                               hdr.src_lun, hdr.seq);
-               s_tree = proto_item_add_subtree(ti, ett_header_byte_4);
+       /* get RQ Seq/RQ LUN field */
+       tmp = tvb_get_guint8(tvb, offset++);
 
-               proto_tree_add_item(s_tree, hf_ipmi_header_src_lun, tvb, offs, 1, ENC_LITTLE_ENDIAN);
-               proto_tree_add_item(s_tree, hf_ipmi_header_sequence, tvb, offs, 1, ENC_LITTLE_ENDIAN);
-               offs++;
+       /* set RQ Seq  and RQ LUN */
+       ctx.hdr.rq_seq = tmp >> 2;
+       ctx.hdr.rq_lun = tmp & 3;
 
-               /* Command */
-               proto_tree_add_uint_format_value(hdr_tree, hf_ipmi_header_command, tvb, offs++, 1,
-                               hdr.cmd, "%s (0x%02x)", cdesc, hdr.cmd);
+       /* get command code */
+       ctx.hdr.cmd = tvb_get_guint8(tvb, offset++);
 
-               /* Response code (if present) */
-               if (is_resp) {
-                       proto_tree_add_uint_format_value(hdr_tree, hf_ipmi_header_completion, tvb, offs++, 1,
-                               hdr.ccode, "%s (0x%02x)", ccdesc, hdr.ccode);
-               }
+       /* set header length */
+       ctx.hdr_len = offset;
 
-               /* Defining body signature (if present) */
-               if (siglen) {
-                       ti = proto_tree_add_item(hdr_tree, hf_ipmi_header_sig, tvb, offs, siglen, ENC_NA);
-                       proto_item_append_text(ti, " (%s)", ndesc);
-                       /*offs += siglen;*/
-               }
+       /* copy direction */
+       ctx.hdr.dir = arg ? arg->flags >> 7 : ctx.hdr.netfn & 1;
 
-               /* Call data parser */
-               if (tvb_length(data_tvb) && hnd) {
-                       ti = proto_tree_add_text(ipmi_tree, data_tvb, 0, -1, "Data");
-                       data_tree = proto_item_add_subtree(ti, ett_data);
-                       hnd(data_tvb, pinfo, data_tree);
-               }
+       if (ctx.hdr.context == IPMI_E_NONE) {
+               guint red = arg ? (arg->flags & 0x40) : 0;
 
-               /* Checksum all but the last byte */
-               len = tvb_length(tvb) - 1;
-               data_crc = tvb_get_guint8(tvb, len);
-               data_exp_crc = 0;
-               for (i = data_chk_offs; i < len; i++) {
-                       data_exp_crc += tvb_get_guint8(tvb, i);
+               if (!ctx.hdr.channel) {
+                       col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
+                                       "0x%02x(%s)", ctx.hdr.rq_sa, red ? "IPMB-B" : "IPMB-A");
+               } else {
+                       col_add_fstr(pinfo->cinfo, COL_DEF_SRC,
+                                       "0x%02x", ctx.hdr.rq_sa);
                }
-               data_exp_crc = (0 - data_exp_crc) & 0xff;
 
-               if (data_crc == data_exp_crc) {
-                       proto_tree_add_uint_format_value(ipmi_tree, hf_ipmi_data_crc, tvb, len, 1,
-                                       data_crc, "0x%02x (correct)", data_crc);
-               }
-               else {
-                       ti = proto_tree_add_boolean(hdr_tree, hf_ipmi_bad_checksum, tvb, 0, 0, TRUE);
-                       PROTO_ITEM_SET_HIDDEN(ti);
-                       proto_tree_add_uint_format_value(ipmi_tree, hf_ipmi_data_crc, tvb, len, 1,
-                                       data_crc, "0x%02x (incorrect, expected 0x%02x)",
-                                       data_crc, data_exp_crc);
-               }
+               col_add_fstr(pinfo->cinfo, COL_DEF_DST, "0x%02x", ctx.hdr.rs_sa);
        }
 
-       /* Restore globals, in case we've been called recursively */
-       ipmi_current_hdr = saved_hdr;
-       current_saved_data = saved_saved_data;
-       nest_level--;
+       /* dissect IPMI command */
+       return dissect_ipmi_cmd(tvb, pinfo, tree, hf_parent_item, ett_tree, &ctx);
 }
 
-static void
-dissect_ipmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static int
+dissect_ipmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
 {
-       proto_tree *ipmi_tree = NULL;
-       proto_item *ti;
-       ipmi_dissect_format_t dfmt;
-
-       col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPMI/ATCA");
-
-       if (tree) {
-               ti = proto_tree_add_item(tree, proto_ipmi, tvb, 0, -1, ENC_NA);
-               ipmi_tree = proto_item_add_subtree(ti, ett_ipmi);
-       }
-
-       memset(&dfmt, 0, sizeof(dfmt));
-       dfmt.flags = IPMI_D_BROADCAST | IPMI_D_TRG_SA;
-       ipmi_do_dissect(tvb, pinfo, ipmi_tree, &dfmt);
-
-       col_add_str(pinfo->cinfo, COL_INFO, dfmt.info);
-
+       return do_dissect_ipmb(tvb, pinfo, tree, proto_ipmb, ett_ipmi,
+                       (ipmi_dissect_arg_t *) data);
 }
 
 /* Register IPMB protocol.
  */
-
 void
 proto_register_ipmi(void)
 {
        static hf_register_info hf[] = {
-               { &hf_ipmi_message, { "Message", "ipmi.message", FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_session_handle, { "Session handle", "ipmi.session_handle", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
-               { &hf_ipmi_header_broadcast, { "Broadcast message", "ipmi.header.broadcast", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_header_trg, { "Target Address", "ipmi.header.target", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL }},
                { &hf_ipmi_header_trg_lun, { "Target LUN", "ipmi.header.trg_lun", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL }},
                { &hf_ipmi_header_netfn, { "NetFN", "ipmi.header.netfn", FT_UINT8, BASE_HEX, NULL, 0xfc, NULL, HFILL }},
                { &hf_ipmi_header_crc, { "Header Checksum", "ipmi.header.crc", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_header_src, { "Source Address", "ipmi.header.source", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_header_src_lun, { "Source LUN", "ipmi.header.src_lun", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL }},
+               { &hf_ipmi_header_bridged, { "Bridged", "ipmi.header.bridged", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL }},
                { &hf_ipmi_header_sequence, { "Sequence Number", "ipmi.header.sequence", FT_UINT8, BASE_HEX, NULL, 0xfc, NULL, HFILL }},
                { &hf_ipmi_header_command, { "Command", "ipmi.header.command", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_header_completion, { "Completion Code", "ipmi.header.completion", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
@@ -1379,8 +1746,7 @@ proto_register_ipmi(void)
                { &hf_ipmi_data_crc, { "Data checksum", "ipmi.data.crc", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_response_to, { "Response to", "ipmi.response_to", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }},
                { &hf_ipmi_response_in, { "Response in", "ipmi.response_in", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }},
-               { &hf_ipmi_response_time, { "Responded in", "ipmi.response_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0, NULL, HFILL }},
-               { &hf_ipmi_bad_checksum, { "Bad checksum", "ipmi.bad_checksum", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }}
+               { &hf_ipmi_response_time, { "Responded in", "ipmi.response_time", FT_RELATIVE_TIME, BASE_NONE, NULL, 0, NULL, HFILL }}
        };
        static gint *ett[] = {
                &ett_ipmi,
@@ -1406,9 +1772,19 @@ proto_register_ipmi(void)
        guint32 i;
 
        proto_ipmi = proto_register_protocol("Intelligent Platform Management Interface",
-                               "IPMI/ATCA",
+                               "IPMI",
                                "ipmi");
 
+       proto_ipmb = proto_register_protocol("Intelligent Platform Management Bus",
+                               "IPMB",
+                               "ipmb");
+       proto_kcs = proto_register_protocol("Keyboard Controller Style Interface",
+                               "KCS",
+                               "kcs");
+       proto_tmode = proto_register_protocol("Serial Terminal Mode Interface",
+                               "TMode",
+                               "tmode");
+
        proto_register_field_array(proto_ipmi, hf, array_length(hf));
        proto_register_subtree_array(ett, array_length(ett));
 
@@ -1434,8 +1810,14 @@ proto_register_ipmi(void)
        ipmi_register_transport(proto_ipmi);
        ipmi_register_picmg(proto_ipmi);
        ipmi_register_pps(proto_ipmi);
+       ipmi_register_vita(proto_ipmi);
+
+       new_register_dissector("ipmi", dissect_ipmi, proto_ipmi);
+       new_register_dissector("ipmb", dissect_ipmi, proto_ipmb);
+       new_register_dissector("kcs", dissect_kcs, proto_kcs);
+       new_register_dissector("tmode", dissect_tmode, proto_tmode);
 
-       register_dissector("ipmi", dissect_ipmi, proto_ipmi);
+       data_dissector = find_dissector("data");
 
        m = prefs_register_protocol(proto_ipmi, NULL);
        prefs_register_bool_preference(m, "fru_langcode_is_english", "FRU Language Code is English",
index 840506f73742db05dbbf953436f2453cc2d70b6f..f28a994c0937954563be018f312d6dca1d27d1b7 100644 (file)
@@ -54,23 +54,36 @@ enum {
        IPMI_OEM_PPS            /* Pigeon Point Systems extensions */
 };
 
-/* IPMI header fields */
-struct ipmi_header {
-       guint8 trg_sa;
-       guint8 trg_lun;
-       guint8 src_sa;
-       guint8 src_lun;
-       guint8 netfn;
-       guint8 cmd;
-       guint8 seq;
-       guint8 ccode;
-       guint8 data_len;
+/*
+ * Command context (environment).
+ */
+enum {
+       IPMI_E_NONE,            /* no surround environment */
+       IPMI_E_SENDMSG_RQ,      /* encapsulated into Send Message request */
+       IPMI_E_SENDMSG_RS,      /* encapsulated into Send Message response */
+       IPMI_E_GETMSG           /* encapsulated into Get Message response */
 };
 
-extern struct ipmi_header *ipmi_current_hdr;
+/*
+ * Cached IPMI message header.
+ */
+typedef struct {
+       guint8 context;
+       guint8 channel;
+       guint8 dir;
+       guint8 session;
+       guint8 rs_sa;
+       guint8 rs_lun;
+       guint8 netfn;
+       guint8 rq_sa;
+       guint8 rq_lun;
+       guint8 rq_seq;
+       guint8 cmd;
+} ipmi_header_t;
 
 /* Sub-parser */
-typedef void (*ipmi_cmd_handler_t)(tvbuff_t *, packet_info *, proto_tree *);
+typedef void (*ipmi_cmd_handler_t)(tvbuff_t *,
+               packet_info *, proto_tree *);
 
 /* IPMI command structure.  */
 typedef struct {
@@ -84,12 +97,19 @@ typedef struct {
 } ipmi_cmd_t;
 
 /* Command flags */
-#define CMD_MAYBROADCAST       0x01            /* Command can be broadcast over IPMB */
 #define CMD_CALLRQ             0x02            /* Call request handler early to cache data */
-#define CMD_NEWCONV            0x04            /* This command starts new conversation */
 
-void ipmi_setsaveddata(guint idx, guint32 val);
-gboolean ipmi_getsaveddata(guint idx, guint32 *val);
+/* Get currently parsed message header */
+const ipmi_header_t * ipmi_get_hdr(packet_info * pinfo);
+
+/* Get completion code for currently parsed message */
+guint8 ipmi_get_ccode(packet_info * pinfo);
+
+/* Save request data for later use in response */
+void ipmi_set_data(packet_info *pinfo, guint idx, guint32 data);
+
+/* Get saved request data */
+gboolean ipmi_get_data(packet_info *pinfo, guint idx, guint32 * data);
 
 /* Top-level search structure: signatures (if any) + command table */
 typedef struct ipmi_netfn_handler {
@@ -154,35 +174,30 @@ void ipmi_register_se(int proto);
 void ipmi_register_storage(int proto);
 void ipmi_register_transport(int proto);
 void ipmi_register_update(int proto);
+void ipmi_register_vita(int proto);
 
 /* Main dissection routine */
-#define IPMI_D_NONE                    0x0001 /* Do not parse at all */
-#define IPMI_D_SESSION_HANDLE          0x0002 /* Session handle */
-#define IPMI_D_BROADCAST               0x0004 /* Check for broadcast message */
-#define IPMI_D_TRG_SA                  0x0008 /* Target slave addr is present */
-
-struct ipmi_reqresp;
-
+#define IPMI_D_NONE            0x0001 /* Do not parse at all */
+#define IPMI_D_SESSION_HANDLE  0x0002 /* Session handle */
+#define IPMI_D_BROADCAST       0x0004 /* Check for broadcast message */
+#define IPMI_D_TRG_SA          0x0008 /* Target slave addr is present */
+#define IPMI_D_TMODE           0x0010 /* Bridged field instead of Rq LUN */
+#define IPMI_D_NO_CKS          0x0020 /* Checksum bytes are not present */
+#define IPMI_D_NO_RQ_SA                0x0040 /* RQ SA is not present */
+#define IPMI_D_NO_SEQ          0x0080 /* RQ Seq is not present */
+
+/* IPMI dissector argument */
 typedef struct {
-       guint32 flags;
-       gchar info[ITEM_LABEL_LENGTH];
-       void *arg;                      /* Argument passed to callbacks */
-
-       /* Extra methods for requests that contain embedded commands */
-       struct ipmi_header *(*getmoreheaders)(struct ipmi_header *base, void *arg, guint i);
-       int (*whichresponse)(struct ipmi_header *hdr, struct ipmi_reqresp *rr);
-       int (*otheridx)(struct ipmi_header *hdr);
-} ipmi_dissect_format_t;
-
-int ipmi_guess_dissect_flags(tvbuff_t *tvb);
-void ipmi_do_dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, ipmi_dissect_format_t *dfmt);
-
-struct ipmi_header *ipmi_sendmsg_getheaders(struct ipmi_header *base, void *arg, guint i);
-int ipmi_sendmsg_whichresponse(struct ipmi_header *hdr, struct ipmi_reqresp *rr);
-int ipmi_sendmsg_otheridx(struct ipmi_header *hdr);
+       guint8 context;
+       guint8 channel;
+       guint8 flags;
+} ipmi_dissect_arg_t;
 
-#endif
+int
+do_dissect_ipmb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
+               gint hf_parent_item, gint ett_tree, ipmi_dissect_arg_t * arg);
 
+#endif /* __PACKET_IPMI_H__ */
 
 /*
  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
index 46b2412467ffd87919d109783421b0a229eb4204..d06397d47ea098e9a7c3b7e5971a4d82fac851d4 100644 (file)
@@ -734,6 +734,9 @@ static struct encap_type_info encap_table_base[] = {
 
        /* WTAP_ENCAP_EPON */
        { "Ethernet Passive Optical Network", "epon" },
+
+       /* WTAP_ENCAP_IPMI_TRACE */
+       { "IPMI Trace Data Collection", "ipmi-trace" },
 };
 
 WS_DLL_LOCAL
index c324b2199c49e4a2fe9946908b56ba8a7bcd0a94..d0910d930d6f71f682c72779840be9c67d012af0 100644 (file)
@@ -264,6 +264,7 @@ extern "C" {
 #define WTAP_ENCAP_LOGCAT_LONG                  171
 #define WTAP_ENCAP_PKTAP                        172
 #define WTAP_ENCAP_EPON                         173
+#define WTAP_ENCAP_IPMI_TRACE                   174
 /* After adding new item here, please also add new item to encap_table_base array */
 
 #define WTAP_NUM_ENCAP_TYPES                    wtap_get_num_encap_types()