2 * Routines for java rmiregistry dissection
3 * Copyright 2002, Michael Stiller <ms@2scale.net>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/packet.h>
37 #include <epan/strutil.h>
39 #include "packet-rmi.h"
42 dissect_ser(tvbuff_t *tvb, proto_tree *tree);
45 get_rmi_type(const guchar *data, int datalen);
47 /* Initialize the protocol and registered fields */
48 static int proto_rmi = -1;
49 static int proto_ser = -1;
50 static int hf_rmi_magic = -1;
51 static int hf_rmi_version = -1;
52 static int hf_rmi_protocol = -1;
53 static int hf_rmi_inputmessage = -1;
54 static int hf_rmi_outputmessage = -1;
55 static int hf_rmi_epid_length = -1;
56 static int hf_rmi_epid_hostname = -1;
57 static int hf_rmi_epid_port = -1;
59 static int hf_ser_magic = -1;
60 static int hf_ser_version = -1;
62 /* Initialize the subtree pointers */
63 static gint ett_rmi = -1;
64 static gint ett_rmi_magic = -1;
65 static gint ett_rmi_version = -1;
66 static gint ett_rmi_inputmessage = -1;
67 static gint ett_rmi_outputmessage = -1;
68 static gint ett_rmi_epid_length = -1;
69 static gint ett_rmi_epid_hostname = -1;
70 static gint ett_rmi_epid_port = -1;
72 static gint ett_ser = -1;
77 * http://java.sun.com/products/jdk/1.2/docs/guide/rmi/spec/rmi-protocol.doc1.html
81 * http://java.sun.com/products/jdk/1.2/docs/guide/serialization/spec/protocol.doc.html
83 * for the serialization protocol.
86 #define TCP_PORT_RMI 1099
88 static const value_string rmi_protocol_str[] = {
89 {RMI_OUTPUTSTREAM_PROTOCOL_STREAM, "StreamProtocol"},
90 {RMI_OUTPUTSTREAM_PROTOCOL_SINGLEOP, "SingleOpProtocol"},
91 {RMI_OUTPUTSTREAM_PROTOCOL_MULTIPLEX, "MultiPlexProtocol"},
95 static const value_string rmi_output_message_str[] = {
96 {RMI_OUTPUTSTREAM_MESSAGE_CALL, "Call"},
97 {RMI_OUTPUTSTREAM_MESSAGE_PING, "Ping"},
98 {RMI_OUTPUTSTREAM_MESSAGE_DGCACK, "DgcAck"},
102 static const value_string rmi_input_message_str[] = {
103 {RMI_INPUTSTREAM_MESSAGE_ACK, "ProtocolAck"},
104 {RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED, "ProtocolNotSupported"},
105 {RMI_INPUTSTREAM_MESSAGE_RETURNDATA, "ReturnData"},
106 {RMI_INPUTSTREAM_MESSAGE_PINGACK, "PingAck"},
111 dissect_rmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
114 proto_tree *rmi_tree;
123 guint16 version, len, port;
124 guint8 message, proto;
134 /* Make entries in Protocol column and Info column on summary display */
135 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RMI");
137 datalen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
138 data = tvb_get_ptr(tvb, offset, datalen);
140 rmitype = get_rmi_type(data, datalen);
142 if (check_col(pinfo->cinfo, COL_INFO)) {
144 case RMI_OUTPUTSTREAM:
145 version = tvb_get_ntohs(tvb,4);
146 col_add_fstr(pinfo->cinfo, COL_INFO,
147 "JRMI, Version: %d, ", version);
149 proto = tvb_get_guint8(tvb, 6);
150 col_append_str(pinfo->cinfo, COL_INFO,
151 val_to_str(proto, rmi_protocol_str,
152 "Unknown protocol"));
154 case RMI_OUTPUTMESSAGE:
155 message = tvb_get_guint8(tvb,0);
156 col_set_str(pinfo->cinfo, COL_INFO,
158 col_append_str(pinfo->cinfo, COL_INFO,
159 val_to_str(message, rmi_output_message_str,
162 case RMI_INPUTSTREAM:
163 message = tvb_get_guint8(tvb,0);
164 col_set_str(pinfo->cinfo, COL_INFO,
166 col_append_str(pinfo->cinfo, COL_INFO,
167 val_to_str(message, rmi_input_message_str,
170 case SERIALIZATION_DATA:
171 version = tvb_get_ntohs(tvb,2);
172 col_add_fstr(pinfo->cinfo, COL_INFO,
173 "Serialization data, Version: %d", version);
176 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
182 ti = proto_tree_add_item(tree, proto_rmi, tvb, 0, -1, FALSE);
183 rmi_tree = proto_item_add_subtree(ti, ett_rmi);
185 case RMI_OUTPUTSTREAM:
186 /* XXX - uint, or string? */
187 proto_tree_add_uint(rmi_tree, hf_rmi_magic,
188 tvb, offset, 4, tvb_get_ntohl(tvb,0));
189 proto_tree_add_item(rmi_tree, hf_rmi_version,
190 tvb, offset + 4, 2, FALSE);
191 proto_tree_add_item(rmi_tree, hf_rmi_protocol,
192 tvb, offset + 6, 1, FALSE);
194 case RMI_INPUTSTREAM:
195 message = tvb_get_guint8(tvb, 0);
196 proto_tree_add_uint(rmi_tree, hf_rmi_inputmessage,
197 tvb, offset, 1, message);
198 if(message == RMI_INPUTSTREAM_MESSAGE_ACK) {
199 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
200 "EndPointIdentifier");
201 /* MESSAGE_ACK should include EndpointIdentifier */
202 len = tvb_get_ntohs(tvb, 1);
203 proto_tree_add_uint(rmi_tree, hf_rmi_epid_length,
204 tvb, offset + 1, 2, len);
205 epid_len = len < ITEM_LABEL_LENGTH ? len : ITEM_LABEL_LENGTH;
207 epid_hostname = tvb_format_text(tvb, offset + 3, epid_len);
209 epid_hostname = "[Empty]";
211 proto_tree_add_string(rmi_tree, hf_rmi_epid_hostname,
212 tvb, offset + 3, len, epid_hostname);
214 port = tvb_get_ntohs(tvb, offset + len + 5);
215 proto_tree_add_uint(rmi_tree, hf_rmi_epid_port,
216 tvb, offset + len + 5, 2, port);
218 if(message == RMI_INPUTSTREAM_MESSAGE_RETURNDATA) {
219 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
220 "Serialization Data");
221 next_tvb = tvb_new_subset_remaining(tvb, offset + 1);
222 dissect_ser(next_tvb, tree);
225 case RMI_OUTPUTMESSAGE:
226 message = tvb_get_guint8(tvb, 0);
227 proto_tree_add_uint(rmi_tree, hf_rmi_outputmessage,
228 tvb, offset, 1, message);
229 if(message == RMI_OUTPUTSTREAM_MESSAGE_CALL) {
230 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
231 "Serialization Data");
233 next_tvb = tvb_new_subset_remaining(tvb, offset + 1);
234 dissect_ser(next_tvb, tree);
236 if(message == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
237 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
241 case SERIALIZATION_DATA:
242 dissect_ser(tvb, tree);
251 dissect_ser(tvbuff_t *tvb, proto_tree *tree)
254 proto_tree *ser_tree;
261 ti = proto_tree_add_item(tree, proto_ser, tvb, 0, -1, FALSE);
262 ser_tree = proto_item_add_subtree(ti, ett_ser);
263 proto_tree_add_item(ser_tree, hf_ser_magic,
264 tvb, offset, 2, FALSE);
265 proto_tree_add_item(ser_tree, hf_ser_version,
266 tvb, offset + 2, 2, FALSE);
272 get_rmi_type(const guchar *data, int datalen)
277 ser_magic = data[0] << 8 | data[1];
278 if (ser_magic == SER_STREAM_MAGIC) {
279 return SERIALIZATION_DATA;
283 if(strncmp(data, RMI_MAGIC, 4) == 0) {
284 return RMI_OUTPUTSTREAM;
288 if (data[0] == RMI_INPUTSTREAM_MESSAGE_ACK ||
289 data[0] == RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED ||
290 data[0] == RMI_INPUTSTREAM_MESSAGE_RETURNDATA ||
291 data[0] == RMI_INPUTSTREAM_MESSAGE_PINGACK) {
292 return RMI_INPUTSTREAM;
296 if (data[0] == RMI_OUTPUTSTREAM_MESSAGE_CALL ||
297 data[0] == RMI_OUTPUTSTREAM_MESSAGE_PING ||
298 data[0] == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
299 return RMI_OUTPUTMESSAGE;
306 proto_register_rmi(void)
309 static hf_register_info hf[] = {
311 { "Magic", "rmi.magic",
312 FT_UINT32, BASE_HEX, NULL, 0x0,
313 "RMI Header Magic", HFILL }},
315 { "Version", "rmi.version",
316 FT_UINT16, BASE_DEC, NULL, 0x0,
317 "RMI Protocol Version", HFILL }},
319 { "Protocol","rmi.protocol",
320 FT_UINT8, BASE_HEX, VALS(rmi_protocol_str), 0x0,
321 "RMI Protocol Type", HFILL }},
322 { &hf_rmi_inputmessage,
323 { "Input Stream Message", "rmi.inputstream.message",
324 FT_UINT8, BASE_HEX, VALS(rmi_input_message_str), 0x0,
325 "RMI Inputstream Message Token", HFILL }},
326 { &hf_rmi_outputmessage,
327 { "Output Stream Message", "rmi.outputstream.message",
328 FT_UINT8, BASE_HEX, VALS(rmi_output_message_str), 0x0,
329 "RMI Outputstream Message token", HFILL }},
330 { &hf_rmi_epid_length,
331 { "Length", "rmi.endpoint_id.length",
332 FT_UINT16, BASE_DEC, NULL, 0x0,
333 "RMI Endpointidentifier Length", HFILL }},
334 { &hf_rmi_epid_hostname,
335 { "Hostname", "rmi.endpoint_id.hostname",
336 FT_STRING, BASE_NONE, NULL, 0x0,
337 "RMI Endpointidentifier Hostname", HFILL }},
339 { "Port", "rmi.endpoint_id.port",
340 FT_UINT16, BASE_DEC, NULL, 0x0,
341 "RMI Endpointindentifier Port", HFILL }},
344 { "Magic", "rmi.ser.magic",
345 FT_UINT16, BASE_HEX, NULL, 0x0,
346 "Java Serialization Magic", HFILL }},
348 { "Version", "rmi.ser.version",
349 FT_UINT16, BASE_DEC, NULL, 0x0,
350 "Java Serialization Version", HFILL }},
353 static gint *ett[] = {
357 &ett_rmi_inputmessage,
358 &ett_rmi_outputmessage,
359 &ett_rmi_epid_length,
360 &ett_rmi_epid_hostname,
365 proto_rmi = proto_register_protocol("Java RMI", "RMI", "rmi");
366 proto_ser = proto_register_protocol("Java Serialization", "Serialization",
368 proto_register_field_array(proto_rmi, hf, array_length(hf));
369 proto_register_subtree_array(ett, array_length(ett));
374 proto_reg_handoff_rmi(void)
376 dissector_handle_t rmi_handle;
378 rmi_handle = create_dissector_handle(dissect_rmi, proto_rmi);
379 dissector_add("tcp.port", TCP_PORT_RMI, rmi_handle);