2 * Routines for distcc dissection
3 * Copyright 2003, Brad Hards <bradh@frogmouth.net>
4 * Copyright 2003, Ronnie Sahlberg, added TCP desegmentation.
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 */
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]");\
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);\
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
);
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
);
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
);
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
);
133 dissect_distcc_argv(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, gint 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
);
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
);
156 proto_tree_add_text(tree
, tvb
, 0, 0, "[Short ARGV PDU]");
162 dissect_distcc_serr(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, gint 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
);
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
);
185 proto_tree_add_text(tree
, tvb
, 0, 0, "[Short SERR PDU]");
191 dissect_distcc_sout(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, int offset
, gint 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
);
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
);
214 proto_tree_add_text(tree
, tvb
, 0, 0, "[Short SOUT PDU]");
221 dissect_distcc_doti(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, gint 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
);
235 proto_tree_add_text(tree
, tvb
, 0, 0, "[Short DOTI PDU]");
241 dissect_distcc_doto(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, gint 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
);
255 proto_tree_add_text(tree
, tvb
, 0, 0, "[Short DOTO PDU]");
262 /* Packet dissection routine called by tcp (& udp) when port 3632 detected */
264 dissect_distcc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
)
267 proto_tree
*tree
=NULL
;
268 proto_item
*item
=NULL
;
273 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DISTCC ");
275 col_clear(pinfo
->cinfo
, COL_INFO
);
278 item
= proto_tree_add_item(parent_tree
, proto_distcc
, tvb
, offset
,
280 tree
= proto_item_add_subtree(item
, ett_distcc
);
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){
291 tvb_memcpy(tvb
, token
, offset
, 4);
294 /* read the parameter */
295 if (sscanf(tvb_get_ptr(tvb
, offset
, 8), "%08x", ¶meter
) != 1)
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
);
318 call_dissector(data_handle
, tvb
, pinfo
, tree
);
326 /* Register protocol with Wireshark. */
328 proto_register_distcc(void)
330 static hf_register_info hf
[] = {
332 {"DISTCC Version", "distcc.version",
333 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
336 {"ARGC", "distcc.argc",
337 FT_UINT32
, BASE_DEC
, NULL
, 0x0, "Number of arguments", HFILL
}
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
}
348 {"Status", "distcc.status",
349 FT_UINT32
, BASE_DEC
, NULL
, 0x0, "Unix wait status for command completion", HFILL
}
352 {"SERR", "distcc.serr",
353 FT_STRING
, BASE_NONE
, NULL
, 0x0, "STDERR output", HFILL
}
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
[] = {
370 module_t
*distcc_module
;
372 proto_distcc
= proto_register_protocol("Distcc Distributed Compiler",
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",
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.",
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
403 distcc_handle
= create_dissector_handle(dissect_distcc
,
405 data_handle
= find_dissector("data");
406 registered_dissector
= TRUE
;
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
);