1 /* packet-ipmi-session.c
2 * Routines for dissection of IPMI session wrapper (v1.5 and v2.0)
3 * Copyright 2007-2008, Alexey Neyman, Pigeon Point Systems <avn@pigeonpoint.com>
4 * Copyright Duncan Laurie <duncan@sun.com>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Partially copied from packet-ipmi.c.
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
32 #include <epan/packet.h>
34 #define RMCP_CLASS_IPMI 0x07
36 static int proto_ipmi_session
= -1;
38 static gint ett_ipmi_session
= -1;
39 static gint ett_ipmi_session_payloadtype
= -1;
41 /* IPMI session header */
42 static int hf_ipmi_session_id
= -1;
43 static int hf_ipmi_session_authtype
= -1;
44 static int hf_ipmi_session_payloadtype
= -1;
45 static int hf_ipmi_session_payloadtype_auth
= -1;
46 static int hf_ipmi_session_payloadtype_enc
= -1;
47 static int hf_ipmi_session_oem_iana
= -1;
48 static int hf_ipmi_session_oem_payload_id
= -1;
49 static int hf_ipmi_session_sequence
= -1;
50 static int hf_ipmi_session_authcode
= -1;
51 static int hf_ipmi_session_msg_len_1b
= -1;
52 static int hf_ipmi_session_msg_len_2b
= -1;
53 static int hf_ipmi_session_trailer
= -1;
55 static dissector_handle_t ipmi_handle
;
56 static dissector_handle_t data_handle
;
58 #define IPMI_AUTH_NONE 0x00
59 #define IPMI_AUTH_MD2 0x01
60 #define IPMI_AUTH_MD5 0x02
61 #define IPMI_AUTH_PASSWORD 0x04
62 #define IPMI_AUTH_OEM 0x05
63 #define IPMI_AUTH_RMCPP 0x06
65 static const value_string ipmi_authtype_vals
[] = {
66 { IPMI_AUTH_NONE
, "NONE" },
67 { IPMI_AUTH_MD2
, "MD2" },
68 { IPMI_AUTH_MD5
, "MD5" },
69 { IPMI_AUTH_PASSWORD
, "PASSWORD" },
70 { IPMI_AUTH_OEM
, "OEM" },
71 { IPMI_AUTH_RMCPP
, "RMCP+"},
75 #define IPMI_IPMI_MESSAGE 0
76 #define IPMI_OEM_EXPLICIT 2
78 static const value_string ipmi_payload_vals
[] = {
79 { IPMI_IPMI_MESSAGE
, "IPMI Message" },
80 { 0x01, "SOL (serial over LAN)" },
81 { IPMI_OEM_EXPLICIT
, "OEM Explicit" },
82 /* Session Setup Payload Types */
83 { 0x10, "RMCP+ Open Session Request" },
84 { 0x11, "RMCP+ Open Session Response" },
85 { 0x12, "RAKP Message 1" },
86 { 0x13, "RAKP Message 2" },
87 { 0x14, "RAKP Message 3" },
88 { 0x15, "RAKP Message 4" },
89 /* OEM Payload Type Handles */
90 { 0x20, "OEM0 (OEM Payload)" },
91 { 0x21, "OEM1 (OEM Payload)" },
92 { 0x22, "OEM2 (OEM Payload)" },
93 { 0x23, "OEM3 (OEM Payload)" },
94 { 0x24, "OEM4 (OEM Payload)" },
95 { 0x25, "OEM5 (OEM Payload)" },
96 { 0x26, "OEM6 (OEM Payload)" },
97 { 0x27, "OEM7 (OEM Payload)" },
101 static const true_false_string ipmi_payload_aut_val
= {
102 "Payload is authenticated",
103 "Payload is unauthenticated"
106 static const true_false_string ipmi_payload_enc_val
= {
107 "Payload is encrypted",
108 "Payload is unencrypted"
112 dissect_ipmi_session(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
114 proto_tree
*sess_tree
= NULL
, *s_tree
;
115 proto_item
*ti
= NULL
;
118 guint8 authtype
, payloadtype
= 0;
119 guint32 msg_start
, msg_len
, offset
= 0;
120 gboolean payloadtype_auth
= 0, payloadtype_enc
= 0;
122 /* session authtype, 0=no authcode present, 6=RMCP+ */
123 authtype
= tvb_get_guint8(tvb
, 0);
124 if (authtype
== IPMI_AUTH_RMCPP
) {
125 /* Fetch additional info before trying to interpret
126 the packet. It may not be IPMI at all! */
127 payloadtype
= tvb_get_guint8(tvb
, 1);
128 payloadtype_auth
= (payloadtype
>> 6) & 1;
129 payloadtype_enc
= (payloadtype
>> 7);
132 /* IPMI v2.0 packets have session ID BEFORE the session
133 sequence number; just after authentification and payload
134 types. The OEM Explicit payload type has 6 more bytes
135 (IANA + Payload ID) before the session ID. */
136 if (payloadtype
== IPMI_OEM_EXPLICIT
) {
137 session_id
= tvb_get_letohl(tvb
, 8);
139 msg_len
= tvb_get_letohs(tvb
, 16);
141 session_id
= tvb_get_letohl(tvb
, 2);
143 msg_len
= tvb_get_letohs(tvb
, 10);
146 /* IPMI v1.5 packets have session ID AFTER the session
147 sequence number. They also have 1 byte for payload
149 session_id
= tvb_get_letohl(tvb
, 5);
150 if (authtype
== IPMI_AUTH_NONE
) {
152 msg_len
= tvb_get_guint8(tvb
, 9);
155 msg_len
= tvb_get_guint8(tvb
, 25);
159 /* Later it will be overridden with sub-dissector, if any */
160 if (authtype
== IPMI_AUTH_RMCPP
) {
161 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "RMCP+");
163 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "IPMI");
166 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Session ID 0x%x", session_id
);
167 if (authtype
== IPMI_AUTH_RMCPP
) {
168 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", payload type: %s",
169 val_to_str_const(payloadtype
, ipmi_payload_vals
, "Unknown"));
174 ti
= proto_tree_add_protocol_format(tree
, proto_ipmi_session
,
175 tvb
, 0, tvb_length(tvb
),
176 "IPMI v%s Session Wrapper, session ID 0x%x",
177 authtype
== IPMI_AUTH_RMCPP
? "2.0+" : "1.5",
179 sess_tree
= proto_item_add_subtree(ti
, ett_ipmi_session
);
180 proto_tree_add_item(sess_tree
, hf_ipmi_session_authtype
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
183 if (authtype
== IPMI_AUTH_RMCPP
) {
185 ti
= proto_tree_add_text(sess_tree
, tvb
, offset
, 1,
186 "Payload type: %s (0x%02x), %sencrypted, %sauthenticated",
187 val_to_str_const(payloadtype
, ipmi_payload_vals
, "Unknown"),
189 payloadtype_enc
? "" : "not ",
190 payloadtype_auth
? "" : "not ");
191 s_tree
= proto_item_add_subtree(ti
, ett_ipmi_session_payloadtype
);
192 proto_tree_add_item(s_tree
, hf_ipmi_session_payloadtype_enc
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
193 proto_tree_add_item(s_tree
, hf_ipmi_session_payloadtype_auth
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
194 proto_tree_add_item(s_tree
, hf_ipmi_session_payloadtype
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
197 if (payloadtype
== IPMI_OEM_EXPLICIT
) {
198 proto_tree_add_item(sess_tree
, hf_ipmi_session_oem_iana
, tvb
, offset
, 4, ENC_NA
);
200 proto_tree_add_item(sess_tree
, hf_ipmi_session_oem_payload_id
, tvb
, offset
, 2, ENC_NA
);
203 proto_tree_add_item(sess_tree
, hf_ipmi_session_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
205 proto_tree_add_item(sess_tree
, hf_ipmi_session_sequence
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
207 proto_tree_add_item(sess_tree
, hf_ipmi_session_msg_len_2b
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
211 proto_tree_add_item(sess_tree
, hf_ipmi_session_sequence
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
213 proto_tree_add_item(sess_tree
, hf_ipmi_session_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
215 if (authtype
!= IPMI_AUTH_NONE
) {
216 proto_tree_add_item(sess_tree
, hf_ipmi_session_authcode
,
217 tvb
, offset
, 16, ENC_NA
);
220 proto_tree_add_item(sess_tree
, hf_ipmi_session_msg_len_1b
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
225 /* If we can parse the embedded message, do so */
226 next_tvb
= tvb_new_subset(tvb
, msg_start
, msg_len
, -1);
227 if (payloadtype_enc
) {
228 /* This is RMCP+, and payload is encrypted. In this case,
229 there is a 'confidentiality header/trailer', whose lengths
230 are unknown to us. These lengths are negotiated during
231 session open process and are retained over a session.
232 Since we are stateless (and more, we may have no session
233 open packet in the capture we parse), we cannot even
234 decipher where a message starts. Just print them as data.
236 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
237 } else if (authtype
!= IPMI_AUTH_RMCPP
|| payloadtype
== IPMI_IPMI_MESSAGE
) {
238 /* This is an IPMI message, either v1.5 or v2.0+. For now,
239 we don't need to distinguish these kinds. */
240 call_dissector(ipmi_handle
, next_tvb
, pinfo
, tree
);
242 /* All other RMCP+ payload types fall here: session open/close
243 requests, RAKP messages, SOL. We cannot parse them yet, thus
244 just output as data. */
245 call_dissector(data_handle
, next_tvb
, pinfo
, tree
);
249 /* Account for the message we just parsed. */
252 /* Show the rest of the session wrapper as binary data */
253 if (offset
< tvb_length(tvb
)) {
254 proto_tree_add_item(sess_tree
, hf_ipmi_session_trailer
,
255 tvb
, offset
, tvb_length(tvb
) - offset
, ENC_NA
);
258 return tvb_length(tvb
);
262 proto_register_ipmi_session(void)
264 static hf_register_info hf
[] = {
265 { &hf_ipmi_session_authtype
, {
266 "Authentication Type", "ipmi_session.authtype",
267 FT_UINT8
, BASE_HEX
, VALS(ipmi_authtype_vals
), 0, NULL
, HFILL
}},
268 { &hf_ipmi_session_payloadtype
,{
269 "Payload Type", "ipmi_session.payloadtype",
270 FT_UINT8
, BASE_HEX
, VALS(ipmi_payload_vals
), 0x3f, NULL
, HFILL
}},
271 { &hf_ipmi_session_payloadtype_auth
,{
272 "Authenticated","ipmi_session.payloadtype.auth",
273 FT_BOOLEAN
,8, TFS(&ipmi_payload_aut_val
), 0x40, NULL
, HFILL
}},
274 { &hf_ipmi_session_payloadtype_enc
,{
275 "Encryption","ipmi_session.payloadtype.enc",
276 FT_BOOLEAN
,8, TFS(&ipmi_payload_enc_val
), 0x80, NULL
, HFILL
}},
277 { &hf_ipmi_session_oem_iana
, {
278 "OEM IANA", "ipmi_session.oem.iana",
279 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
280 { &hf_ipmi_session_oem_payload_id
, {
281 "OEM Payload ID", "ipmi_session.oem.payloadid",
282 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
283 { &hf_ipmi_session_sequence
, {
284 "Session Sequence Number", "ipmi_session.sequence",
285 FT_UINT32
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
286 { &hf_ipmi_session_id
, {
287 "Session ID", "ipmi_session.id",
288 FT_UINT32
, BASE_HEX
, NULL
, 0, NULL
, HFILL
}},
289 { &hf_ipmi_session_authcode
, {
290 "Authentication Code", "ipmi_session.authcode",
291 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
292 { &hf_ipmi_session_msg_len_1b
, {
293 "Message Length", "ipmi_session.msg.len",
294 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
295 { &hf_ipmi_session_msg_len_2b
, {
296 "Message Length", "ipmi_session.msg.len",
297 FT_UINT16
, BASE_DEC
, NULL
, 0, NULL
, HFILL
}},
298 { &hf_ipmi_session_trailer
, {
299 "IPMI Session Wrapper (trailer)", "ipmi_session.trailer",
300 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
}},
303 static gint
*ett
[] = { &ett_ipmi_session
, &ett_ipmi_session_payloadtype
};
305 proto_ipmi_session
= proto_register_protocol(
306 "Intelligent Platform Management Interface (Session Wrapper)", "IPMI Session",
308 proto_register_field_array(proto_ipmi_session
, hf
, array_length(hf
));
309 proto_register_subtree_array(ett
, array_length(ett
));
313 proto_reg_handoff_ipmi_session(void)
315 dissector_handle_t ipmi_session_handle
;
317 ipmi_session_handle
= new_create_dissector_handle(dissect_ipmi_session
, proto_ipmi_session
);
318 dissector_add_uint("rmcp.class", RMCP_CLASS_IPMI
, ipmi_session_handle
);
320 data_handle
= find_dissector("data");
321 ipmi_handle
= find_dissector("ipmi");