diff options
Diffstat (limited to 'epan')
-rw-r--r-- | epan/CMakeLists.txt | 2 | ||||
-rw-r--r-- | epan/dissectors/Makefile.common | 4 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi-app.c | 100 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi-chassis.c | 25 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi-picmg.c | 1602 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi-pps.c | 119 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi-se.c | 55 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi-session.c | 8 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi-storage.c | 24 | ||||
-rwxr-xr-x | epan/dissectors/packet-ipmi-trace.c | 479 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi-transport.c | 74 | ||||
-rwxr-xr-x | epan/dissectors/packet-ipmi-vita.c | 1325 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi.c | 1592 | ||||
-rw-r--r-- | epan/dissectors/packet-ipmi.h | 97 |
14 files changed, 4583 insertions, 923 deletions
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index f6d69f5aed..7461dc1cbc 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -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 diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common index 94ce213316..6d24559e13 100644 --- a/epan/dissectors/Makefile.common +++ b/epan/dissectors/Makefile.common @@ -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 diff --git a/epan/dissectors/packet-ipmi-app.c b/epan/dissectors/packet-ipmi-app.c index fffb526827..97b71bc93f 100644 --- a/epan/dissectors/packet-ipmi-app.c +++ b/epan/dissectors/packet-ipmi-app.c @@ -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, diff --git a/epan/dissectors/packet-ipmi-chassis.c b/epan/dissectors/packet-ipmi-chassis.c index 2d8d85c5a6..98e9ed68b3 100644 --- a/epan/dissectors/packet-ipmi-chassis.c +++ b/epan/dissectors/packet-ipmi-chassis.c @@ -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 }}, diff --git a/epan/dissectors/packet-ipmi-picmg.c b/epan/dissectors/packet-ipmi-picmg.c index a957ff26ae..04f2423747 100644 --- a/epan/dissectors/packet-ipmi-picmg.c +++ b/epan/dissectors/packet-ipmi-picmg.c @@ -28,11 +28,11 @@ #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 }; diff --git a/epan/dissectors/packet-ipmi-pps.c b/epan/dissectors/packet-ipmi-pps.c index 5d4a3c77c3..f3d089018f 100644 --- a/epan/dissectors/packet-ipmi-pps.c +++ b/epan/dissectors/packet-ipmi-pps.c @@ -28,59 +28,72 @@ #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 diff --git a/epan/dissectors/packet-ipmi-se.c b/epan/dissectors/packet-ipmi-se.c index def7398c46..b464a00316 100644 --- a/epan/dissectors/packet-ipmi-se.c +++ b/epan/dissectors/packet-ipmi-se.c @@ -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]); diff --git a/epan/dissectors/packet-ipmi-session.c b/epan/dissectors/packet-ipmi-session.c index b3f6e403ad..c04db04a9f 100644 --- a/epan/dissectors/packet-ipmi-session.c +++ b/epan/dissectors/packet-ipmi-session.c @@ -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 diff --git a/epan/dissectors/packet-ipmi-storage.c b/epan/dissectors/packet-ipmi-storage.c index 29f260235d..5f9d0ab6f9 100644 --- a/epan/dissectors/packet-ipmi-storage.c +++ b/epan/dissectors/packet-ipmi-storage.c @@ -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 index 0000000000..fa5dc03980 --- /dev/null +++ b/epan/dissectors/packet-ipmi-trace.c @@ -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, ×tamp); + + /* 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: + */ diff --git a/epan/dissectors/packet-ipmi-transport.c b/epan/dissectors/packet-ipmi-transport.c index 30591496b1..acfa0bf97c 100644 --- a/epan/dissectors/packet-ipmi-transport.c +++ b/epan/dissectors/packet-ipmi-transport.c @@ -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 index 0000000000..d41b33d654 --- /dev/null +++ b/epan/dissectors/packet-ipmi-vita.c @@ -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: + */ diff --git a/epan/dissectors/packet-ipmi.c b/epan/dissectors/packet-ipmi.c index 62f71049d3..54cc8ca174 100644 --- a/epan/dissectors/packet-ipmi.c +++ b/epan/dissectors/packet-ipmi.c @@ -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", diff --git a/epan/dissectors/packet-ipmi.h b/epan/dissectors/packet-ipmi.h index 840506f737..f28a994c09 100644 --- a/epan/dissectors/packet-ipmi.h +++ b/epan/dissectors/packet-ipmi.h @@ -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 |