Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / packet-rmi.c
1 /* packet-rmi.c
2  * Routines for java rmiregistry dissection
3  * Copyright 2002, Michael Stiller <ms@2scale.net>
4  *
5  * $Id: packet-rmi.c,v 1.5 2002/08/28 21:00:29 jmayer Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  *
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.
20  *
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.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33
34 #include <glib.h>
35
36 #include <epan/packet.h>
37 #include <epan/strutil.h>
38
39 #include "packet-rmi.h"
40
41 /* Initialize the protocol and registered fields */
42 static int proto_rmi             = -1;
43 static int proto_ser             = -1;
44 static int hf_rmi_magic          = -1;
45 static int hf_rmi_version        = -1;
46 static int hf_rmi_protocol       = -1;
47 static int hf_rmi_inputmessage   = -1;
48 static int hf_rmi_outputmessage  = -1;
49 static int hf_rmi_epid_length    = -1;
50 static int hf_rmi_epid_hostname  = -1;
51 static int hf_rmi_epid_port      = -1;
52
53 static int hf_ser_magic          = -1;
54 static int hf_ser_version        = -1;
55
56 /* Initialize the subtree pointers */
57 static gint ett_rmi               = -1;
58 static gint ett_rmi_magic         = -1;
59 static gint ett_rmi_version       = -1;
60 static gint ett_rmi_protocol      = -1;
61 static gint ett_rmi_inputmessage  = -1;
62 static gint ett_rmi_outputmessage = -1;
63 static gint ett_rmi_epid_length   = -1;
64 static gint ett_rmi_epid_hostname = -1;
65 static gint ett_rmi_epid_port     = -1;
66
67 static gint ett_ser               = -1;
68 static gint ett_ser_magic         = -1;
69 static gint ett_ser_version       = -1;
70
71 #define TCP_PORT_RMI    1099
72
73 static void
74 dissect_rmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
75 {
76     proto_item *ti;
77     proto_tree *rmi_tree;
78
79     tvbuff_t   *next_tvb;
80
81     gint       offset;
82     gint       next_offset;
83     int        datalen;
84     const guchar *data;
85
86     guint16    version, len, port;
87     guint8     message, proto;
88
89     rmi_type   rmitype;
90
91     char epid_hostname[256];
92
93     offset     = 0;
94     rmitype    = 0;
95
96 /* Make entries in Protocol column and Info column on summary display */
97     if (check_col(pinfo->cinfo, COL_PROTOCOL))
98         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RMI");
99
100     datalen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
101     data = tvb_get_ptr(tvb, offset, datalen);
102
103     rmitype = get_rmi_type(data, datalen);
104
105     if (check_col(pinfo->cinfo, COL_INFO)) {
106         switch(rmitype) {
107         case RMI_OUTPUTSTREAM:
108             version = tvb_get_ntohs(tvb,4);
109             col_add_fstr(pinfo->cinfo, COL_INFO,
110                          "JRMI, Version: %d, ", version);
111
112             proto   = tvb_get_guint8(tvb, 6);
113             col_append_str(pinfo->cinfo, COL_INFO,
114                            val_to_str(proto, rmi_protocol_str,
115                                       "Unknown protocol"));
116             break;
117         case RMI_OUTPUTMESSAGE:
118             message = tvb_get_guint8(tvb,0);
119             col_add_str(pinfo->cinfo, COL_INFO,
120                         "JRMI, ");
121             col_append_str(pinfo->cinfo, COL_INFO,
122                            val_to_str(message, rmi_output_message_str,
123                                       "Unknown message"));
124             break;
125         case RMI_INPUTSTREAM:
126             message = tvb_get_guint8(tvb,0);
127             col_add_str(pinfo->cinfo, COL_INFO,
128                         "JRMI, ");
129             col_append_str(pinfo->cinfo, COL_INFO,
130                            val_to_str(message, rmi_input_message_str,
131                                       "Unknown message"));
132             break;
133         case SERIALIZATION_DATA:
134             version = tvb_get_ntohs(tvb,2);
135             col_add_fstr(pinfo->cinfo, COL_INFO,
136                          "Serialization data, Version: %d", version);
137             break;
138         default:
139             col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
140             break;
141         }
142     }
143
144     if (tree) {
145         ti = proto_tree_add_item(tree, proto_rmi, tvb, 0, -1, FALSE);
146         rmi_tree = proto_item_add_subtree(ti, ett_rmi);
147         switch(rmitype) {
148         case RMI_OUTPUTSTREAM:
149             proto_tree_add_uint(rmi_tree, hf_rmi_magic,
150                                 tvb, offset,     4, tvb_get_ntohl(tvb,0));
151             proto_tree_add_uint(rmi_tree, hf_rmi_version,
152                                 tvb, offset + 4, 2, tvb_get_ntohs(tvb,4));
153             proto_tree_add_string(rmi_tree, hf_rmi_protocol,
154                                   tvb, offset + 6, 1,
155                                   val_to_str(tvb_get_guint8(tvb, 6),
156                                              rmi_protocol_str,
157                                              "Unknown Protocol"));
158             break;
159         case RMI_INPUTSTREAM:
160             message = tvb_get_guint8(tvb, 0);
161             proto_tree_add_string(rmi_tree, hf_rmi_inputmessage,
162                                   tvb, offset, 1,
163                                   val_to_str(message,
164                                              rmi_input_message_str,
165                                              "Unknown Message"));
166             if(message == RMI_INPUTSTREAM_MESSAGE_ACK) {
167                 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
168                                     "EndPointIdentifier");
169                 /* MESSAGE_ACK should include EndpointIdentifier */
170                 len = tvb_get_ntohs(tvb, 1);
171                 proto_tree_add_uint(rmi_tree, hf_rmi_epid_length,
172                                        tvb, offset + 1, 2, len);
173                 memset(epid_hostname, 0, sizeof(epid_hostname));
174                 if (len < sizeof(epid_hostname)) {
175                     strncpy(epid_hostname,tvb_get_ptr(tvb, offset + 3, len),
176                             sizeof(epid_hostname));
177                 } else {
178                     strncpy(epid_hostname,
179                             "<string too long>", sizeof(epid_hostname));
180                 }
181                 proto_tree_add_string(rmi_tree, hf_rmi_epid_hostname,
182                                       tvb, offset + 3, strlen(epid_hostname),
183                                       epid_hostname);
184
185                 port = tvb_get_ntohs(tvb, offset + len + 5);
186                 proto_tree_add_uint(rmi_tree, hf_rmi_epid_port,
187                                     tvb, offset + len + 5, 2, port);
188             }
189             if(message == RMI_INPUTSTREAM_MESSAGE_RETURNDATA) {
190                 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
191                                     "Serialization Data");
192                 next_tvb = tvb_new_subset(tvb, offset + 1, -1, -1);
193                 dissect_ser(next_tvb, pinfo, tree);
194             }
195             break;
196         case RMI_OUTPUTMESSAGE:
197             message = tvb_get_guint8(tvb, 0);
198             proto_tree_add_string(rmi_tree, hf_rmi_outputmessage,
199                                   tvb, offset, 1,
200                                   val_to_str(message,
201                                              rmi_output_message_str,
202                                              "Unknown Message"));
203             if(message == RMI_OUTPUTSTREAM_MESSAGE_CALL) {
204                 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
205                                     "Serialization Data");
206                 /* XXX */
207                 next_tvb = tvb_new_subset(tvb, offset + 1, -1, -1);
208                 dissect_ser(next_tvb, pinfo, tree);
209             }
210             if(message == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
211                 proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
212                                     "UniqueIdentifier");
213             }
214             break;
215         case SERIALIZATION_DATA:
216             dissect_ser(tvb, pinfo, tree);
217             break;
218         default:
219             break;
220         }
221     }
222 }
223
224 static void
225 dissect_ser(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
226 {
227     proto_item *ti;
228     proto_tree *ser_tree;
229
230     gint offset;
231
232     offset = 0;
233
234     if(tree) {
235         ti = proto_tree_add_item(tree, proto_ser, tvb, 0, -1, FALSE);
236         ser_tree = proto_item_add_subtree(ti, ett_ser);
237         proto_tree_add_uint(ser_tree, hf_ser_magic,
238                             tvb, offset,     2, tvb_get_ntohs(tvb,0));
239         proto_tree_add_uint(ser_tree, hf_ser_version,
240                             tvb, offset + 2, 2, tvb_get_ntohs(tvb,2));
241
242     }
243 }
244
245 static rmi_type
246 get_rmi_type(const guchar *data, int datalen)
247 {
248     guint16 ser_magic;
249
250     if (datalen >= 2) {
251         ser_magic = data[0] << 8 | data[1];
252         if (ser_magic == SER_STREAM_MAGIC) {
253             return SERIALIZATION_DATA;
254         }
255     }
256     if (datalen >= 4) {
257         if(strncmp(data, "JRMI", 4) == 0) {
258             return RMI_OUTPUTSTREAM;
259         }
260     }
261     if (datalen >= 1) {
262         if (data[0] == RMI_INPUTSTREAM_MESSAGE_ACK ||
263             data[0] == RMI_INPUTSTREAM_MESSAGE_NOTSUPPORTED ||
264             data[0] == RMI_INPUTSTREAM_MESSAGE_RETURNDATA ||
265             data[0] == RMI_INPUTSTREAM_MESSAGE_PINGACK) {
266             return RMI_INPUTSTREAM;
267         }
268     }
269     if (datalen >= 1) {
270         if (data[0] == RMI_OUTPUTSTREAM_MESSAGE_CALL ||
271             data[0] == RMI_OUTPUTSTREAM_MESSAGE_PING ||
272             data[0] == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
273             return RMI_OUTPUTMESSAGE;
274         }
275     }
276     return CONTINUATION;
277 }
278
279 void
280 proto_register_rmi(void)
281 {
282
283     static hf_register_info hf[] = {
284         { &hf_rmi_magic,
285           { "Magic",   "rmi.magic",
286             FT_UINT32, BASE_HEX, NULL, 0x0,
287             "RMI Header Magic", HFILL }},
288         { &hf_rmi_version,
289           { "Version", "rmi.version",
290             FT_UINT16, BASE_DEC, NULL, 0x0,
291             "RMI Protocol Version", HFILL }},
292         { &hf_rmi_protocol,
293           { "Protocol","rmi.protocol",
294             FT_STRING, BASE_HEX, NULL, 0x0,
295             "RMI Protocol Type", HFILL }},
296         { &hf_rmi_inputmessage,
297           { "Input Stream Message", "rmi.inputstream.message",
298             FT_STRING, BASE_HEX, NULL, 0x0,
299             "RMI Inputstream Message Token", HFILL }},
300         { &hf_rmi_outputmessage,
301           { "Output Stream Message", "rmi.outputstream.message",
302             FT_STRING, BASE_HEX, NULL, 0x0,
303             "RMI Outputstream Message token", HFILL }},
304         { &hf_rmi_epid_length,
305           { "Length", "rmi.endpoint_id.length",
306             FT_UINT16, BASE_DEC, NULL, 0x0,
307             "RMI Endpointidentifier Length", HFILL }},
308         { &hf_rmi_epid_hostname,
309           { "Hostname", "rmi.endpoint_id.hostname",
310             FT_STRING, BASE_HEX, NULL, 0x0,
311             "RMI Endpointidentifier Hostname", HFILL }},
312         { &hf_rmi_epid_port,
313           { "Port", "rmi.endpoint_id.port",
314             FT_UINT16, BASE_DEC, NULL, 0x0,
315             "RMI Endpointindentifier Port", HFILL }},
316
317         { &hf_ser_magic,
318           { "Magic",   "rmi.ser.magic",
319             FT_UINT16, BASE_HEX, NULL, 0x0,
320             "Java Serialization Magic", HFILL }},
321         { &hf_ser_version,
322           { "Version", "rmi.ser.version",
323             FT_UINT16, BASE_DEC, NULL, 0x0,
324             "Java Serialization Version", HFILL }},
325     };
326
327     static gint *ett[] = {
328         &ett_rmi,
329         &ett_rmi_magic,
330         &ett_rmi_version,
331         &ett_rmi_inputmessage,
332         &ett_rmi_outputmessage,
333         &ett_rmi_epid_length,
334         &ett_rmi_epid_hostname,
335         &ett_rmi_epid_port,
336         &ett_ser,
337     };
338
339     proto_rmi = proto_register_protocol("Java RMI", "RMI", "rmi");
340     proto_ser = proto_register_protocol("Java Serialization", "Serialization",
341                                         "serialization");
342     proto_register_field_array(proto_rmi, hf, array_length(hf));
343     proto_register_subtree_array(ett, array_length(ett));
344
345 }
346
347 void
348 proto_reg_handoff_rmi(void)
349 {
350     dissector_handle_t rmi_handle;
351
352     rmi_handle = create_dissector_handle(dissect_rmi, proto_rmi);
353     dissector_add("tcp.port", TCP_PORT_RMI, rmi_handle);
354 }