2 * Routines for java rmiregistry dissection
3 * Copyright 2002, Michael Stiller <ms@2scale.net>
5 * $Id: packet-rmi.c,v 1.9 2003/05/26 21:44:28 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
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;
128 char epid_hostname[256];
133 /* Make entries in Protocol column and Info column on summary display */
134 if (check_col(pinfo->cinfo, COL_PROTOCOL))
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_add_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_add_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 memset(epid_hostname, 0, sizeof(epid_hostname));
206 if (len < sizeof(epid_hostname)) {
207 strncpy(epid_hostname,tvb_get_ptr(tvb, offset + 3, len),
208 sizeof(epid_hostname));
210 strncpy(epid_hostname,
211 "<string too long>", sizeof(epid_hostname));
213 epid_hostname[sizeof(epid_hostname)-1] = '\0';
214 proto_tree_add_string(rmi_tree, hf_rmi_epid_hostname,
215 tvb, offset + 3, strlen(epid_hostname),
218 port = tvb_get_ntohs(tvb, offset + len + 5);
219 proto_tree_add_uint(rmi_tree, hf_rmi_epid_port,
220 tvb, offset + len + 5, 2, port);
222 if(message == RMI_INPUTSTREAM_MESSAGE_RETURNDATA) {
223 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
224 "Serialization Data");
225 next_tvb = tvb_new_subset(tvb, offset + 1, -1, -1);
226 dissect_ser(next_tvb, tree);
229 case RMI_OUTPUTMESSAGE:
230 message = tvb_get_guint8(tvb, 0);
231 proto_tree_add_uint(rmi_tree, hf_rmi_outputmessage,
232 tvb, offset, 1, message);
233 if(message == RMI_OUTPUTSTREAM_MESSAGE_CALL) {
234 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
235 "Serialization Data");
237 next_tvb = tvb_new_subset(tvb, offset + 1, -1, -1);
238 dissect_ser(next_tvb, tree);
240 if(message == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
241 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
245 case SERIALIZATION_DATA:
246 dissect_ser(tvb, tree);
255 dissect_ser(tvbuff_t *tvb, proto_tree *tree)
258 proto_tree *ser_tree;
265 ti = proto_tree_add_item(tree, proto_ser, tvb, 0, -1, FALSE);
266 ser_tree = proto_item_add_subtree(ti, ett_ser);
267 proto_tree_add_item(ser_tree, hf_ser_magic,
268 tvb, offset, 2, FALSE);
269 proto_tree_add_item(ser_tree, hf_ser_version,
270 tvb, offset + 2, 2, FALSE);
276 get_rmi_type(const guchar *data, int datalen)
281 ser_magic = data[0] << 8 | data[1];
282 if (ser_magic == SER_STREAM_MAGIC) {
283 return SERIALIZATION_DATA;
287 if(strncmp(data, RMI_MAGIC, 4) == 0) {
288 return RMI_OUTPUTSTREAM;
292 if (data[0] == RMI_INPUTSTREAM_MESSAGE_ACK ||
293 data[0] == RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED ||
294 data[0] == RMI_INPUTSTREAM_MESSAGE_RETURNDATA ||
295 data[0] == RMI_INPUTSTREAM_MESSAGE_PINGACK) {
296 return RMI_INPUTSTREAM;
300 if (data[0] == RMI_OUTPUTSTREAM_MESSAGE_CALL ||
301 data[0] == RMI_OUTPUTSTREAM_MESSAGE_PING ||
302 data[0] == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
303 return RMI_OUTPUTMESSAGE;
310 proto_register_rmi(void)
313 static hf_register_info hf[] = {
315 { "Magic", "rmi.magic",
316 FT_UINT32, BASE_HEX, NULL, 0x0,
317 "RMI Header Magic", HFILL }},
319 { "Version", "rmi.version",
320 FT_UINT16, BASE_DEC, NULL, 0x0,
321 "RMI Protocol Version", HFILL }},
323 { "Protocol","rmi.protocol",
324 FT_UINT8, BASE_HEX, VALS(rmi_protocol_str), 0x0,
325 "RMI Protocol Type", HFILL }},
326 { &hf_rmi_inputmessage,
327 { "Input Stream Message", "rmi.inputstream.message",
328 FT_UINT8, BASE_HEX, VALS(rmi_input_message_str), 0x0,
329 "RMI Inputstream Message Token", HFILL }},
330 { &hf_rmi_outputmessage,
331 { "Output Stream Message", "rmi.outputstream.message",
332 FT_UINT8, BASE_HEX, VALS(rmi_output_message_str), 0x0,
333 "RMI Outputstream Message token", HFILL }},
334 { &hf_rmi_epid_length,
335 { "Length", "rmi.endpoint_id.length",
336 FT_UINT16, BASE_DEC, NULL, 0x0,
337 "RMI Endpointidentifier Length", HFILL }},
338 { &hf_rmi_epid_hostname,
339 { "Hostname", "rmi.endpoint_id.hostname",
340 FT_STRING, BASE_HEX, NULL, 0x0,
341 "RMI Endpointidentifier Hostname", HFILL }},
343 { "Port", "rmi.endpoint_id.port",
344 FT_UINT16, BASE_DEC, NULL, 0x0,
345 "RMI Endpointindentifier Port", HFILL }},
348 { "Magic", "rmi.ser.magic",
349 FT_UINT16, BASE_HEX, NULL, 0x0,
350 "Java Serialization Magic", HFILL }},
352 { "Version", "rmi.ser.version",
353 FT_UINT16, BASE_DEC, NULL, 0x0,
354 "Java Serialization Version", HFILL }},
357 static gint *ett[] = {
361 &ett_rmi_inputmessage,
362 &ett_rmi_outputmessage,
363 &ett_rmi_epid_length,
364 &ett_rmi_epid_hostname,
369 proto_rmi = proto_register_protocol("Java RMI", "RMI", "rmi");
370 proto_ser = proto_register_protocol("Java Serialization", "Serialization",
372 proto_register_field_array(proto_rmi, hf, array_length(hf));
373 proto_register_subtree_array(ett, array_length(ett));
378 proto_reg_handoff_rmi(void)
380 dissector_handle_t rmi_handle;
382 rmi_handle = create_dissector_handle(dissect_rmi, proto_rmi);
383 dissector_add("tcp.port", TCP_PORT_RMI, rmi_handle);