The current year is 2004
[obnox/wireshark/wip.git] / packet-ipmi.c
1 /* packet-ipmi.c
2  * Routines for IPMI-over-LAN packet dissection
3  *
4  * Duncan Laurie <duncan@sun.com>
5  *
6  * $Id: packet-ipmi.c,v 1.4 2003/12/13 01:08:32 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from packet-rmcp.c
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27  * 02111-1307, USA.
28  *
29  *
30  * See the IPMI spec at
31  *
32  *      http://www.intel.com/design/servers/ipmi/
33  *
34  * IPMI LAN Message Request
35  *  ipmi.session.authtype
36  *  ipmi.session.sequence
37  *  ipmi.session.id
38  * [ipmi.session.authcode]
39  *  ipmi.msg.len
40  *  ipmi.msg.rsaddr
41  *  ipmi.msg.netfn << 2 | ipmi.msg.rslun
42  *  ipmi.msg.csum1
43  *  ipmi.msg.rqaddr
44  *  ipmi.msg.seq << 2 | ipmi.msg.rqlun
45  *  ipmi.msg.cmd
46  *  ipmi.msg.DATA
47  *  ipmi.msg.csum2
48  *
49  * IPMI LAN Message Response
50  *  ipmi.session.authtype
51  *  ipmi.session.sequence
52  *  ipmi.session.id
53  * [ipmi.session.authcode]
54  *  ipmi.msg.len
55  *  ipmi.msg.rqaddr
56  *  ipmi.msg.netfn << 2 | ipmi.msg.rqlun
57  *  ipmi.msg.csum1
58  *  ipmi.msg.rsaddr
59  *  ipmi.msg.seq << 2 | ipmi.msg.rslun
60  *  ipmi.msg.cmd
61  *  ipmi.msg.ccode
62  *  ipmi.msg.DATA
63  *  ipmi.msg.csum2
64  */
65
66 #ifdef HAVE_CONFIG_H
67 # include "config.h"
68 #endif
69
70 #include <glib.h>
71 #include <epan/packet.h>
72
73 #define RMCP_CLASS_IPMI 0x07
74
75 static dissector_handle_t data_handle;
76 static int proto_ipmi = -1;
77
78 static gint ett_ipmi = -1;
79 static gint ett_ipmi_session = -1;
80 static gint ett_ipmi_msg_nlfield = -1;
81 static gint ett_ipmi_msg_slfield = -1;
82
83 /* IPMI session header */
84 static int hf_ipmi_session_id = -1;
85 static int hf_ipmi_session_authtype = -1;
86 static int hf_ipmi_session_sequence = -1;
87 static int hf_ipmi_session_authcode = -1;
88
89 /* IPMI message header */
90 static int hf_ipmi_msg_len = -1;
91 static int hf_ipmi_msg_rsaddr = -1;
92 static int hf_ipmi_msg_nlfield = -1;
93 static int hf_ipmi_msg_netfn = -1;
94 static int hf_ipmi_msg_rqlun = -1;
95 static int hf_ipmi_msg_csum1 = -1;
96 static int hf_ipmi_msg_rqaddr = -1;
97 static int hf_ipmi_msg_slfield = -1;
98 static int hf_ipmi_msg_seq = -1;
99 static int hf_ipmi_msg_rslun = -1;
100 static int hf_ipmi_msg_cmd = -1;
101 static int hf_ipmi_msg_ccode = -1;
102 static int hf_ipmi_msg_csum2 = -1;
103
104 static const value_string ipmi_netfn_vals[] = {
105         { 0x00, "Chassis Request" },
106         { 0x01, "Chassis Response" },
107         { 0x02, "Bridge Request" },
108         { 0x03, "Bridge Response" },
109         { 0x04, "Sensor/Event Request" },
110         { 0x05, "Sensor/Event Response" },
111         { 0x06, "Application Request" },
112         { 0x07, "Application Response" },
113         { 0x08, "Firmware Request" },
114         { 0x09, "Frimware Response" },
115         { 0x0a, "Storage Request" },
116         { 0x0b, "Storage Response" },
117         { 0x0c, "Transport Request" },
118         { 0x0d, "Transport Response" },
119         { 0x2c, "Group Extension Request" },
120         { 0x2d, "Group Extension Response" },
121         { 0x30, "OEM Request" },
122         { 0x31, "OEM Response" },
123         { 0x00, NULL },
124 };
125
126 static const value_string ipmi_authtype_vals[] = {
127         { 0x00, "NONE" },
128         { 0x01, "MD2" },
129         { 0x02, "MD5" },
130         { 0x04, "PASSWORD" },
131         { 0x05, "OEM" },
132         { 0x00, NULL }
133 };
134
135 static const value_string ipmi_ccode_vals[] = {
136         { 0x00, "Command completed normally" },
137         { 0xc0, "Node busy" },
138         { 0xc1, "Unrecognized or unsupported command" },
139         { 0xc2, "Command invalid for given LUN" },
140         { 0xc3, "Timeout while processing command" },
141         { 0xc4, "Out of space" },
142         { 0xc5, "Reservation cancelled or invalid reservation ID" },
143         { 0xc6, "Request data truncated" },
144         { 0xc7, "Request data length invalid" },
145         { 0xc8, "Request data field length limit exceeded" },
146         { 0xc9, "Parameter out of range" },
147         { 0xca, "Cannot return number of requested data bytes" },
148         { 0xcb, "Requested sensor, data, or record not present" },
149         { 0xcc, "Invalid data field in request" },
150         { 0xcd, "Command illegal for specified sensor or record type" },
151         { 0xce, "Command response could not be provided" },
152         { 0xcf, "Cannot execute duplicated request" },
153         { 0xd0, "SDR repository in update mode" },
154         { 0xd1, "Device in firmware update mode" },
155         { 0xd2, "BMC initialization or initialization agent running" },
156         { 0xd3, "Destination unavailable" },
157         { 0xd4, "Insufficient privilege level" },
158         { 0xd5, "Command or param not supported in present state" },
159         { 0xff, "Unspecified error" },
160         { 0x00, NULL },
161 };
162
163 static const value_string ipmi_addr_vals[] = {
164         { 0x20, "BMC Slave Address" },
165         { 0x81, "Remote Console Software ID" },
166         { 0x00, NULL },
167 };
168
169 static const value_string ipmi_chassis_cmd_vals[] = {
170         /* Chassis Device Commands */
171         { 0x00, "Get Chassis Capabilities" },
172         { 0x01, "Get Chassis Status" },
173         { 0x02, "Chassis Control" },
174         { 0x03, "Chassis Reset" },
175         { 0x04, "Chassis Identify" },
176         { 0x05, "Set Chassis Capabilities" },
177         { 0x06, "Set Power Restore Policy" },
178         { 0x07, "Get System Restart Cause" },
179         { 0x08, "Set System Boot Options" },
180         { 0x09, "Get System Boot Options" },
181         { 0x0f, "Get POH Counter" },
182         { 0x00, NULL },
183 };
184
185 static const value_string ipmi_bridge_cmd_vals[] = {
186         /* ICMB Bridge Management Commands */
187         { 0x00, "Get Bridge State" },
188         { 0x01, "Set Bridge State" },
189         { 0x02, "Get ICMB Address" },
190         { 0x03, "Set ICMB Address" },
191         { 0x04, "Set Bridge ProxyAddress" },
192         { 0x05, "Get Bridge Statistics" },
193         { 0x06, "Get ICMB Capabilities" },
194         { 0x08, "Clear Bridge Statistics" },
195         { 0x09, "Get Bridge Proxy Address" },
196         { 0x0a, "Get ICMB Connector Info" },
197         { 0x0b, "Get ICMB Connection ID" },
198         { 0x0c, "Send ICMB Connection ID" },
199         /* ICMB Discovery Commands */
200         { 0x10, "Prepare For Discovery" },
201         { 0x11, "Get Addresses" },
202         { 0x12, "Set Discovered" },
203         { 0x13, "Get Chassis Device ID" },
204         { 0x14, "Set Chassis Device ID" },
205         /* ICMB Bridging Commands */
206         { 0x20, "Bridge Request" },
207         { 0x21, "Bridge Message" },
208         /* ICMB Event Commands */
209         { 0x30, "Get Event Count" },
210         { 0x31, "Set Event Destination" },
211         { 0x32, "Set Event Reception State" },
212         { 0x33, "Send ICMB Event Message" },
213         { 0x34, "Get Event Destination" },
214         { 0x35, "Get Event Reception State" },
215         { 0x00, NULL },
216 };
217
218 static const value_string ipmi_se_cmd_vals[] = {
219         /* Event Commands */
220         { 0x00, "Set Event Receiver" },
221         { 0x01, "Get Event Receiver" },
222         { 0x02, "Platform Event Message" },
223         /* PEF and Alerting Commands */
224         { 0x10, "Get PEF Capabilities" },
225         { 0x11, "Arm PEF Postpone Timer" },
226         { 0x12, "Set PEF Config Params" },
227         { 0x13, "Get PEF Config Params" },
228         { 0x14, "Set Last Processed Event ID" },
229         { 0x15, "Get Last Processed Event ID" },
230         { 0x16, "Alert Immediate" },
231         { 0x17, "PET Acknowledge" },
232         /* Sensor Device Commands */
233         { 0x20, "Get Device SDR Info" },
234         { 0x21, "Get Device SDR" },
235         { 0x22, "Reserve Device SDR Repository" },
236         { 0x23, "Get Sensor Reading Factors" },
237         { 0x24, "Set Sensor Hysteresis" },
238         { 0x25, "Get Sensor Hysteresis" },
239         { 0x26, "Set Sensor Threshold" },
240         { 0x27, "Get Sensor Threshold" },
241         { 0x28, "Set Sensor Event Enable" },
242         { 0x29, "Get Sensor Event Enable" },
243         { 0x2a, "Re-arm Sensor Events" },
244         { 0x2b, "Get Sensor Event Status" },
245         { 0x2d, "Get Sensor Reading" },
246         { 0x2e, "Set Sensor Type" },
247         { 0x2f, "Get Sensor Type" },
248         { 0x00, NULL },
249 };
250
251 static const value_string ipmi_storage_cmd_vals[] = {
252         /* FRU Device Commands */
253         { 0x10, "Get FRU Inventory Area Info" },
254         { 0x11, "Read FRU Data" },
255         { 0x12, "Write FRU Data" },
256         /* SDR Device Commands */
257         { 0x20, "Get SDR Repository Info" },
258         { 0x21, "Get SDR Repository Allocation Info" },
259         { 0x22, "Reserve SDR Repository" },
260         { 0x23, "Get SDR" },
261         { 0x24, "Add SDR" },
262         { 0x25, "Partial Add SDR" },
263         { 0x26, "Delete SDR" },
264         { 0x27, "Clear SDR Repository" },
265         { 0x28, "Get SDR Repository Time" },
266         { 0x29, "Set SDR Repository Time" },
267         { 0x2a, "Enter SDR Repository Update Mode" },
268         { 0x2b, "Exit SDR Repository Update Mode" },
269         { 0x2c, "Run Initialization Agent" },
270         /* SEL Device Commands */
271         { 0x40, "Get SEL Info" },
272         { 0x41, "Get SEL Allocation Info" },
273         { 0x42, "Reserve SEL" },
274         { 0x43, "Get SEL Entry" },
275         { 0x44, "Add SEL Entry" },
276         { 0x45, "Partial Add SEL Entry" },
277         { 0x46, "Delete SEL Entry" },
278         { 0x47, "Clear SEL" },
279         { 0x48, "Get SEL Time" },
280         { 0x49, "Set SEL Time" },
281         { 0x5a, "Get Auxillary Log Status" },
282         { 0x5b, "Set Auxillary Log Status" },
283         { 0x00, NULL },
284 };
285
286 static const value_string ipmi_transport_cmd_vals[] = {
287         /* LAN Device Commands */
288         { 0x01, "Set LAN Config Param" },
289         { 0x02, "Get LAN Config Param" },
290         { 0x03, "Suspend BMC ARPs" },
291         { 0x04, "Get IP/UDP/RMCP Statistics" },
292         /* Serial/Modem Device Commands */
293         { 0x10, "Set Serial/Modem Config" },
294         { 0x11, "Get Serial/Modem Config" },
295         { 0x12, "Get Serial/Modem Mux" },
296         { 0x13, "Get TAP Response Codes" },
297         { 0x14, "Set PPP UDP Proxy Transmit Data" },
298         { 0x15, "Get PPP UDP Proxy Transmit Data" },
299         { 0x16, "Send PPP UDP Proxy Packet" },
300         { 0x17, "Get PPP UDP Proxy Data" },
301         { 0x18, "Serial/Modem Connection Active" },
302         { 0x19, "Callback" },
303         { 0x1a, "Set User Callback Options" },
304         { 0x1b, "Get User Callback Options" },
305         { 0x00, NULL },
306 };
307
308 static const value_string ipmi_app_cmd_vals[] = {
309         /* Device "Global" Commands */
310         { 0x01, "Get Device ID" },
311         { 0x02, "Cold Reset" },
312         { 0x03, "Warm Reset" },
313         { 0x04, "Get Self Test Results" },
314         { 0x05, "Manufacturing Test On" },
315         { 0x06, "Set ACPI Power State" },
316         { 0x07, "Get ACPI Power State" },
317         { 0x08, "Get Device GUID" },
318         /* BMC Watchdog Timer Commands */
319         { 0x22, "Reset Watchdog Timer" },
320         { 0x24, "Set Watchdog Timer" },
321         { 0x25, "Get Watchdog Timer" },
322         /* BMC Device and Messaging Commands */
323         { 0x2e, "Set BMC Global Enables" },
324         { 0x2f, "Get BMC Global Enables" },
325         { 0x30, "Clear Message Flags" },
326         { 0x31, "Get Message Flags" },
327         { 0x32, "Enable Message Channel Receive" },
328         { 0x33, "Get Message" },
329         { 0x34, "Send Message" },
330         { 0x35, "Read Event Message Buffer" },
331         { 0x36, "Get BT Interface Capabilities" },
332         { 0x37, "Get System GUID" },
333         { 0x38, "Get Channel Auth Capabilities" },
334         { 0x39, "Get Session Challenge" },
335         { 0x3a, "Activate Session" },
336         { 0x3b, "Set Session Privilege Level" },
337         { 0x3c, "Close Session" },
338         { 0x3d, "Get Session Info" },
339         { 0x3e, "unassigned" },
340         { 0x3f, "Get AuthCode" },
341         { 0x40, "Set Channel Access" },
342         { 0x41, "Get Channel Access" },
343         { 0x42, "Get Channel Info" },
344         { 0x43, "Set User Access" },
345         { 0x44, "Get User Access" },
346         { 0x45, "Set User Name" },
347         { 0x46, "Get User Name" },
348         { 0x47, "Set User Password" },
349         { 0x52, "Master Write-Read" },
350         { 0x00, NULL },
351 };
352
353 static const char *
354 get_netfn_cmd_text(guint8 netfn, guint8 cmd)
355 {
356         switch (netfn) {
357         case 0x00:
358         case 0x01:
359                 return val_to_str(cmd, ipmi_chassis_cmd_vals, "Unknown (0x%02x)");
360         case 0x02:
361         case 0x03:
362                 return val_to_str(cmd, ipmi_bridge_cmd_vals, "Unknown (0x%02x)");
363         case 0x04:
364         case 0x05:
365                 return val_to_str(cmd, ipmi_se_cmd_vals, "Unknown (0x%02x)");
366         case 0x06:
367         case 0x07:
368                 return val_to_str(cmd, ipmi_app_cmd_vals, "Unknown (0x%02x)");
369         case 0x0a:
370         case 0x0b:
371                 return val_to_str(cmd, ipmi_storage_cmd_vals, "Unknown (0x%02x)");
372         case 0x0c:
373         case 0x0d:
374                 return val_to_str(cmd, ipmi_transport_cmd_vals, "Unknown (0x%02x)");
375         default:
376                 return (netfn & 1) ? "Unknown Response" : "Unknown Request";
377         }
378 }
379
380 static void
381 dissect_ipmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
382 {
383         proto_tree      *ipmi_tree = NULL, *field_tree = NULL;
384         proto_item      *ti = NULL, *tf;
385         gint            offset = 0;
386         tvbuff_t        *next_tvb;
387         guint32         session_id;
388         guint8          authtype, netfn, cmd, ccode, len;
389         gint            response;
390
391         /* session authtype, 0=no authcode present */
392         authtype = tvb_get_guint8(tvb, 0);
393
394         /* session ID */
395         session_id = tvb_get_letohl(tvb, 5);
396
397         /* network function code */
398         netfn = tvb_get_guint8(tvb, authtype ? 27 : 11) >> 2;
399
400         /* bit 0 of netfn: even=request odd=response */
401         response =  netfn & 1;
402
403         /* command */
404         cmd = tvb_get_guint8(tvb, authtype ? 31 : 15);
405
406         /* completion code */
407         ccode = response ? tvb_get_guint8(tvb, authtype ? 32 : 16) : 0;
408
409         if (check_col(pinfo->cinfo, COL_PROTOCOL))
410                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "IPMI");
411         if (check_col(pinfo->cinfo, COL_INFO))
412                 col_clear(pinfo->cinfo, COL_INFO);
413         if (check_col(pinfo->cinfo, COL_INFO)) {
414                 if (ccode)
415                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s, %s: %s",
416                              get_netfn_cmd_text(netfn, cmd),
417                              val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)"),
418                              val_to_str(ccode, ipmi_ccode_vals, "Unknown (0x%02x)"));
419                 else
420                         col_add_fstr(pinfo->cinfo, COL_INFO, "%s, %s",
421                              get_netfn_cmd_text(netfn, cmd),
422                              val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)"));
423         }
424
425         if (tree) {
426                 ti = proto_tree_add_protocol_format(tree, proto_ipmi,
427                             tvb, offset, authtype ? 32 : 16,
428                             "Intelligent Platform Management Interface, "
429                             "NetFn: %s (0x%02x), Cmd: %s (0x%02x)",
430                             val_to_str(netfn, ipmi_netfn_vals, "Unknown (0x%02x)"),
431                             netfn, get_netfn_cmd_text(netfn, cmd), cmd);
432                 ipmi_tree = proto_item_add_subtree(ti, ett_ipmi);
433         }
434
435         /* ipmi session field */
436         if (tree) {
437                 tf = proto_tree_add_text(ipmi_tree, tvb, offset,
438                                  authtype ? 25 : 9,
439                                  "Session: ID 0x%08x (%d bytes)",
440                                  session_id, authtype ? 25 : 9);
441                 field_tree = proto_item_add_subtree(tf, ett_ipmi_session);
442                 proto_tree_add_item(field_tree, hf_ipmi_session_authtype,
443                             tvb, offset++, 1, TRUE);
444                 proto_tree_add_item(field_tree, hf_ipmi_session_sequence,
445                             tvb, offset, 4, TRUE);
446                 offset += 4;
447                 proto_tree_add_item(field_tree, hf_ipmi_session_id,
448                             tvb, offset, 4, TRUE);
449                 offset += 4;
450                 if (authtype) {
451                         proto_tree_add_item(field_tree, hf_ipmi_session_authcode,
452                                     tvb, offset, 16, TRUE);
453                         offset += 16;
454                 }
455         }
456
457         /* message length */
458         if (tree) {
459                 proto_tree_add_item(ipmi_tree, hf_ipmi_msg_len,
460                             tvb, offset++, 1, TRUE);
461         }
462
463         /* r[sq]addr */
464         if (tree) {
465                 proto_tree_add_item(ipmi_tree,
466                             response ? hf_ipmi_msg_rqaddr : hf_ipmi_msg_rsaddr,
467                             tvb, offset++, 1, TRUE);
468         }
469
470         /* netfn/lun */
471         if (tree) {
472                 guint8 lun;
473
474                 tf = proto_tree_add_text(ipmi_tree, tvb, offset, 1,
475                          "NetFn/LUN: %s (0x%02x)", val_to_str(netfn,
476                          ipmi_netfn_vals, "Unknown (0x%02x)"),
477                          netfn);
478
479                 field_tree = proto_item_add_subtree(tf, ett_ipmi_msg_nlfield);
480
481                 proto_tree_add_item(field_tree, hf_ipmi_msg_netfn,
482                                     tvb, offset, 1, TRUE);
483                 proto_tree_add_item(field_tree,
484                                     response ? hf_ipmi_msg_rqlun : hf_ipmi_msg_rslun,
485                                     tvb, offset, 1, TRUE);
486                 lun = tvb_get_guint8(tvb, offset);
487                 proto_item_append_text(tf, ", LUN 0x%02x", lun);
488                 offset += 1;
489         }
490
491         /* checksum */
492         if (tree) {
493                 proto_tree_add_item(ipmi_tree, hf_ipmi_msg_csum1,
494                                     tvb, offset++, 1, TRUE);
495         }
496
497         /* r[sq]addr */
498         if (tree) {
499                 proto_tree_add_item(ipmi_tree,
500                                     response ? hf_ipmi_msg_rsaddr : hf_ipmi_msg_rqaddr,
501                                     tvb, offset++, 1, TRUE);
502         }
503
504         /* seq/lun */
505         if (tree) {
506                 guint8 lun;
507
508                 tf = proto_tree_add_item(ipmi_tree, hf_ipmi_msg_slfield,
509                                          tvb, offset, 1, TRUE);
510                 field_tree = proto_item_add_subtree(tf, ett_ipmi_msg_slfield);
511
512                 proto_tree_add_item(field_tree, hf_ipmi_msg_seq,
513                                     tvb, offset, 1, TRUE);
514                 proto_tree_add_item(field_tree,
515                                     response ? hf_ipmi_msg_rslun : hf_ipmi_msg_rqlun,
516                                     tvb, offset, 1, TRUE);
517                 lun = tvb_get_guint8(tvb, offset);
518                 proto_item_append_text(tf, ", LUN 0x%02x", lun);
519                 offset += 1;
520         }
521
522         /* command */
523         if (tree) {
524                 proto_tree_add_text(ipmi_tree, tvb, offset++, 1,
525                                     "Command: %s (0x%02x)",
526                                     get_netfn_cmd_text(netfn, cmd), cmd);
527         }
528
529         /* completion code */
530         if (tree && response) {
531                 proto_tree_add_item(ipmi_tree, hf_ipmi_msg_ccode,
532                                     tvb, offset++, 1, TRUE);
533         }
534
535         /* determine data length */
536         len = tvb_get_guint8(tvb, authtype ? 25 : 9) - 7 - (response ? 1 : 0);
537
538         /* dissect the data block */
539         next_tvb = tvb_new_subset(tvb, offset, len, len);
540         call_dissector(data_handle, next_tvb, pinfo, tree);
541         offset += len;
542
543         /* checksum 2 */
544         if (tree) {
545                 proto_tree_add_item(ipmi_tree, hf_ipmi_msg_csum2,
546                                     tvb, offset++, 1, TRUE);
547         }
548 }
549
550 void
551 proto_register_ipmi(void)
552 {
553         static hf_register_info hf_session[] = {
554                 { &hf_ipmi_session_authtype, {
555                         "Authentication Type", "ipmi.session.authtype",
556                         FT_UINT8, BASE_HEX, VALS(ipmi_authtype_vals), 0,
557                         "IPMI Authentication Type", HFILL }},
558                 { &hf_ipmi_session_sequence, {
559                         "Session Sequence Number", "ipmi.session.sequence",
560                         FT_UINT32, BASE_HEX, NULL, 0,
561                         "IPMI Session Sequence Number", HFILL }},
562                 { &hf_ipmi_session_id, {
563                         "Session ID", "ipmi.session.id",
564                         FT_UINT32, BASE_HEX, NULL, 0,
565                         "IPMI Session ID", HFILL }},
566                 { &hf_ipmi_session_authcode, {
567                         "Authentication Code", "ipmi.session.authcode",
568                         FT_BYTES, BASE_HEX, NULL, 0,
569                         "IPMI Message Authentication Code", HFILL }},
570         };
571         static hf_register_info hf_msg[] = {
572                 { &hf_ipmi_msg_len, {
573                         "Message Length", "ipmi.msg.len",
574                         FT_UINT8, BASE_DEC, NULL, 0,
575                         "IPMI Message Length", HFILL }},
576                 { &hf_ipmi_msg_rsaddr, {
577                         "Response Address", "ipmi.msg.rsaddr",
578                         FT_UINT8, BASE_HEX, VALS(ipmi_addr_vals), 0,
579                         "Responder's Slave Address", HFILL }},
580                 { &hf_ipmi_msg_csum1, {
581                         "Checksum 1", "ipmi.msg.csum1",
582                         FT_UINT8, BASE_HEX, NULL, 0,
583                         "2s Complement Checksum", HFILL }},
584                 { &hf_ipmi_msg_rqaddr, {
585                         "Request Address", "ipmi.msg.rqaddr",
586                         FT_UINT8, BASE_HEX, VALS(ipmi_addr_vals), 0,
587                         "Requester's Address (SA or SWID)", HFILL }},
588                 { &hf_ipmi_msg_cmd, {
589                         "Command", "ipmi.msg.cmd",
590                         FT_UINT8, BASE_HEX, NULL, 0,
591                         "IPMI Command Byte", HFILL }},
592                 { &hf_ipmi_msg_ccode, {
593                         "Completion Code", "ipmi.msg.ccode",
594                         FT_UINT8, BASE_HEX, VALS(ipmi_ccode_vals), 0,
595                         "Completion Code for Request", HFILL }},
596                 { &hf_ipmi_msg_csum2, {
597                         "Checksum 2", "ipmi.msg.csum2",
598                         FT_UINT8, BASE_HEX, NULL, 0,
599                         "2s Complement Checksum", HFILL }},
600         };
601         static hf_register_info hf_msg_field[] = {
602                 { &hf_ipmi_msg_nlfield, {
603                         "NetFn/LUN", "ipmi.msg.nlfield",
604                         FT_UINT8, BASE_HEX, NULL, 0,
605                         "Network Function and LUN field", HFILL }},
606                 { &hf_ipmi_msg_netfn, {
607                         "NetFn", "ipmi.msg.nlfield.netfn",
608                         FT_UINT8, BASE_HEX, VALS(ipmi_netfn_vals), 0xfc,
609                         "Network Function Code", HFILL }},
610                 { &hf_ipmi_msg_rqlun, {
611                         "Request LUN", "ipmi.msg.nlfield.rqlun",
612                         FT_UINT8, BASE_HEX, NULL, 0x03,
613                         "Requester's Logical Unit Number", HFILL }},
614                 { &hf_ipmi_msg_slfield, {
615                         "Seq/LUN", "ipmi.msg.slfield",
616                         FT_UINT8, BASE_HEX, NULL, 0,
617                         "Sequence and LUN field", HFILL }},
618                 { &hf_ipmi_msg_seq, {
619                         "Sequence", "ipmi.msg.slfield.seq",
620                         FT_UINT8, BASE_HEX, NULL, 0xfc,
621                         "Sequence Number (requester)", HFILL }},
622                 { &hf_ipmi_msg_rslun, {
623                         "Response LUN", "ipmi.msg.slfield.rslun",
624                         FT_UINT8, BASE_HEX, NULL, 0x03,
625                         "Responder's Logical Unit Number", HFILL }},
626         };
627         static gint *ett[] = {
628                 &ett_ipmi,
629                 &ett_ipmi_session,
630                 &ett_ipmi_msg_nlfield,
631                 &ett_ipmi_msg_slfield,
632         };
633
634         proto_ipmi = proto_register_protocol(
635                 "Intelligent Platform Management Interface", "IPMI", "ipmi");
636
637         proto_register_field_array(proto_ipmi, hf_session,
638                            array_length(hf_session));
639         proto_register_field_array(proto_ipmi, hf_msg,
640                            array_length(hf_msg));
641         proto_register_field_array(proto_ipmi, hf_msg_field,
642                            array_length(hf_msg_field));
643
644         proto_register_subtree_array(ett, array_length(ett));
645 }
646
647 void
648 proto_reg_handoff_ipmi(void)
649 {
650         dissector_handle_t ipmi_handle;
651
652         data_handle = find_dissector("data");
653
654         ipmi_handle = create_dissector_handle(dissect_ipmi, proto_ipmi);
655         dissector_add("rmcp.class", RMCP_CLASS_IPMI, ipmi_handle);
656 }