2 * Routines for distcc dissection
3 * Copyright 2003, Brad Hards <bradh@frogmouth.net>
4 * Copyright 2003, Ronnie Sahlberg, added TCP desegmentation.
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 * This dissector supports version 1 of the DISTCC protocol:
16 * https://github.com/distcc/distcc/blob/master/doc/protocol-1.txt
21 #include <epan/packet.h>
22 #include <epan/expert.h>
23 #include <epan/prefs.h>
25 #include <wsutil/strtoi.h>
27 static int proto_distcc
;
28 static int hf_distcc_version
;
29 static int hf_distcc_argc
;
30 static int hf_distcc_argv
;
31 static int hf_distcc_doti_source
;
32 static int hf_distcc_stat
;
33 static int hf_distcc_serr
;
34 static int hf_distcc_sout
;
35 static int hf_distcc_doto_object
;
38 static int ett_distcc
;
40 static expert_field ei_distcc_short_pdu
;
43 static bool distcc_desegment
= true;
46 #define TCP_PORT_DISTCC 3632
48 void proto_register_distcc(void);
49 extern void proto_reg_handoff_distcc(void);
51 static dissector_handle_t distcc_handle
;
53 #define CHECK_PDU_LEN(x) \
54 if(parameter>(unsigned)tvb_captured_length_remaining(tvb, offset) || parameter < 1){\
55 len=tvb_captured_length_remaining(tvb, offset);\
56 col_append_str(pinfo->cinfo, COL_INFO, "[Short" x " PDU]");\
58 tvb_ensure_bytes_exist(tvb, offset, len);
61 #define DESEGMENT_TCP(x) \
62 if(distcc_desegment && pinfo->can_desegment){\
63 /* only attempt reassembly if we have the full segment */\
64 if(tvb_captured_length_remaining(tvb, offset)==tvb_reported_length_remaining(tvb, offset)){\
65 if(parameter>(unsigned)tvb_captured_length_remaining(tvb, offset)){\
66 proto_tree_add_expert_format(tree, pinfo, &ei_distcc_short_pdu, tvb, offset-12, -1, "[Short " x " PDU]");\
67 pinfo->desegment_offset=offset-12;\
68 pinfo->desegment_len=parameter-tvb_captured_length_remaining(tvb, offset);\
75 dissect_distcc_dist(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint32_t parameter
)
77 proto_tree_add_uint_format(tree
, hf_distcc_version
, tvb
, offset
-12, 12, parameter
, "DIST: %u", parameter
);
79 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "DIST:%u ", parameter
);
85 dissect_distcc_done(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint32_t parameter
)
87 proto_tree_add_uint_format(tree
, hf_distcc_version
, tvb
, offset
-12, 12, parameter
, "DONE: %u", parameter
);
89 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "DONE:%u ", parameter
);
95 dissect_distcc_stat(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint32_t parameter
)
97 proto_tree_add_uint_format(tree
, hf_distcc_stat
, tvb
, offset
-12, 12, parameter
, "STAT: %u", parameter
);
99 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "STAT:%u ", parameter
);
105 dissect_distcc_argc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, uint32_t parameter
)
107 proto_tree_add_uint(tree
, hf_distcc_argc
, tvb
, offset
-12, 12, parameter
);
109 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "ARGC:%u ", parameter
);
115 dissect_distcc_argv(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, unsigned parameter
)
117 int len
=(int)parameter
;
121 CHECK_PDU_LEN("ARGV");
123 /* see if we need to desegment the PDU */
124 DESEGMENT_TCP("ARGV");
127 * XXX - we have no idea what encoding is being used, other than
128 * it being some flavor of "extended ASCII"; these days, it's
129 * *probably* UTF-8, but it could conceivably be something else.
131 ti
= proto_tree_add_item_ret_display_string(tree
, hf_distcc_argv
, tvb
, offset
, len
, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &argv
);
133 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", argv
);
135 if(len
!=(int)parameter
){
136 expert_add_info_format(pinfo
, ti
, &ei_distcc_short_pdu
, "[Short ARGV PDU]");
142 dissect_distcc_serr(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, unsigned parameter
)
144 int len
=(int)parameter
;
148 CHECK_PDU_LEN("SERR");
150 /* see if we need to desegment the PDU */
151 DESEGMENT_TCP("SERR");
154 * XXX - we have no idea what encoding is being used, other than
155 * it being some flavor of "extended ASCII"; these days, it's
156 * *probably* UTF-8, but it could conceivably be something else.
158 ti
= proto_tree_add_item_ret_display_string(tree
, hf_distcc_serr
, tvb
, offset
, len
, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &serr
);
160 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "SERR:%s ", serr
);
162 if(len
!=(int)parameter
){
163 expert_add_info_format(pinfo
, ti
, &ei_distcc_short_pdu
, "[Short SERR PDU]");
169 dissect_distcc_sout(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, unsigned parameter
)
171 int len
=(int)parameter
;
175 CHECK_PDU_LEN("SOUT");
177 /* see if we need to desegment the PDU */
178 DESEGMENT_TCP("SOUT");
181 * XXX - we have no idea what encoding is being used, other than
182 * it being some flavor of "extended ASCII"; these days, it's
183 * *probably* UTF-8, but it could conceivably be something else.
185 ti
= proto_tree_add_item_ret_display_string(tree
, hf_distcc_sout
, tvb
, offset
, len
, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &sout
);
187 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "SOUT:%s ", sout
);
189 if(len
!=(int)parameter
){
190 expert_add_info_format(pinfo
, ti
, &ei_distcc_short_pdu
, "[Short SOUT PDU]");
197 dissect_distcc_doti(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, unsigned parameter
)
199 int len
=(int)parameter
;
202 CHECK_PDU_LEN("DOTI");
204 /* see if we need to desegment the PDU */
205 DESEGMENT_TCP("DOTI");
207 col_append_str(pinfo
->cinfo
, COL_INFO
, "DOTI source ");
209 ti
= proto_tree_add_item(tree
, hf_distcc_doti_source
, tvb
, offset
, len
, ENC_ASCII
);
211 if(len
!=(int)parameter
){
212 expert_add_info_format(pinfo
, ti
, &ei_distcc_short_pdu
, "[Short DOTI PDU]");
218 dissect_distcc_doto(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int offset
, unsigned parameter
)
220 int len
=(int)parameter
;
223 CHECK_PDU_LEN("DOTO");
225 /* see if we need to desegment the PDU */
226 DESEGMENT_TCP("DOTO");
228 col_append_str(pinfo
->cinfo
, COL_INFO
, "DOTO object ");
230 ti
= proto_tree_add_item(tree
, hf_distcc_doto_object
, tvb
, offset
, len
, ENC_NA
);
232 if(len
!=(int)parameter
){
233 expert_add_info_format(pinfo
, ti
, &ei_distcc_short_pdu
, "[Short DOTO PDU]");
240 /* Packet dissection routine called by tcp (& udp) when port 3632 detected */
242 dissect_distcc(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, void* data _U_
)
245 proto_tree
*tree
=NULL
;
246 proto_item
*item
=NULL
;
251 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DISTCC ");
253 col_clear(pinfo
->cinfo
, COL_INFO
);
256 item
= proto_tree_add_item(parent_tree
, proto_distcc
, tvb
, offset
,
258 tree
= proto_item_add_subtree(item
, ett_distcc
);
262 /* read the raw token (4 bytes) and parameter (8 bytes) */
263 tvb_memcpy(tvb
, buf
, offset
, 12);
267 /* get the parameter value */
268 if (!ws_hexstrtou32(buf
+ 4, NULL
, ¶meter
))
271 if(!strncmp(buf
, "DIST", 4)){
272 offset
=dissect_distcc_dist(tvb
, pinfo
, tree
, offset
, parameter
);
273 } else if(!strncmp(buf
, "ARGC", 4)){
274 offset
=dissect_distcc_argc(tvb
, pinfo
, tree
, offset
, parameter
);
275 } else if(!strncmp(buf
, "ARGV", 4)){
276 offset
=dissect_distcc_argv(tvb
, pinfo
, tree
, offset
, parameter
);
277 } else if(!strncmp(buf
, "DOTI", 4)){
278 offset
=dissect_distcc_doti(tvb
, pinfo
, tree
, offset
, parameter
);
279 } else if(!strncmp(buf
, "DONE", 4)){
280 offset
=dissect_distcc_done(tvb
, pinfo
, tree
, offset
, parameter
);
281 } else if(!strncmp(buf
, "STAT", 4)){
282 offset
=dissect_distcc_stat(tvb
, pinfo
, tree
, offset
, parameter
);
283 } else if(!strncmp(buf
, "SERR", 4)){
284 offset
=dissect_distcc_serr(tvb
, pinfo
, tree
, offset
, parameter
);
285 } else if(!strncmp(buf
, "SOUT", 4)){
286 offset
=dissect_distcc_sout(tvb
, pinfo
, tree
, offset
, parameter
);
287 } else if(!strncmp(buf
, "DOTO", 4)){
288 offset
=dissect_distcc_doto(tvb
, pinfo
, tree
, offset
, parameter
);
290 call_data_dissector(tvb
, pinfo
, tree
);
295 return tvb_captured_length(tvb
);
298 /* Register protocol with Wireshark. */
300 proto_register_distcc(void)
302 static hf_register_info hf
[] = {
304 {"DISTCC Version", "distcc.version",
305 FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}
308 {"ARGC", "distcc.argc",
309 FT_UINT32
, BASE_DEC
, NULL
, 0x0, "Number of arguments", HFILL
}
312 {"ARGV", "distcc.argv",
313 FT_STRING
, BASE_NONE
, NULL
, 0x0, "ARGV argument", HFILL
}
315 {&hf_distcc_doti_source
,
316 {"Source", "distcc.doti_source",
317 FT_STRING
, BASE_NONE
, NULL
, 0x0, "DOTI Preprocessed Source File (.i)", HFILL
}
320 {"Status", "distcc.status",
321 FT_UINT32
, BASE_DEC
, NULL
, 0x0, "Unix wait status for command completion", HFILL
}
324 {"SERR", "distcc.serr",
325 FT_STRING
, BASE_NONE
, NULL
, 0x0, "STDERR output", HFILL
}
328 {"SOUT", "distcc.sout",
329 FT_STRING
, BASE_NONE
, NULL
, 0x0, "STDOUT output", HFILL
}
331 {&hf_distcc_doto_object
,
332 {"Object", "distcc.doto_object",
333 FT_BYTES
, BASE_NONE
, NULL
, 0x0, "DOTO Compiled object file (.o)", HFILL
}
338 static int *ett
[] = {
342 static ei_register_info ei
[] = {
343 { &ei_distcc_short_pdu
, { "distcc.short_pdu", PI_MALFORMED
, PI_ERROR
, "Short PDU", EXPFILL
}},
346 module_t
*distcc_module
;
347 expert_module_t
* expert_distcc
;
349 proto_distcc
= proto_register_protocol("Distcc Distributed Compiler", "DISTCC", "distcc");
351 proto_register_field_array(proto_distcc
, hf
, array_length(hf
));
352 proto_register_subtree_array(ett
, array_length(ett
));
353 expert_distcc
= expert_register_protocol(proto_distcc
);
354 expert_register_field_array(expert_distcc
, ei
, array_length(ei
));
356 distcc_module
= prefs_register_protocol(proto_distcc
, NULL
);
358 prefs_register_bool_preference(distcc_module
, "desegment_distcc_over_tcp",
359 "Reassemble DISTCC-over-TCP messages spanning multiple TCP segments",
360 "Whether the DISTCC dissector should reassemble messages spanning multiple TCP segments."
361 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
364 distcc_handle
= register_dissector("distcc", dissect_distcc
, proto_distcc
);
368 proto_reg_handoff_distcc(void)
370 dissector_add_uint_with_preference("tcp.port", TCP_PORT_DISTCC
, distcc_handle
);
374 * Editor modelines - https://www.wireshark.org/tools/modelines.html
379 * indent-tabs-mode: nil
382 * vi: set shiftwidth=4 tabstop=8 expandtab:
383 * :indentSize=4:tabSize=8:noTabs=true: