HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-distcc.c
blob1478ca2f2895672a32a4eb4d42cd7be472844eea
1 /* packet-distcc.c
2 * Routines for distcc dissection
3 * Copyright 2003, Brad Hards <bradh@frogmouth.net>
4 * Copyright 2003, Ronnie Sahlberg, added TCP desegmentation.
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 /* This dissector supports version 1 of the DISTCC protocol */
28 #include "config.h"
30 #include <stdio.h>
31 #include <string.h>
32 #include <time.h>
34 #include <glib.h>
36 #include <epan/packet.h>
38 #include <epan/prefs.h>
41 static int proto_distcc = -1;
42 static int hf_distcc_version = -1;
43 static int hf_distcc_argc = -1;
44 static int hf_distcc_argv = -1;
45 static int hf_distcc_doti_source = -1;
46 static int hf_distcc_stat = -1;
47 static int hf_distcc_serr = -1;
48 static int hf_distcc_sout = -1;
49 static int hf_distcc_doto_object = -1;
52 static gint ett_distcc = -1;
54 static dissector_handle_t data_handle;
57 static gboolean distcc_desegment = TRUE;
60 #define TCP_PORT_DISTCC 3632
62 static guint glb_distcc_tcp_port = TCP_PORT_DISTCC;
64 void proto_register_distcc(void);
65 extern void proto_reg_handoff_distcc(void);
67 #define CHECK_PDU_LEN(x) \
68 if(parameter>tvb_length_remaining(tvb, offset) || parameter < 1){\
69 len=tvb_length_remaining(tvb, offset);\
70 col_append_str(pinfo->cinfo, COL_INFO, "[Short" x " PDU]");\
71 } \
72 tvb_ensure_bytes_exist(tvb, offset, len);
75 #define DESEGMENT_TCP(x) \
76 if(distcc_desegment && pinfo->can_desegment){\
77 /* only attempt reassembly if whe have the full segment */\
78 if(tvb_length_remaining(tvb, offset)==tvb_reported_length_remaining(tvb, offset)){\
79 if(parameter>tvb_length_remaining(tvb, offset)){\
80 proto_tree_add_text(tree, tvb, offset-12, -1, "[Short " x " PDU]");\
81 pinfo->desegment_offset=offset-12;\
82 pinfo->desegment_len=parameter-tvb_length_remaining(tvb, offset);\
83 return offset+len;\
92 static int
93 dissect_distcc_dist(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint32 parameter)
95 proto_tree_add_uint_format(tree, hf_distcc_version, tvb, offset-12, 12, parameter, "DIST: %d", parameter);
97 col_append_fstr(pinfo->cinfo, COL_INFO, "DIST:%d ", parameter);
99 return offset;
102 static int
103 dissect_distcc_done(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint32 parameter)
105 proto_tree_add_uint_format(tree, hf_distcc_version, tvb, offset-12, 12, parameter, "DONE: %d", parameter);
107 col_append_fstr(pinfo->cinfo, COL_INFO, "DONE:%d ", parameter);
109 return offset;
112 static int
113 dissect_distcc_stat(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint32 parameter)
115 proto_tree_add_uint_format(tree, hf_distcc_stat, tvb, offset-12, 12, parameter, "STAT: %d", parameter);
117 col_append_fstr(pinfo->cinfo, COL_INFO, "STAT:%d ", parameter);
119 return offset;
122 static int
123 dissect_distcc_argc(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, guint32 parameter)
125 proto_tree_add_uint(tree, hf_distcc_argc, tvb, offset-12, 12, parameter);
127 col_append_fstr(pinfo->cinfo, COL_INFO, "ARGC:%d ", parameter);
129 return offset;
132 static int
133 dissect_distcc_argv(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gint parameter)
135 char argv[256];
136 int argv_len;
137 gint len=parameter;
140 CHECK_PDU_LEN("ARGV");
142 /* see if we need to desegment the PDU */
143 DESEGMENT_TCP("ARGV");
147 argv_len=len>255?255:len;
148 tvb_memcpy(tvb, argv, offset, argv_len);
149 argv[argv_len]=0;
151 proto_tree_add_item(tree, hf_distcc_argv, tvb, offset, len, ENC_ASCII|ENC_NA);
153 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", argv);
155 if(len!=parameter){
156 proto_tree_add_text(tree, tvb, 0, 0, "[Short ARGV PDU]");
158 return offset+len;
161 static int
162 dissect_distcc_serr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gint parameter)
164 char argv[256];
165 int argv_len;
166 gint len=parameter;
169 CHECK_PDU_LEN("SERR");
171 /* see if we need to desegment the PDU */
172 DESEGMENT_TCP("SERR");
176 argv_len=len>255?255:len;
177 tvb_memcpy(tvb, argv, offset, argv_len);
178 argv[argv_len]=0;
180 proto_tree_add_item(tree, hf_distcc_serr, tvb, offset, len, ENC_ASCII|ENC_NA);
182 col_append_fstr(pinfo->cinfo, COL_INFO, "SERR:%s ", argv);
184 if(len!=parameter){
185 proto_tree_add_text(tree, tvb, 0, 0, "[Short SERR PDU]");
187 return offset+len;
190 static int
191 dissect_distcc_sout(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gint parameter)
193 char argv[256];
194 int argv_len;
195 gint len=parameter;
198 CHECK_PDU_LEN("SOUT");
200 /* see if we need to desegment the PDU */
201 DESEGMENT_TCP("SOUT");
205 argv_len=len>255?255:len;
206 tvb_memcpy(tvb, argv, offset, argv_len);
207 argv[argv_len]=0;
209 proto_tree_add_item(tree, hf_distcc_sout, tvb, offset, len, ENC_ASCII|ENC_NA);
211 col_append_fstr(pinfo->cinfo, COL_INFO, "SOUT:%s ", argv);
213 if(len!=parameter){
214 proto_tree_add_text(tree, tvb, 0, 0, "[Short SOUT PDU]");
216 return offset+len;
220 static int
221 dissect_distcc_doti(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, gint parameter)
223 gint len=parameter;
226 CHECK_PDU_LEN("DOTI");
228 /* see if we need to desegment the PDU */
229 DESEGMENT_TCP("DOTI");
231 col_append_str(pinfo->cinfo, COL_INFO, "DOTI source ");
233 proto_tree_add_item(tree, hf_distcc_doti_source, tvb, offset, len, ENC_ASCII|ENC_NA);
234 if(len!=parameter){
235 proto_tree_add_text(tree, tvb, 0, 0, "[Short DOTI PDU]");
237 return offset+len;
240 static int
241 dissect_distcc_doto(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, gint parameter)
243 gint len=parameter;
246 CHECK_PDU_LEN("DOTO");
248 /* see if we need to desegment the PDU */
249 DESEGMENT_TCP("DOTO");
251 col_append_str(pinfo->cinfo, COL_INFO, "DOTO object ");
253 proto_tree_add_item(tree, hf_distcc_doto_object, tvb, offset, len, ENC_NA);
254 if(len!=parameter){
255 proto_tree_add_text(tree, tvb, 0, 0, "[Short DOTO PDU]");
257 return offset+len;
262 /* Packet dissection routine called by tcp (& udp) when port 3632 detected */
263 static void
264 dissect_distcc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
266 int offset=0;
267 proto_tree *tree=NULL;
268 proto_item *item=NULL;
269 char token[4];
270 guint32 parameter;
273 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DISTCC ");
275 col_clear(pinfo->cinfo, COL_INFO);
277 if (parent_tree) {
278 item = proto_tree_add_item(parent_tree, proto_distcc, tvb, offset,
279 -1, ENC_NA);
280 tree = proto_item_add_subtree(item, ett_distcc);
283 while(1){
284 /* we must have at least 12 bytes so we can read the
285 token and the parameter */
286 if(tvb_length_remaining(tvb, offset)<12){
287 return;
290 /* read the token */
291 tvb_memcpy(tvb, token, offset, 4);
292 offset+=4;
294 /* read the parameter */
295 if (sscanf(tvb_get_ptr(tvb, offset, 8), "%08x", &parameter) != 1)
296 return;
297 offset+=8;
299 if(!strncmp(token, "DIST", 4)){
300 offset=dissect_distcc_dist(tvb, pinfo, tree, offset, parameter);
301 } else if(!strncmp(token, "ARGC", 4)){
302 offset=dissect_distcc_argc(tvb, pinfo, tree, offset, parameter);
303 } else if(!strncmp(token, "ARGV", 4)){
304 offset=dissect_distcc_argv(tvb, pinfo, tree, offset, parameter);
305 } else if(!strncmp(token, "DOTI", 4)){
306 offset=dissect_distcc_doti(tvb, pinfo, tree, offset, parameter);
307 } else if(!strncmp(token, "DONE", 4)){
308 offset=dissect_distcc_done(tvb, pinfo, tree, offset, parameter);
309 } else if(!strncmp(token, "STAT", 4)){
310 offset=dissect_distcc_stat(tvb, pinfo, tree, offset, parameter);
311 } else if(!strncmp(token, "SERR", 4)){
312 offset=dissect_distcc_serr(tvb, pinfo, tree, offset, parameter);
313 } else if(!strncmp(token, "SOUT", 4)){
314 offset=dissect_distcc_sout(tvb, pinfo, tree, offset, parameter);
315 } else if(!strncmp(token, "DOTO", 4)){
316 offset=dissect_distcc_doto(tvb, pinfo, tree, offset, parameter);
317 } else {
318 call_dissector(data_handle, tvb, pinfo, tree);
319 return;
326 /* Register protocol with Wireshark. */
327 void
328 proto_register_distcc(void)
330 static hf_register_info hf[] = {
331 {&hf_distcc_version,
332 {"DISTCC Version", "distcc.version",
333 FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }
335 {&hf_distcc_argc,
336 {"ARGC", "distcc.argc",
337 FT_UINT32, BASE_DEC, NULL, 0x0, "Number of arguments", HFILL }
339 {&hf_distcc_argv,
340 {"ARGV", "distcc.argv",
341 FT_STRING, BASE_NONE, NULL, 0x0, "ARGV argument", HFILL }
343 {&hf_distcc_doti_source,
344 {"Source", "distcc.doti_source",
345 FT_STRING, BASE_NONE, NULL, 0x0, "DOTI Preprocessed Source File (.i)", HFILL }
347 {&hf_distcc_stat,
348 {"Status", "distcc.status",
349 FT_UINT32, BASE_DEC, NULL, 0x0, "Unix wait status for command completion", HFILL }
351 {&hf_distcc_serr,
352 {"SERR", "distcc.serr",
353 FT_STRING, BASE_NONE, NULL, 0x0, "STDERR output", HFILL }
355 {&hf_distcc_sout,
356 {"SOUT", "distcc.sout",
357 FT_STRING, BASE_NONE, NULL, 0x0, "STDOUT output", HFILL }
359 {&hf_distcc_doto_object,
360 {"Object", "distcc.doto_object",
361 FT_BYTES, BASE_NONE, NULL, 0x0, "DOTO Compiled object file (.o)", HFILL }
366 static gint *ett[] = {
367 &ett_distcc,
370 module_t *distcc_module;
372 proto_distcc = proto_register_protocol("Distcc Distributed Compiler",
373 "DISTCC", "distcc");
374 proto_register_field_array(proto_distcc, hf, array_length(hf));
375 proto_register_subtree_array(ett, array_length(ett));
377 distcc_module = prefs_register_protocol(proto_distcc,
378 proto_reg_handoff_distcc);
379 prefs_register_uint_preference(distcc_module, "tcp.port",
380 "DISTCC TCP Port",
381 "Set the TCP port for DISTCC messages",
383 &glb_distcc_tcp_port);
384 prefs_register_bool_preference(distcc_module, "desegment_distcc_over_tcp",
385 "Reassemble DISTCC-over-TCP messages\nspanning multiple TCP segments",
386 "Whether the DISTCC dissector should reassemble messages spanning multiple TCP segments."
387 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
388 &distcc_desegment);
391 void
392 proto_reg_handoff_distcc(void)
394 static gboolean registered_dissector = FALSE;
395 static int distcc_tcp_port;
396 static dissector_handle_t distcc_handle;
398 if (!registered_dissector) {
400 * We haven't registered the dissector yet; get a handle
401 * for it.
403 distcc_handle = create_dissector_handle(dissect_distcc,
404 proto_distcc);
405 data_handle = find_dissector("data");
406 registered_dissector = TRUE;
407 } else {
409 * We've registered the dissector with a TCP port number
410 * of "distcc_tcp_port"; we might be changing the TCP port
411 * number, so remove that registration.
413 dissector_delete_uint("tcp.port", distcc_tcp_port, distcc_handle);
415 distcc_tcp_port = glb_distcc_tcp_port;
416 dissector_add_uint("tcp.port", distcc_tcp_port, distcc_handle);