diff options
author | Guy Harris <guy@alum.mit.edu> | 2003-04-23 00:24:38 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2003-04-23 00:24:38 +0000 |
commit | 733b96657b9c461e802a6d12c8ba0e09a53dce6d (patch) | |
tree | f125c2b34f26275baa5095ddeed2dc07bd7cab6e | |
parent | cf110883402711dcb5c697109a30fac125c1cd6b (diff) | |
download | wireshark-733b96657b9c461e802a6d12c8ba0e09a53dce6d.tar.gz wireshark-733b96657b9c461e802a6d12c8ba0e09a53dce6d.tar.bz2 wireshark-733b96657b9c461e802a6d12c8ba0e09a53dce6d.zip |
From Duncan Laurie: IPMI-over-LAN support.
svn path=/trunk/; revision=7538
-rw-r--r-- | AUTHORS | 4 | ||||
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | Makefile.nmake | 5 | ||||
-rw-r--r-- | doc/ethereal.pod.template | 1 | ||||
-rw-r--r-- | packet-asf.c | 147 | ||||
-rw-r--r-- | packet-ipmi.c | 647 | ||||
-rw-r--r-- | packet-rmcp.c | 189 |
7 files changed, 996 insertions, 2 deletions
@@ -1674,6 +1674,10 @@ Erwin Rol <erwin [AT] muffin.org> { ArtNET support } +Duncan Laurie <duncan [AT] sun.com> { + IPMI-over-LAN support (IPMI, RMCP, partial ASF) +} + And assorted fixes and enhancements by the people listed above and by: Pavel Roskin <proski [AT] gnu.org> diff --git a/Makefile.am b/Makefile.am index 38601d0536..17cd47e87b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am # Automake file for Ethereal # -# $Id: Makefile.am,v 1.575 2003/04/21 21:28:31 guy Exp $ +# $Id: Makefile.am,v 1.576 2003/04/23 00:24:36 guy Exp $ # # Ethereal - Network traffic analyzer # By Gerald Combs <gerald@ethereal.com> @@ -96,6 +96,7 @@ DISSECTOR_SRC = \ packet-arp.c \ packet-asap.c \ packet-ascend.c\ + packet-asf.c \ packet-atalk.c \ packet-atm.c \ packet-auto_rp.c \ @@ -228,6 +229,7 @@ DISSECTOR_SRC = \ packet-imap.c \ packet-ip.c \ packet-ipfc.c \ + packet-ipmi.c \ packet-ipp.c \ packet-ipsec.c \ packet-ipv6.c \ @@ -322,6 +324,7 @@ DISSECTOR_SRC = \ packet-rip.c \ packet-ripng.c \ packet-rlogin.c \ + packet-rmcp.c \ packet-rmi.c \ packet-rmp.c \ packet-rpc.c \ diff --git a/Makefile.nmake b/Makefile.nmake index a8cc2fb973..503bdf4499 100644 --- a/Makefile.nmake +++ b/Makefile.nmake @@ -1,7 +1,7 @@ ## Makefile for building ethereal.exe with Microsoft C and nmake ## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake # -# $Id: Makefile.nmake,v 1.293 2003/04/16 07:24:03 guy Exp $ +# $Id: Makefile.nmake,v 1.294 2003/04/23 00:24:36 guy Exp $ include config.nmake include <win32.mak> @@ -38,6 +38,7 @@ DISSECTOR_SRC = \ packet-arp.c \ packet-asap.c \ packet-ascend.c\ + packet-asf.c \ packet-atalk.c \ packet-atm.c \ packet-auto_rp.c \ @@ -170,6 +171,7 @@ DISSECTOR_SRC = \ packet-imap.c \ packet-ip.c \ packet-ipfc.c \ + packet-ipmi.c \ packet-ipp.c \ packet-ipsec.c \ packet-ipv6.c \ @@ -264,6 +266,7 @@ DISSECTOR_SRC = \ packet-rip.c \ packet-ripng.c \ packet-rlogin.c \ + packet-rmcp.c \ packet-rmi.c \ packet-rmp.c \ packet-rpc.c \ diff --git a/doc/ethereal.pod.template b/doc/ethereal.pod.template index ee982ce30f..5ed6fc17a6 100644 --- a/doc/ethereal.pod.template +++ b/doc/ethereal.pod.template @@ -1728,6 +1728,7 @@ B<http://www.ethereal.com>. emre <emre [AT] flash.net> Stephen Shelley <steve.shelley [AT] attbi.com> Erwin Rol <erwin [AT] muffin.org> + Duncan Laurie <duncan [AT] sun.com> Pavel Roskin <proski [AT] gnu.org> Georgi Guninski <guninski [AT] guninski.com> Jason Copenhaver <jcopenha [AT] typedef.org> diff --git a/packet-asf.c b/packet-asf.c new file mode 100644 index 0000000000..a379a418f6 --- /dev/null +++ b/packet-asf.c @@ -0,0 +1,147 @@ +/* packet-asf.c + * Routines for ASF packet dissection + * + * Duncan Laurie <duncan@sun.com> + * + * $Id: packet-asf.c,v 1.1 2003/04/23 00:24:36 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * Copied from packet-rmcp.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <glib.h> +#include <epan/packet.h> + +/* + * See + * + * http://www.dmtf.org/standards/standard_alert.php + */ + +#define RMCP_CLASS_ASF 0x06 + +static int proto_asf = -1; +static int hf_asf_iana = -1; +static int hf_asf_type = -1; +static int hf_asf_tag = -1; +static int hf_asf_len = -1; + +static dissector_handle_t data_handle; +static gint ett_asf = -1; + +static const value_string asf_type_vals[] = { + { 0x10, "Reset" }, + { 0x11, "Power-up" }, + { 0x12, "Unconditional Power-down" }, + { 0x13, "Power Cycle" }, + { 0x40, "Presence Pong" }, + { 0x41, "Capabilities Response" }, + { 0x42, "System State Response" }, + { 0x80, "Presence Ping" }, + { 0x81, "Capabilities Request" }, + { 0x82, "System State Request" }, + { 0x00, NULL } +}; + +static void +dissect_asf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *asf_tree = NULL; + proto_item *ti; + guint8 type; + guint8 len; + tvbuff_t *next_tvb; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "ASF"); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + type = tvb_get_guint8(tvb, 4); + len = tvb_get_guint8(tvb, 7); + + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_fstr(pinfo->cinfo, COL_INFO, "%s", + val_to_str(type, asf_type_vals, "Unknown (0x%02x)")); + + if (tree) { + ti = proto_tree_add_item(tree, proto_asf, tvb, 0, 8, TRUE); + asf_tree = proto_item_add_subtree(ti, ett_asf); + proto_tree_add_item(asf_tree, hf_asf_iana, tvb, 0, 4, TRUE); + proto_tree_add_item(asf_tree, hf_asf_type, tvb, 4, 1, TRUE); + proto_tree_add_item(asf_tree, hf_asf_tag, tvb, 5, 1, TRUE); + proto_tree_add_item(asf_tree, hf_asf_len, tvb, 7, 1, TRUE); + } + + if (len) { + next_tvb = tvb_new_subset(tvb, 8, -1, len); + call_dissector(data_handle, next_tvb, pinfo, tree); + } +} + +void +proto_register_asf(void) +{ + static hf_register_info hf[] = { + { &hf_asf_iana, { + "IANA Enterprise Number", "asf.iana", + FT_UINT32, BASE_HEX, NULL, 0, + "ASF IANA Enterprise Number", HFILL }}, + { &hf_asf_type, { + "Message Type", "asf.type", + FT_UINT8, BASE_HEX, VALS(asf_type_vals), 0, + "ASF Message Type", HFILL }}, + { &hf_asf_tag, { + "Message Tag", "asf.tag", + FT_UINT8, BASE_HEX, NULL, 0, + "ASF Message Tag", HFILL }}, + { &hf_asf_len, { + "Data Length", "asf.len", + FT_UINT8, BASE_DEC, NULL, 0, + "ASF Data Length", HFILL }}, + }; + static gint *ett[] = { + &ett_asf, + }; + + proto_asf = proto_register_protocol( + "Alert Standard Forum", "ASF", "asf"); + + proto_register_field_array(proto_asf, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("asf", dissect_asf, proto_asf); +} + +void +proto_reg_handoff_asf(void) +{ + dissector_handle_t asf_handle; + asf_handle = create_dissector_handle(dissect_asf, proto_asf); + dissector_add("rmcp.class", RMCP_CLASS_ASF, asf_handle); + + data_handle = find_dissector("data"); +} diff --git a/packet-ipmi.c b/packet-ipmi.c new file mode 100644 index 0000000000..066cc68e8f --- /dev/null +++ b/packet-ipmi.c @@ -0,0 +1,647 @@ +/* packet-ipmi.c + * Routines for IPMI-over-LAN packet dissection + * + * Duncan Laurie <duncan@sun.com> + * + * $Id: packet-ipmi.c,v 1.1 2003/04/23 00:24:36 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * Copied from packet-rmcp.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * + * See the IPMI spec at + * + * http://www.intel.com/design/servers/ipmi/ + * + * IPMI LAN Message Request + * ipmi.session.authtype + * ipmi.session.sequence + * ipmi.session.id + * [ipmi.session.authcode] + * ipmi.msg.len + * ipmi.msg.rsaddr + * ipmi.msg.netfn << 2 | ipmi.msg.rslun + * ipmi.msg.csum1 + * ipmi.msg.rqaddr + * ipmi.msg.seq << 2 | ipmi.msg.rqlun + * ipmi.msg.cmd + * ipmi.msg.DATA + * ipmi.msg.csum2 + * + * IPMI LAN Message Response + * ipmi.session.authtype + * ipmi.session.sequence + * ipmi.session.id + * [ipmi.session.authcode] + * ipmi.msg.len + * ipmi.msg.rqaddr + * ipmi.msg.netfn << 2 | ipmi.msg.rqlun + * ipmi.msg.csum1 + * ipmi.msg.rsaddr + * ipmi.msg.seq << 2 | ipmi.msg.rslun + * ipmi.msg.cmd + * ipmi.msg.ccode + * ipmi.msg.DATA + * ipmi.msg.csum2 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <glib.h> +#include <epan/packet.h> + +#define RMCP_CLASS_IPMI 0x07 + +static dissector_handle_t data_handle; +static int proto_ipmi = -1; + +static gint ett_ipmi = -1; +static gint ett_ipmi_session = -1; +static gint ett_ipmi_msg_nlfield = -1; +static gint ett_ipmi_msg_slfield = -1; + +/* IPMI session header */ +static int hf_ipmi_session_id = -1; +static int hf_ipmi_session_authtype = -1; +static int hf_ipmi_session_sequence = -1; +static int hf_ipmi_session_authcode = -1; + +/* IPMI message header */ +static int hf_ipmi_msg_len = -1; +static int hf_ipmi_msg_rsaddr = -1; +static int hf_ipmi_msg_nlfield = -1; +static int hf_ipmi_msg_netfn = -1; +static int hf_ipmi_msg_rqlun = -1; +static int hf_ipmi_msg_csum1 = -1; +static int hf_ipmi_msg_rqaddr = -1; +static int hf_ipmi_msg_slfield = -1; +static int hf_ipmi_msg_seq = -1; +static int hf_ipmi_msg_rslun = -1; +static int hf_ipmi_msg_cmd = -1; +static int hf_ipmi_msg_ccode = -1; +static int hf_ipmi_msg_csum2 = -1; + +static const value_string ipmi_netfn_vals[] = { + { 0x00, "Chassis Request" }, + { 0x01, "Chassis Response" }, + { 0x02, "Bridge Request" }, + { 0x03, "Bridge Response" }, + { 0x04, "Sensor/Event Request" }, + { 0x05, "Sensor/Event Response" }, + { 0x06, "Application Request" }, + { 0x07, "Application Response" }, + { 0x08, "Firmware Request" }, + { 0x09, "Frimware Response" }, + { 0x0a, "Storage Request" }, + { 0x0b, "Storage Response" }, + { 0x0c, "Transport Request" }, + { 0x0d, "Transport Response" }, + { 0x2c, "Group Extension Request" }, + { 0x2d, "Group Extension Response" }, + { 0x30, "OEM Request" }, + { 0x31, "OEM Response" }, + { 0x00, NULL }, +}; + +static const value_string ipmi_authtype_vals[] = { + { 0x00, "NONE" }, + { 0x01, "MD2" }, + { 0x02, "MD5" }, + { 0x04, "PASSWORD" }, + { 0x05, "OEM" }, + { 0x00, NULL } +}; + +static const value_string ipmi_ccode_vals[] = { + { 0x00, "Command completed normally" }, + { 0xc0, "Node busy" }, + { 0xc1, "Unrecognized or unsupported command" }, + { 0xc2, "Command invalid for given LUN" }, + { 0xc3, "Timeout while processing command" }, + { 0xc4, "Out of space" }, + { 0xc5, "Reservation cancelled or invalid reservation ID" }, + { 0xc6, "Request data truncated" }, + { 0xc7, "Request data length invalid" }, + { 0xc8, "Request data field length limit exceeded" }, + { 0xc9, "Parameter out of range" }, + { 0xca, "Cannot return number of requested data bytes" }, + { 0xcb, "Requested sensor, data, or record not present" }, + { 0xcc, "Invalid data field in request" }, + { 0xcd, "Command illegal for specified sensor or record type" }, + { 0xce, "Command response could not be provided" }, + { 0xcf, "Cannot execute duplicated request" }, + { 0xd0, "SDR repository in update mode" }, + { 0xd1, "Device in firmware update mode" }, + { 0xd2, "BMC initialization or initialization agent running" }, + { 0xd3, "Destination unavailable" }, + { 0xd4, "Insufficient privilege level" }, + { 0xd5, "Command or param not supported in present state" }, + { 0xff, "Unspecified error" }, + { 0x00, NULL }, +}; + +static const value_string ipmi_addr_vals[] = { + { 0x20, "BMC Slave Address" }, + { 0x81, "Remote Console Software ID" }, + { 0x00, NULL }, +}; + +static const value_string ipmi_chassis_cmd_vals[] = { + /* Chassis Device Commands */ + { 0x00, "Get Chassis Capabilities" }, + { 0x01, "Get Chassis Status" }, + { 0x02, "Chassis Control" }, + { 0x03, "Chassis Reset" }, + { 0x04, "Chassis Identify" }, + { 0x05, "Set Chassis Capabilities" }, + { 0x06, "Set Power Restore Policy" }, + { 0x07, "Get System Restart Cause" }, + { 0x08, "Set System Boot Options" }, + { 0x09, "Get System Boot Options" }, + { 0x0f, "Get POH Counter" }, + { 0x00, NULL }, +}; + +static const value_string ipmi_bridge_cmd_vals[] = { + /* ICMB Bridge Management Commands */ + { 0x00, "Get Bridge State" }, + { 0x01, "Set Bridge State" }, + { 0x02, "Get ICMB Address" }, + { 0x03, "Set ICMB Address" }, + { 0x04, "Set Bridge ProxyAddress" }, + { 0x05, "Get Bridge Statistics" }, + { 0x06, "Get ICMB Capabilities" }, + { 0x08, "Clear Bridge Statistics" }, + { 0x09, "Get Bridge Proxy Address" }, + { 0x0a, "Get ICMB Connector Info" }, + { 0x0b, "Get ICMB Connection ID" }, + { 0x0c, "Send ICMB Connection ID" }, + /* ICMB Discovery Commands */ + { 0x10, "Prepare For Discovery" }, + { 0x11, "Get Addresses" }, + { 0x12, "Set Discovered" }, + { 0x13, "Get Chassis Device ID" }, + { 0x14, "Set Chassis Device ID" }, + /* ICMB Bridging Commands */ + { 0x20, "Bridge Request" }, + { 0x21, "Bridge Message" }, + /* ICMB Event Commands */ + { 0x30, "Get Event Count" }, + { 0x31, "Set Event Destination" }, + { 0x32, "Set Event Reception State" }, + { 0x33, "Send ICMB Event Message" }, + { 0x34, "Get Event Destination" }, + { 0x35, "Get Event Recption State" }, + { 0x00, NULL }, +}; + +static const value_string ipmi_se_cmd_vals[] = { + /* Event Commands */ + { 0x00, "Set Event Receiver" }, + { 0x01, "Get Event Receiver" }, + { 0x02, "Platform Event Message" }, + /* PEF and Alerting Commands */ + { 0x10, "Get PEF Capabilities" }, + { 0x11, "Arm PEF Postpone Timer" }, + { 0x12, "Set PEF Config Params" }, + { 0x13, "Get PEF Config Params" }, + { 0x14, "Set Last Processed Event ID" }, + { 0x15, "Get Last Processed Event ID" }, + { 0x16, "Alert Immediate" }, + { 0x17, "PET Acknowledge" }, + /* Sensor Device Commands */ + { 0x20, "Get Device SDR Info" }, + { 0x21, "Get Device SDR" }, + { 0x22, "Reserve Device SDR Repository" }, + { 0x23, "Get Sensor Reading Factors" }, + { 0x24, "Set Sensor Hysteresis" }, + { 0x25, "Get Sensor Hysteresis" }, + { 0x26, "Set Sensor Threshold" }, + { 0x27, "Get Sensor Threshold" }, + { 0x28, "Set Sensor Event Enable" }, + { 0x29, "Get Sensor Event Enable" }, + { 0x2a, "Re-arm Sensor Events" }, + { 0x2b, "Get Sensor Event Status" }, + { 0x2d, "Get Sensor Reading" }, + { 0x2e, "Set Sensor Type" }, + { 0x2f, "Get Sensor Type" }, + { 0x00, NULL }, +}; + +static const value_string ipmi_storage_cmd_vals[] = { + /* FRU Device Commands */ + { 0x10, "Get FRU Inventory Area Info" }, + { 0x11, "Read FRU Data" }, + { 0x12, "Write FRU Data" }, + /* SDR Device Commands */ + { 0x20, "Get SDR Repository Info" }, + { 0x21, "Get SDR Repository Allocation Info" }, + { 0x22, "Reserve SDR Repository" }, + { 0x23, "Get SDR" }, + { 0x24, "Add SDR" }, + { 0x25, "Partial Add SDR" }, + { 0x26, "Delete SDR" }, + { 0x27, "Clear SDR Repository" }, + { 0x28, "Get SDR Repository Time" }, + { 0x29, "Set SDR Repository Time" }, + { 0x2a, "Enter SDR Repository Update Mode" }, + { 0x2b, "Exit SDR Repository Update Mode" }, + { 0x2c, "Run Initialization Agent" }, + /* SEL Device Commands */ + { 0x40, "Get SEL Info" }, + { 0x41, "Get SEL Allocation Info" }, + { 0x42, "Reserve SEL" }, + { 0x43, "Get SEL Entry" }, + { 0x44, "Add SEL Entry" }, + { 0x45, "Partial Add SEL Entry" }, + { 0x46, "Delete SEL Entry" }, + { 0x47, "Clear SEL" }, + { 0x48, "Get SEL Time" }, + { 0x49, "Set SEL Time" }, + { 0x5a, "Get Auxillary Log Status" }, + { 0x5b, "Set Auxillary Log Status" }, + { 0x00, NULL }, +}; + +static const value_string ipmi_transport_cmd_vals[] = { + /* LAN Device Commands */ + { 0x01, "Set LAN Config Param" }, + { 0x02, "Get LAN Config Param" }, + { 0x03, "Suspend BMC ARPs" }, + { 0x04, "Get IP/UDP/RMCP Statistics" }, + /* Serial/Modem Device Commands */ + { 0x10, "Set Serial/Modem Config" }, + { 0x11, "Get Serial/Modem Config" }, + { 0x12, "Get Serial/Modem Mux" }, + { 0x13, "Get TAP Response Codes" }, + { 0x14, "Set PPP UDP Proxy Transmit Data" }, + { 0x15, "Get PPP UDP Proxy Transmit Data" }, + { 0x16, "Send PPP UDP Proxy Packet" }, + { 0x17, "Get PPP UDP Proxy Data" }, + { 0x18, "Serial/Modem Connection Active" }, + { 0x19, "Callback" }, + { 0x1a, "Set User Callback Options" }, + { 0x1b, "Get User Callback Options" }, + { 0x00, NULL }, +}; + +static const value_string ipmi_app_cmd_vals[] = { + /* Device "Global" Commands */ + { 0x01, "Get Device ID" }, + { 0x02, "Cold Reset" }, + { 0x03, "Warm Reset" }, + { 0x04, "Get Self Test Results" }, + { 0x05, "Manufacturing Test On" }, + { 0x06, "Set ACPI Power State" }, + { 0x07, "Get ACPI Power State" }, + { 0x08, "Get Device GUID" }, + /* BMC Watchdog Timer Commands */ + { 0x22, "Reset Watchdog Timer" }, + { 0x24, "Set Watchdog Timer" }, + { 0x25, "Get Watchdog Timer" }, + /* BMC Device and Messaging Commands */ + { 0x2e, "Set BMC Global Enables" }, + { 0x2f, "Get BMC Global Enables" }, + { 0x30, "Clear Message Flags" }, + { 0x31, "Get Message Flags" }, + { 0x32, "Enable Message Channel Receive" }, + { 0x33, "Get Message" }, + { 0x34, "Send Message" }, + { 0x35, "Read Event Message Buffer" }, + { 0x36, "Get BT Interface Capabilities" }, + { 0x37, "Get System GUID" }, + { 0x38, "Get Channel Auth Capabilities" }, + { 0x39, "Get Session Challenge" }, + { 0x3a, "Activate Session" }, + { 0x3b, "Set Session Privilege Level" }, + { 0x3c, "Close Session" }, + { 0x3d, "Get Session Info" }, + { 0x3e, "unassigned" }, + { 0x3f, "Get AuthCode" }, + { 0x40, "Set Channel Access" }, + { 0x41, "Get Channel Access" }, + { 0x42, "Get Channel Info" }, + { 0x43, "Set User Access" }, + { 0x44, "Get User Access" }, + { 0x45, "Set User Name" }, + { 0x46, "Get User Name" }, + { 0x47, "Set User Password" }, + { 0x52, "Master Write-Read" }, + { 0x00, NULL }, +}; + +static const char * +get_netfn_cmd_text(guint8 netfn, guint8 cmd) +{ + switch (netfn) { + case 0x00: + case 0x01: + return val_to_str(cmd, ipmi_chassis_cmd_vals, "Unknown (0x%02x)"); + case 0x02: + case 0x03: + return val_to_str(cmd, ipmi_bridge_cmd_vals, "Unknown (0x%02x)"); + case 0x04: + case 0x05: + return val_to_str(cmd, ipmi_se_cmd_vals, "Unknown (0x%02x)"); + case 0x06: + case 0x07: + return val_to_str(cmd, ipmi_app_cmd_vals, "Unknown (0x%02x)"); + case 0x0a: + case 0x0b: + return val_to_str(cmd, ipmi_storage_cmd_vals, "Unknown (0x%02x)"); + case 0x0c: + case 0x0d: + return val_to_str(cmd, ipmi_transport_cmd_vals, "Unknown (0x%02x)"); + default: + return (netfn & 1) ? "Unknown Response" : "Unknown Request"; + } +} + +static void +dissect_ipmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *ipmi_tree = NULL, *field_tree = NULL; + proto_item *ti = NULL, *tf; + gint offset = 0; + tvbuff_t *next_tvb; + guint32 session_id; + guint8 authtype, netfn, cmd, ccode, len; + gint response; + + /* session authtype, 0=no authcode present */ + authtype = tvb_get_guint8(tvb, 0); + + /* session ID */ + session_id = tvb_get_letohl(tvb, 5); + + /* network function code */ + netfn = tvb_get_guint8(tvb, authtype ? 27 : 11) >> 2; + + /* bit 0 of netfn: even=request odd=response */ + response = netfn & 1; + + /* command */ + cmd = tvb_get_guint8(tvb, authtype ? 31 : 15); + + /* completion code */ + ccode = response ? tvb_get_guint8(tvb, authtype ? 32 : 16) : 0; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPMI"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + if (check_col(pinfo->cinfo, COL_INFO)) { + if (ccode) + col_add_fstr(pinfo->cinfo, COL_INFO, "%s, %s: %s", + get_netfn_cmd_text(netfn, cmd), + val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)"), + val_to_str(ccode, ipmi_ccode_vals, "Unknown (0x%02x)")); + else + col_add_fstr(pinfo->cinfo, COL_INFO, "%s, %s", + get_netfn_cmd_text(netfn, cmd), + val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)")); + } + + if (tree) { + ti = proto_tree_add_protocol_format(tree, proto_ipmi, + tvb, offset, authtype ? 32 : 16, + "Intelligent Platform Management Interface, " + "NetFn: %s (0x%02x), Cmd: %s (0x%02x)", + val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)"), + netfn, get_netfn_cmd_text(netfn, cmd), cmd); + ipmi_tree = proto_item_add_subtree(ti, ett_ipmi); + } + + /* ipmi session field */ + if (tree) { + tf = proto_tree_add_text(ipmi_tree, tvb, offset, + authtype ? 25 : 9, + "Session: ID 0x%08x (%d bytes)", + session_id, authtype ? 25 : 9); + field_tree = proto_item_add_subtree(tf, ett_ipmi_session); + proto_tree_add_item(field_tree, hf_ipmi_session_authtype, + tvb, offset++, 1, TRUE); + proto_tree_add_item(field_tree, hf_ipmi_session_sequence, + tvb, offset, 4, TRUE); + offset += 4; + proto_tree_add_item(field_tree, hf_ipmi_session_id, + tvb, offset, 4, TRUE); + offset += 4; + if (authtype) { + proto_tree_add_item(field_tree, hf_ipmi_session_authcode, + tvb, offset, 16, TRUE); + offset += 16; + } + } + + /* message length */ + if (tree) { + proto_tree_add_item(ipmi_tree, hf_ipmi_msg_len, + tvb, offset++, 1, TRUE); + } + + /* r[sq]addr */ + if (tree) { + proto_tree_add_item(ipmi_tree, + response ? hf_ipmi_msg_rqaddr : hf_ipmi_msg_rsaddr, + tvb, offset++, 1, TRUE); + } + + /* netfn/lun */ + if (tree) { + tf = proto_tree_add_text(ipmi_tree, tvb, offset, 1, + "NetFn/LUN: %s", val_to_str(netfn, + ipmi_netfn_vals, "Unknown (0x%02x)")); + + field_tree = proto_item_add_subtree(tf, ett_ipmi_msg_nlfield); + + proto_tree_add_item(field_tree, hf_ipmi_msg_netfn, + tvb, offset, 1, TRUE); + proto_tree_add_item(field_tree, + response ? hf_ipmi_msg_rqlun : hf_ipmi_msg_rslun, + tvb, offset, 1, TRUE); + offset += 1; + } + + /* checksum */ + if (tree) { + proto_tree_add_item(ipmi_tree, hf_ipmi_msg_csum1, + tvb, offset++, 1, TRUE); + } + + /* r[sq]addr */ + if (tree) { + proto_tree_add_item(ipmi_tree, + response ? hf_ipmi_msg_rsaddr : hf_ipmi_msg_rqaddr, + tvb, offset++, 1, TRUE); + } + + /* seq/lun */ + if (tree) { + tf = proto_tree_add_item(ipmi_tree, hf_ipmi_msg_slfield, + tvb, offset, 1, TRUE); + field_tree = proto_item_add_subtree(tf, ett_ipmi_msg_slfield); + + proto_tree_add_item(field_tree, hf_ipmi_msg_seq, + tvb, offset, 1, TRUE); + proto_tree_add_item(field_tree, + response ? hf_ipmi_msg_rslun : hf_ipmi_msg_rqlun, + tvb, offset, 1, TRUE); + offset += 1; + } + + /* command */ + if (tree) { + proto_tree_add_text(ipmi_tree, tvb, offset++, 1, + "Command: %s (0x%02x)", + get_netfn_cmd_text(netfn, cmd), cmd); + } + + /* completion code */ + if (tree && response) { + proto_tree_add_item(ipmi_tree, hf_ipmi_msg_ccode, + tvb, offset++, 1, TRUE); + } + + /* determine data length */ + len = tvb_get_guint8(tvb, authtype ? 25 : 9) - 7 - (response ? 1 : 0); + + /* dissect the data block */ + next_tvb = tvb_new_subset(tvb, offset, len, len); + call_dissector(data_handle, next_tvb, pinfo, tree); + offset += len; + + /* checksum 2 */ + if (tree) { + proto_tree_add_item(ipmi_tree, hf_ipmi_msg_csum2, + tvb, offset++, 1, TRUE); + } +} + +void +proto_register_ipmi(void) +{ + static hf_register_info hf_session[] = { + { &hf_ipmi_session_authtype, { + "Authentication Type", "ipmi.session.authtype", + FT_UINT8, BASE_HEX, VALS(ipmi_authtype_vals), 0, + "IPMI Authentication Type", HFILL }}, + { &hf_ipmi_session_sequence, { + "Session Sequence Number", "ipmi.session.sequence", + FT_UINT32, BASE_HEX, NULL, 0, + "IPMI Session Sequence Number", HFILL }}, + { &hf_ipmi_session_id, { + "Session ID", "ipmi.session.id", + FT_UINT32, BASE_HEX, NULL, 0, + "IPMI Session ID", HFILL }}, + { &hf_ipmi_session_authcode, { + "Authentication Code", "ipmi.session.authcode", + FT_BYTES, BASE_HEX, NULL, 0, + "IPMI Message Authentication Code", HFILL }}, + }; + static hf_register_info hf_msg[] = { + { &hf_ipmi_msg_len, { + "Message Length", "ipmi.msg.len", + FT_UINT8, BASE_DEC, NULL, 0, + "IPMI Message Length", HFILL }}, + { &hf_ipmi_msg_rsaddr, { + "Response Address", "ipmi.msg.rsaddr", + FT_UINT8, BASE_HEX, VALS(ipmi_addr_vals), 0, + "Responder's Slave Address", HFILL }}, + { &hf_ipmi_msg_csum1, { + "Checksum 1", "ipmi.msg.csum1", + FT_UINT8, BASE_HEX, NULL, 0, + "2s Complement Checksum", HFILL }}, + { &hf_ipmi_msg_rqaddr, { + "Request Address", "ipmi.msg.rqaddr", + FT_UINT8, BASE_HEX, VALS(ipmi_addr_vals), 0, + "Requester's Address (SA or SWID)", HFILL }}, + { &hf_ipmi_msg_cmd, { + "Command", "ipmi.msg.cmd", + FT_UINT8, BASE_HEX, NULL, 0, + "IPMI Command Byte", HFILL }}, + { &hf_ipmi_msg_ccode, { + "Completion Code", "ipmi.msg.ccode", + FT_UINT8, BASE_HEX, VALS(ipmi_ccode_vals), 0, + "Completion Code for Request", HFILL }}, + { &hf_ipmi_msg_csum2, { + "Checksum 2", "ipmi.msg.csum2", + FT_UINT8, BASE_HEX, NULL, 0, + "2s Complement Checksum", HFILL }}, + }; + static hf_register_info hf_msg_field[] = { + { &hf_ipmi_msg_nlfield, { + "NetFn/LUN", "ipmi.msg.nlfield", + FT_UINT8, BASE_HEX, NULL, 0, + "Network Function and LUN field", HFILL }}, + { &hf_ipmi_msg_netfn, { + "NetFn", "ipmi.msg.nlfield.netfn", + FT_UINT8, BASE_HEX, VALS(ipmi_netfn_vals), 0xfc, + "Network Function Code", HFILL }}, + { &hf_ipmi_msg_rqlun, { + "Request LUN", "ipmi.msg.nlfield.rqlun", + FT_UINT8, BASE_HEX, NULL, 0x03, + "Requester's Logical Unit Number", HFILL }}, + { &hf_ipmi_msg_slfield, { + "Seq/LUN", "ipmi.msg.slfield", + FT_UINT8, BASE_HEX, NULL, 0, + "Sequence and LUN field", HFILL }}, + { &hf_ipmi_msg_seq, { + "Sequence", "ipmi.msg.slfield.seq", + FT_UINT8, BASE_HEX, NULL, 0xfc, + "Sequence Number (requester)", HFILL }}, + { &hf_ipmi_msg_rslun, { + "Response LUN", "ipmi.msg.slfield.rslun", + FT_UINT8, BASE_HEX, NULL, 0x03, + "Responder's Logical Unit Number", HFILL }}, + }; + static gint *ett[] = { + &ett_ipmi, + &ett_ipmi_session, + &ett_ipmi_msg_nlfield, + &ett_ipmi_msg_slfield, + }; + + proto_ipmi = proto_register_protocol( + "Intelligent Platform Management Interface", "IPMI", "ipmi"); + + proto_register_field_array(proto_ipmi, hf_session, + array_length(hf_session)); + proto_register_field_array(proto_ipmi, hf_msg, + array_length(hf_msg)); + proto_register_field_array(proto_ipmi, hf_msg_field, + array_length(hf_msg_field)); + + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("ipmi", dissect_ipmi, proto_ipmi); +} + +void +proto_reg_handoff_ipmi(void) +{ + dissector_handle_t ipmi_handle; + ipmi_handle = create_dissector_handle(dissect_ipmi, proto_ipmi); + dissector_add("rmcp.class", RMCP_CLASS_IPMI, ipmi_handle); + data_handle = find_dissector("data"); +} diff --git a/packet-rmcp.c b/packet-rmcp.c new file mode 100644 index 0000000000..1f083cf69a --- /dev/null +++ b/packet-rmcp.c @@ -0,0 +1,189 @@ +/* packet-rmcp.c + * Routines for RMCP packet dissection + * + * Duncan Laurie <duncan@sun.com> + * + * $Id: packet-rmcp.c,v 1.1 2003/04/23 00:24:36 guy Exp $ + * + * Ethereal - Network traffic analyzer + * By Gerald Combs <gerald@ethereal.com> + * Copyright 1998 Gerald Combs + * + * Copied from packet-tftp.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <glib.h> +#include <epan/packet.h> + +/* + * See + * + * http://www.dmtf.org/standards/standard_alert.php + * + * (the ASF specification includes RMCP) + */ + +static int proto_rmcp = -1; +static int hf_rmcp_version = -1; +static int hf_rmcp_sequence = -1; +static int hf_rmcp_class = -1; +static int hf_rmcp_type = -1; + +static gint ett_rmcp = -1; +static gint ett_rmcp_typeclass = -1; + +static dissector_handle_t asf_handle; +static dissector_handle_t ipmi_handle; +static dissector_table_t rmcp_dissector_table; + +#define UDP_PORT_RMCP 623 +#define UDP_PORT_RMCP_SECURE 664 + +#define RMCP_TYPE_MASK 0x80 +#define RMCP_TYPE_NORM 0x00 +#define RMCP_TYPE_ACK 0x01 + +static const value_string rmcp_type_vals[] = { + { RMCP_TYPE_NORM, "Normal RMCP" }, + { RMCP_TYPE_ACK, "RMCP ACK" }, + { 0, NULL } +}; + +#define RMCP_CLASS_MASK 0x1f +#define RMCP_CLASS_ASF 0x06 +#define RMCP_CLASS_IPMI 0x07 +#define RMCP_CLASS_OEM 0x08 + +static const value_string rmcp_class_vals[] = { + { RMCP_CLASS_ASF, "ASF" }, + { RMCP_CLASS_IPMI, "IPMI" }, + { RMCP_CLASS_OEM, "OEM" }, + { 0, NULL } +}; + +static void +dissect_rmcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_tree *rmcp_tree = NULL, *field_tree; + proto_item *ti, *tf; + tvbuff_t *next_tvb; + guint8 class; + guint8 type; + + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "RMCP"); + if (check_col(pinfo->cinfo, COL_INFO)) + col_clear(pinfo->cinfo, COL_INFO); + + /* check RMCP class for normal/ack bit */ + class = tvb_get_guint8(tvb, 3); + type = (class & RMCP_TYPE_MASK) >> 7; + class &= RMCP_CLASS_MASK; + + if (check_col(pinfo->cinfo, COL_INFO)) + col_add_fstr(pinfo->cinfo, COL_INFO, "%s, Class: %s", + val_to_str(type, rmcp_type_vals, "Unknown (0x%02x)"), + val_to_str(class, rmcp_class_vals, "Unknown (0x%02x)")); + + if (tree) { + ti = proto_tree_add_protocol_format(tree, proto_rmcp, tvb, 0, 4, + "Remote Management Control Protocol, Class: %s", + val_to_str(class, rmcp_class_vals, "Unknown (0x%02x)")); + rmcp_tree = proto_item_add_subtree(ti, ett_rmcp); + + proto_tree_add_item(rmcp_tree, hf_rmcp_version, tvb, 0, 1, TRUE); + proto_tree_add_item(rmcp_tree, hf_rmcp_sequence, tvb, 2, 1, TRUE); + + tf = proto_tree_add_text(rmcp_tree, tvb, 3, 1, "Type: %s, Class: %s", + val_to_str(type, rmcp_type_vals, "Unknown (0x%02)"), + val_to_str(class, rmcp_class_vals, "Unknown (0x%02)")); + + field_tree = proto_item_add_subtree(tf, ett_rmcp_typeclass); + + proto_tree_add_item(field_tree, hf_rmcp_class, tvb, 3, 1, TRUE); + proto_tree_add_item(field_tree, hf_rmcp_type, tvb, 3, 1, TRUE); + } + + next_tvb = tvb_new_subset(tvb, 4, -1, -1); + + switch (class) { + case RMCP_CLASS_ASF: + call_dissector(asf_handle, next_tvb, pinfo, tree); + break; + case RMCP_CLASS_IPMI: + call_dissector(ipmi_handle, next_tvb, pinfo, tree); + break; + default: + break; + } +} + +void +proto_register_rmcp(void) +{ + static hf_register_info hf[] = { + { &hf_rmcp_version, { + "Version", "rmcp.version", + FT_UINT8, BASE_HEX, NULL, 0, + "RMCP Version", HFILL }}, + { &hf_rmcp_sequence, { + "Sequence", "rmcp.sequence", + FT_UINT8, BASE_HEX, NULL, 0, + "RMCP Sequence", HFILL }}, + { &hf_rmcp_class, { + "Class", "rmcp.class", + FT_UINT8, BASE_HEX, + VALS(rmcp_class_vals), RMCP_CLASS_MASK, + "RMCP Class", HFILL }}, + { &hf_rmcp_type, { + "Message Type", "rmcp.type", + FT_UINT8, BASE_HEX, + VALS(rmcp_type_vals), RMCP_TYPE_MASK, + "RMCP Message Type", HFILL }}, + }; + static gint *ett[] = { + &ett_rmcp, + &ett_rmcp_typeclass, + }; + + proto_rmcp = proto_register_protocol( + "Remote Management Control Protocol", "RMCP", "rmcp"); + + proto_register_field_array(proto_rmcp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + register_dissector("rmcp", dissect_rmcp, proto_rmcp); + + rmcp_dissector_table = register_dissector_table( + "rmcp.class", "RMCP Class", FT_UINT8, BASE_HEX); +} + +void +proto_reg_handoff_rmcp(void) +{ + dissector_handle_t rmcp_handle; + rmcp_handle = create_dissector_handle(dissect_rmcp, proto_rmcp); + ipmi_handle = find_dissector("ipmi"); + asf_handle = find_dissector("asf"); + dissector_add("udp.port", UDP_PORT_RMCP, rmcp_handle); + dissector_add("udp.port", UDP_PORT_RMCP_SECURE, rmcp_handle); +} |