2 * Routines for Gearman protocol packet disassembly
3 * By Flier Lu <flier.lu@gmail.com>
4 * Copyright 2010 Flier Lu
8 * http://gearman.org/index.php?id=protocol
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <epan/packet.h>
34 #include <epan/prefs.h>
35 #include <epan/expert.h>
36 #include "packet-tcp.h"
38 static int proto_gearman
= -1;
40 static int hf_gearman_mgr_cmd
= -1;
41 static int hf_gearman_magic_code
= -1;
42 static int hf_gearman_pkt_type
= -1;
43 static int hf_gearman_data_size
= -1;
44 static int hf_gearman_data_content
= -1;
45 static int hf_gearman_option_name
= -1;
46 static int hf_gearman_func_name
= -1;
47 static int hf_gearman_func_namez
= -1;
48 static int hf_gearman_client_id
= -1;
49 static int hf_gearman_uniq_id
= -1;
50 static int hf_gearman_argument
= -1;
51 static int hf_gearman_job_handle
= -1;
52 static int hf_gearman_job_handlez
= -1;
53 static int hf_gearman_complete_numerator
= -1;
54 static int hf_gearman_complete_denominator
= -1;
55 static int hf_gearman_submit_job_sched_minute
= -1;
56 static int hf_gearman_submit_job_sched_hour
= -1;
57 static int hf_gearman_submit_job_sched_day_of_month
= -1;
58 static int hf_gearman_submit_job_sched_month
= -1;
59 static int hf_gearman_submit_job_sched_day_of_week
= -1;
60 static int hf_gearman_submit_job_epoch_time
= -1;
61 static int hf_gearman_result
= -1;
62 static int hf_gearman_known_status
= -1;
63 static int hf_gearman_running_status
= -1;
64 static int hf_gearman_echo_text
= -1;
65 static int hf_gearman_err_code
= -1;
66 static int hf_gearman_err_text
= -1;
68 static gint ett_gearman
= -1;
69 static gint ett_gearman_command
= -1;
70 static gint ett_gearman_content
= -1;
72 static expert_field ei_gearman_pkt_type_unknown
= EI_INIT
;
74 static gboolean gearman_desegment
= TRUE
;
76 static const int GEARMAN_COMMAND_HEADER_SIZE
= 12;
77 static const int GEARMAN_PORT
= 4730;
78 static const gchar
*GEARMAN_MAGIC_CODE_REQUEST
= "\0REQ";
79 static const gchar
*GEARMAN_MAGIC_CODE_RESPONSE
= "\0RES";
81 static const gchar
*GEARMAN_MGR_CMDS
[] = {
89 static const int GEARMAN_MGR_CMDS_COUNT
= sizeof(GEARMAN_MGR_CMDS
)/sizeof(GEARMAN_MGR_CMDS
[0]);
94 GEARMAN_COMMAND_CAN_DO
, /* W->J: FUNC */
95 GEARMAN_COMMAND_CANT_DO
, /* W->J: FUNC */
96 GEARMAN_COMMAND_RESET_ABILITIES
, /* W->J: -- */
97 GEARMAN_COMMAND_PRE_SLEEP
, /* W->J: -- */
98 GEARMAN_COMMAND_UNUSED
,
99 GEARMAN_COMMAND_NOOP
, /* J->W: -- */
100 GEARMAN_COMMAND_SUBMIT_JOB
, /* C->J: FUNC[0]UNIQ[0]ARGS */
101 GEARMAN_COMMAND_JOB_CREATED
, /* J->C: HANDLE */
102 GEARMAN_COMMAND_GRAB_JOB
, /* W->J: -- */
103 GEARMAN_COMMAND_NO_JOB
, /* J->W: -- */
104 GEARMAN_COMMAND_JOB_ASSIGN
, /* J->W: HANDLE[0]FUNC[0]ARG */
105 GEARMAN_COMMAND_WORK_STATUS
, /* W->J/C: HANDLE[0]NUMERATOR[0]DENOMINATOR */
106 GEARMAN_COMMAND_WORK_COMPLETE
, /* W->J/C: HANDLE[0]RES */
107 GEARMAN_COMMAND_WORK_FAIL
, /* W->J/C: HANDLE */
108 GEARMAN_COMMAND_GET_STATUS
, /* C->J: HANDLE */
109 GEARMAN_COMMAND_ECHO_REQ
, /* ?->J: TEXT */
110 GEARMAN_COMMAND_ECHO_RES
, /* J->?: TEXT */
111 GEARMAN_COMMAND_SUBMIT_JOB_BG
, /* C->J: FUNC[0]UNIQ[0]ARGS */
112 GEARMAN_COMMAND_ERROR
, /* J->?: ERRCODE[0]ERR_TEXT */
113 GEARMAN_COMMAND_STATUS_RES
, /* C->J: HANDLE[0]KNOWN[0]RUNNING[0]NUM[0]DENOM */
114 GEARMAN_COMMAND_SUBMIT_JOB_HIGH
, /* C->J: FUNC[0]UNIQ[0]ARGS */
115 GEARMAN_COMMAND_SET_CLIENT_ID
, /* W->J: [RANDOM_STRING_NO_WHITESPACE] */
116 GEARMAN_COMMAND_CAN_DO_TIMEOUT
, /* W->J: FUNC[0]TIMEOUT */
117 GEARMAN_COMMAND_ALL_YOURS
,
118 GEARMAN_COMMAND_WORK_EXCEPTION
,
119 GEARMAN_COMMAND_OPTION_REQ
,
120 GEARMAN_COMMAND_OPTION_RES
,
121 GEARMAN_COMMAND_WORK_DATA
,
122 GEARMAN_COMMAND_WORK_WARNING
,
123 GEARMAN_COMMAND_GRAB_JOB_UNIQ
,
124 GEARMAN_COMMAND_JOB_ASSIGN_UNIQ
,
125 GEARMAN_COMMAND_SUBMIT_JOB_HIGH_BG
,
126 GEARMAN_COMMAND_SUBMIT_JOB_LOW
,
127 GEARMAN_COMMAND_SUBMIT_JOB_LOW_BG
,
128 GEARMAN_COMMAND_SUBMIT_JOB_SCHED
,
129 GEARMAN_COMMAND_SUBMIT_JOB_EPOCH
,
130 GEARMAN_COMMAND_MAX
/* Always add new commands before this. */
133 static const value_string gearman_command_names
[] = {
134 { GEARMAN_COMMAND_TEXT
, "TEXT" },
135 { GEARMAN_COMMAND_CAN_DO
, "CAN_DO" }, /* W->J: FUNC */
136 { GEARMAN_COMMAND_CANT_DO
, "CANT_DO" }, /* W->J: FUNC */
137 { GEARMAN_COMMAND_RESET_ABILITIES
, "RESET_ABILITIES" }, /* W->J: -- */
138 { GEARMAN_COMMAND_PRE_SLEEP
, "PRE_SLEEP" }, /* W->J: -- */
139 { GEARMAN_COMMAND_UNUSED
, "UNUSED" },
140 { GEARMAN_COMMAND_NOOP
, "NOOP" }, /* J->W: -- */
141 { GEARMAN_COMMAND_SUBMIT_JOB
, "SUBMIT_JOB" }, /* C->J: FUNC[0]UNIQ[0]ARGS */
142 { GEARMAN_COMMAND_JOB_CREATED
, "JOB_CREATED" }, /* J->C: HANDLE */
143 { GEARMAN_COMMAND_GRAB_JOB
, "GRAB_JOB" }, /* W->J: -- */
144 { GEARMAN_COMMAND_NO_JOB
, "NO_JOB" }, /* J->W: -- */
145 { GEARMAN_COMMAND_JOB_ASSIGN
, "JOB_ASSIGN" }, /* J->W: HANDLE[0]FUNC[0]ARG */
146 { GEARMAN_COMMAND_WORK_STATUS
, "WORK_STATUS" }, /* W->J/C: HANDLE[0]NUMERATOR[0]DENOMINATOR */
147 { GEARMAN_COMMAND_WORK_COMPLETE
, "WORK_COMPLETE" }, /* W->J/C: HANDLE[0]RES */
148 { GEARMAN_COMMAND_WORK_FAIL
, "WORK_FAIL" }, /* W->J/C: HANDLE */
149 { GEARMAN_COMMAND_GET_STATUS
, "GET_STATUS" }, /* C->J: HANDLE */
150 { GEARMAN_COMMAND_ECHO_REQ
, "ECHO_REQ" }, /* ?->J: TEXT */
151 { GEARMAN_COMMAND_ECHO_RES
, "ECHO_RES" }, /* J->?: TEXT */
152 { GEARMAN_COMMAND_SUBMIT_JOB_BG
, "SUBMIT_JOB_BG" }, /* C->J: FUNC[0]UNIQ[0]ARGS */
153 { GEARMAN_COMMAND_ERROR
, "ERROR" }, /* J->?: ERRCODE[0]ERR_TEXT */
154 { GEARMAN_COMMAND_STATUS_RES
, "STATUS_RES" }, /* C->J: HANDLE[0]KNOWN[0]RUNNING[0]NUM[0]DENOM */
155 { GEARMAN_COMMAND_SUBMIT_JOB_HIGH
, "SUBMIT_JOB_HIGH" }, /* C->J: FUNC[0]UNIQ[0]ARGS */
156 { GEARMAN_COMMAND_SET_CLIENT_ID
, "SET_CLIENT_ID" }, /* W->J: [RANDOM_STRING_NO_WHITESPACE] */
157 { GEARMAN_COMMAND_CAN_DO_TIMEOUT
, "CAN_DO_TIMEOUT" }, /* W->J: FUNC[0]TIMEOUT */
158 { GEARMAN_COMMAND_ALL_YOURS
, "ALL_YOURS" },
159 { GEARMAN_COMMAND_WORK_EXCEPTION
, "WORK_EXCEPTION" },
160 { GEARMAN_COMMAND_OPTION_REQ
, "OPTION_REQ" },
161 { GEARMAN_COMMAND_OPTION_RES
, "OPTION_RES" },
162 { GEARMAN_COMMAND_WORK_DATA
, "WORK_DATA" },
163 { GEARMAN_COMMAND_WORK_WARNING
, "WORK_WARNING" },
164 { GEARMAN_COMMAND_GRAB_JOB_UNIQ
, "GRAB_JOB_UNIQ" },
165 { GEARMAN_COMMAND_JOB_ASSIGN_UNIQ
, "JOB_ASSIGN_UNIQ" },
166 { GEARMAN_COMMAND_SUBMIT_JOB_HIGH_BG
, "SUBMIT_JOB_HIGH_BG" },
167 { GEARMAN_COMMAND_SUBMIT_JOB_LOW
, "SUBMIT_JOB_LOW" },
168 { GEARMAN_COMMAND_SUBMIT_JOB_LOW_BG
, "SUBMIT_JOB_LOW_BG" },
169 { GEARMAN_COMMAND_SUBMIT_JOB_SCHED
, "SUBMIT_JOB_SCHED" },
170 { GEARMAN_COMMAND_SUBMIT_JOB_EPOCH
, "SUBMIT_JOB_EPOCH" },
175 get_gearman_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
)
177 return tvb_get_ntohl(tvb
, offset
+8)+GEARMAN_COMMAND_HEADER_SIZE
;
181 dissect_binary_packet(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
183 gint offset
, start_offset
;
187 proto_item
*content_item
= NULL
;
188 proto_tree
*content_tree
= NULL
;
190 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "Gearman");
191 col_clear(pinfo
->cinfo
,COL_INFO
);
193 magic_code
= tvb_get_string(wmem_packet_scope(), tvb
, 1, 3);
194 type
= tvb_get_ntohl(tvb
, 4);
195 size
= tvb_get_ntohl(tvb
, 8);
197 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, " , ", "[%s] ", magic_code
);
199 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s(%d) LEN=%d",
200 val_to_str(type
, gearman_command_names
, "Unknown (0x%08x)"), type
, size
);
204 proto_tree
*command_tree
, *gearman_tree
;
205 ti
= proto_tree_add_item(tree
, proto_gearman
, tvb
, 0, -1, ENC_NA
);
206 gearman_tree
= proto_item_add_subtree(ti
, ett_gearman
);
208 ti
= proto_tree_add_text(gearman_tree
, tvb
, 0, GEARMAN_COMMAND_HEADER_SIZE
+size
,
209 "[%s] %s(%d) LEN=%d", magic_code
, val_to_str(type
, gearman_command_names
, "Unknown (0x%08x)"), type
, size
);
210 command_tree
= proto_item_add_subtree(ti
, ett_gearman_command
);
212 proto_tree_add_string(command_tree
, hf_gearman_magic_code
, tvb
, 0, 4, magic_code
);
213 proto_tree_add_item(command_tree
, hf_gearman_pkt_type
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
214 proto_tree_add_item(command_tree
, hf_gearman_data_size
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
216 content_item
= proto_tree_add_item(command_tree
, hf_gearman_data_content
, tvb
, GEARMAN_COMMAND_HEADER_SIZE
, size
, ENC_ASCII
|ENC_NA
);
217 content_tree
= proto_item_add_subtree(content_item
, ett_gearman_content
);
220 offset
= GEARMAN_COMMAND_HEADER_SIZE
;
224 case GEARMAN_COMMAND_ECHO_REQ
:
225 case GEARMAN_COMMAND_ECHO_RES
:
227 proto_tree_add_item(content_tree
, hf_gearman_echo_text
, tvb
,
228 offset
, size
, ENC_NA
|ENC_ASCII
);
231 case GEARMAN_COMMAND_ERROR
:
233 len
= tvb_strsize(tvb
, offset
);
234 proto_tree_add_item(content_tree
, hf_gearman_err_code
, tvb
, offset
, len
, ENC_NA
|ENC_ASCII
);
235 proto_tree_add_item(content_tree
, hf_gearman_err_text
, tvb
, offset
+len
, size
-len
, ENC_NA
|ENC_ASCII
);
238 case GEARMAN_COMMAND_JOB_CREATED
:
239 case GEARMAN_COMMAND_WORK_FAIL
:
241 proto_tree_add_item(content_tree
, hf_gearman_job_handle
, tvb
,
242 offset
, size
, ENC_NA
|ENC_ASCII
);
245 case GEARMAN_COMMAND_STATUS_RES
:
247 start_offset
= offset
;
248 len
= tvb_strsize(tvb
, start_offset
);
249 proto_tree_add_item(content_tree
, hf_gearman_job_handlez
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
252 len
= tvb_strsize(tvb
, start_offset
);
253 proto_tree_add_item(content_tree
, hf_gearman_known_status
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
256 len
= tvb_strsize(tvb
, start_offset
);
257 proto_tree_add_item(content_tree
, hf_gearman_running_status
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
260 len
= tvb_strsize(tvb
, start_offset
);
261 proto_tree_add_item(content_tree
, hf_gearman_complete_numerator
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
263 proto_tree_add_item(content_tree
, hf_gearman_complete_denominator
, tvb
, start_offset
+len
, size
-start_offset
+GEARMAN_COMMAND_HEADER_SIZE
, ENC_NA
|ENC_ASCII
);
266 case GEARMAN_COMMAND_OPTION_REQ
:
267 case GEARMAN_COMMAND_OPTION_RES
:
269 proto_tree_add_item(content_tree
, hf_gearman_option_name
, tvb
,
270 offset
, size
, ENC_NA
|ENC_ASCII
);
273 case GEARMAN_COMMAND_SUBMIT_JOB
:
274 case GEARMAN_COMMAND_SUBMIT_JOB_BG
:
275 case GEARMAN_COMMAND_SUBMIT_JOB_HIGH
:
276 case GEARMAN_COMMAND_SUBMIT_JOB_HIGH_BG
:
277 case GEARMAN_COMMAND_SUBMIT_JOB_LOW
:
278 case GEARMAN_COMMAND_SUBMIT_JOB_LOW_BG
:
280 start_offset
= offset
;
281 len
= tvb_strsize(tvb
, start_offset
);
282 proto_tree_add_item(content_tree
, hf_gearman_func_name
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
285 len
= tvb_strsize(tvb
, start_offset
);
286 proto_tree_add_item(content_tree
, hf_gearman_uniq_id
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
288 proto_tree_add_item(content_tree
, hf_gearman_argument
, tvb
, start_offset
+len
, size
-start_offset
+GEARMAN_COMMAND_HEADER_SIZE
, ENC_NA
|ENC_ASCII
);
291 case GEARMAN_COMMAND_SUBMIT_JOB_SCHED
:
293 start_offset
= offset
;
294 len
= tvb_strsize(tvb
, start_offset
);
295 proto_tree_add_item(content_tree
, hf_gearman_func_name
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
298 len
= tvb_strsize(tvb
, start_offset
);
299 proto_tree_add_item(content_tree
, hf_gearman_uniq_id
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
302 len
= tvb_strsize(tvb
, start_offset
);
303 proto_tree_add_item(content_tree
, hf_gearman_submit_job_sched_minute
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
306 len
= tvb_strsize(tvb
, start_offset
);
307 proto_tree_add_item(content_tree
, hf_gearman_submit_job_sched_hour
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
310 len
= tvb_strsize(tvb
, start_offset
);
311 proto_tree_add_item(content_tree
, hf_gearman_submit_job_sched_day_of_month
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
314 len
= tvb_strsize(tvb
, start_offset
);
315 proto_tree_add_item(content_tree
, hf_gearman_submit_job_sched_month
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
318 len
= tvb_strsize(tvb
, start_offset
);
319 proto_tree_add_item(content_tree
, hf_gearman_submit_job_sched_day_of_week
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
321 proto_tree_add_item(content_tree
, hf_gearman_argument
, tvb
, start_offset
+len
, size
-start_offset
+GEARMAN_COMMAND_HEADER_SIZE
, ENC_NA
|ENC_ASCII
);
324 case GEARMAN_COMMAND_SUBMIT_JOB_EPOCH
:
326 start_offset
= offset
;
327 len
= tvb_strsize(tvb
, start_offset
);
328 proto_tree_add_item(content_tree
, hf_gearman_func_name
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
331 len
= tvb_strsize(tvb
, start_offset
);
332 proto_tree_add_item(content_tree
, hf_gearman_uniq_id
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
335 len
= tvb_strsize(tvb
, start_offset
);
336 proto_tree_add_item(content_tree
, hf_gearman_submit_job_epoch_time
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
338 proto_tree_add_item(content_tree
, hf_gearman_argument
, tvb
, start_offset
+len
, size
-start_offset
+GEARMAN_COMMAND_HEADER_SIZE
, ENC_NA
|ENC_ASCII
);
341 case GEARMAN_COMMAND_JOB_ASSIGN
:
342 start_offset
= offset
;
343 len
= tvb_strsize(tvb
, start_offset
);
344 proto_tree_add_item(content_tree
, hf_gearman_job_handlez
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
347 len
= tvb_strsize(tvb
, start_offset
);
348 proto_tree_add_item(content_tree
, hf_gearman_func_namez
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
350 proto_tree_add_item(content_tree
, hf_gearman_argument
, tvb
, start_offset
+len
, size
-start_offset
+GEARMAN_COMMAND_HEADER_SIZE
, ENC_NA
|ENC_ASCII
);
353 case GEARMAN_COMMAND_JOB_ASSIGN_UNIQ
:
354 start_offset
= offset
;
355 len
= tvb_strsize(tvb
, start_offset
);
356 proto_tree_add_item(content_tree
, hf_gearman_job_handlez
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
359 len
= tvb_strsize(tvb
, start_offset
);
360 proto_tree_add_item(content_tree
, hf_gearman_func_namez
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
363 len
= tvb_strsize(tvb
, start_offset
);
364 proto_tree_add_item(content_tree
, hf_gearman_uniq_id
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
366 proto_tree_add_item(content_tree
, hf_gearman_argument
, tvb
, start_offset
+len
, size
-start_offset
+GEARMAN_COMMAND_HEADER_SIZE
, ENC_NA
|ENC_ASCII
);
369 case GEARMAN_COMMAND_CAN_DO
:
370 case GEARMAN_COMMAND_CANT_DO
:
372 proto_tree_add_item(content_tree
, hf_gearman_func_name
, tvb
,
373 offset
, size
, ENC_NA
|ENC_ASCII
);
376 case GEARMAN_COMMAND_CAN_DO_TIMEOUT
:
378 proto_tree_add_item(content_tree
, hf_gearman_func_name
, tvb
,
379 offset
, tvb_strsize(tvb
, offset
), ENC_NA
|ENC_ASCII
);
382 case GEARMAN_COMMAND_WORK_DATA
:
383 case GEARMAN_COMMAND_WORK_WARNING
:
384 case GEARMAN_COMMAND_WORK_COMPLETE
:
385 case GEARMAN_COMMAND_WORK_EXCEPTION
:
387 len
= tvb_strsize(tvb
, offset
);
388 proto_tree_add_item(content_tree
, hf_gearman_job_handlez
, tvb
, offset
, len
, ENC_NA
|ENC_ASCII
);
389 proto_tree_add_item(content_tree
, hf_gearman_result
, tvb
, offset
+len
, size
-len
, ENC_NA
|ENC_ASCII
);
392 case GEARMAN_COMMAND_WORK_STATUS
:
394 start_offset
= offset
;
395 len
= tvb_strsize(tvb
, start_offset
);
396 proto_tree_add_item(content_tree
, hf_gearman_job_handlez
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
399 len
= tvb_strsize(tvb
, start_offset
);
400 proto_tree_add_item(content_tree
, hf_gearman_complete_numerator
, tvb
, start_offset
, len
, ENC_NA
|ENC_ASCII
);
402 proto_tree_add_item(content_tree
, hf_gearman_complete_denominator
, tvb
, start_offset
+len
, size
-start_offset
+GEARMAN_COMMAND_HEADER_SIZE
, ENC_NA
|ENC_ASCII
);
405 case GEARMAN_COMMAND_SET_CLIENT_ID
:
407 proto_tree_add_item(content_tree
, hf_gearman_client_id
, tvb
,
408 offset
, size
, ENC_NA
|ENC_ASCII
);
413 expert_add_info(pinfo
, content_item
, &ei_gearman_pkt_type_unknown
);
416 col_set_fence(pinfo
->cinfo
, COL_INFO
);
417 return tvb_length(tvb
);
421 dissect_management_packet(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
423 int i
, type
= 0, cmdlen
, linelen
, offset
= 0, next_offset
= 0;
425 proto_tree
*gearman_tree
;
427 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "Gearman");
428 col_clear(pinfo
->cinfo
, COL_INFO
);
430 ti
= proto_tree_add_item(tree
, proto_gearman
, tvb
, 0, -1, ENC_NA
);
431 gearman_tree
= proto_item_add_subtree(ti
, ett_gearman
);
433 while ((linelen
= tvb_find_line_end(tvb
, offset
, -1, &next_offset
, FALSE
)) > 0)
435 for (i
=0; i
<GEARMAN_MGR_CMDS_COUNT
; i
++)
437 /* the array is a const and clearly none of the elements are longer than
438 * MAX_SIGNED_INT so this is a safe cast */
439 cmdlen
= (int)strlen(GEARMAN_MGR_CMDS
[i
]);
441 if (cmdlen
== linelen
&& 0 == tvb_strneql(tvb
, offset
, GEARMAN_MGR_CMDS
[i
], cmdlen
))
443 proto_tree_add_item(gearman_tree
, hf_gearman_mgr_cmd
, tvb
, offset
, cmdlen
, ENC_ASCII
|ENC_NA
);
444 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "[MGR] %s", tvb_get_string(wmem_packet_scope(), tvb
, offset
, linelen
));
450 if (GEARMAN_MGR_CMDS_COUNT
== i
)
452 proto_tree_add_text(gearman_tree
, tvb
, offset
, next_offset
- offset
,
453 "%s", tvb_format_text(tvb
, offset
, next_offset
- offset
));
457 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "[MGR] %s", tvb_get_string(wmem_packet_scope(), tvb
, offset
, linelen
));
462 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, ",", "%s", tvb_get_string(wmem_packet_scope(), tvb
, offset
, linelen
));
466 offset
= next_offset
;
471 dissect_gearman(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
473 if ((0 == tvb_memeql(tvb
, 0, GEARMAN_MAGIC_CODE_REQUEST
, 4)) ||
474 (0 == tvb_memeql(tvb
, 0, GEARMAN_MAGIC_CODE_RESPONSE
, 4)))
476 tcp_dissect_pdus(tvb
, pinfo
, tree
, gearman_desegment
, GEARMAN_COMMAND_HEADER_SIZE
, get_gearman_pdu_len
, dissect_binary_packet
, data
);
480 dissect_management_packet(tvb
, pinfo
, tree
);
483 return tvb_length(tvb
);
487 proto_register_gearman(void)
489 static hf_register_info hf
[] = {
490 { &hf_gearman_mgr_cmd
, { "Management Command", "gearman.mgr_cmd", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
491 { &hf_gearman_magic_code
, { "Magic Code", "gearman.magic_code", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
492 { &hf_gearman_pkt_type
, { "Packet Type", "gearman.pkt_type", FT_UINT32
, BASE_DEC_HEX
, VALS(gearman_command_names
), 0x0, NULL
, HFILL
} },
493 { &hf_gearman_data_size
, { "Data Length", "gearman.data_size", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
} },
494 { &hf_gearman_data_content
, { "Data Content", "gearman.data_content", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
495 { &hf_gearman_option_name
, { "Option Name", "gearman.opt.name", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
496 { &hf_gearman_func_name
, { "Function Name", "gearman.func.name", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
497 { &hf_gearman_func_namez
, { "Function Name", "gearman.func.name", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
498 { &hf_gearman_client_id
, { "Client ID", "gearman.client_id", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
499 { &hf_gearman_uniq_id
, { "Unique ID", "gearman.uniq_id", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
500 { &hf_gearman_argument
, { "Function Argument", "gearman.func.arg", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
501 { &hf_gearman_job_handle
, { "Job Handle", "gearman.job.handle", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
502 { &hf_gearman_job_handlez
, { "Job Handle", "gearman.job.handle", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
503 { &hf_gearman_complete_numerator
, { "Complete Numerator", "gearman.numerator", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
504 { &hf_gearman_complete_denominator
, { "Complete Denominator", "gearman.denominator", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
505 { &hf_gearman_submit_job_sched_minute
, { "Minute", "gearman.submit_job_sched.minute", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
506 { &hf_gearman_submit_job_sched_hour
, { "Hour", "gearman.submit_job_sched.hour", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
507 { &hf_gearman_submit_job_sched_day_of_month
, { "Day of Month", "gearman.submit_job_sched.day_of_month", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
508 { &hf_gearman_submit_job_sched_month
, { "Month", "gearman.submit_job_sched.month", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
509 { &hf_gearman_submit_job_sched_day_of_week
, { "Day of Week", "gearman.submit_job_sched.day_of_week", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
510 { &hf_gearman_submit_job_epoch_time
, { "Epoch Time", "gearman.submit_job.epoch_time", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
511 { &hf_gearman_result
, { "Function Result", "gearman.func.result", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
512 { &hf_gearman_known_status
, { "Known job", "gearman.job.known", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
513 { &hf_gearman_running_status
, { "Running Job", "gearman.job.running", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
514 { &hf_gearman_echo_text
, { "Echo Text", "gearman.echo_text", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
515 { &hf_gearman_err_code
, { "Error Code", "gearman.err.code", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} },
516 { &hf_gearman_err_text
, { "Error Text", "gearman.err.text", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
} }
519 /* Setup protocol subtree array */
520 static gint
*ett
[] = {
522 &ett_gearman_command
,
526 static ei_register_info ei
[] = {
527 { &ei_gearman_pkt_type_unknown
, { "gearman.pkt_type.unknown", PI_PROTOCOL
, PI_WARN
, "Unknown command", EXPFILL
}},
530 module_t
*gearman_module
;
531 expert_module_t
* expert_gearman
;
533 proto_gearman
= proto_register_protocol("Gearman Protocol", "Gearman", "gearman");
535 proto_register_field_array(proto_gearman
, hf
, array_length(hf
));
536 proto_register_subtree_array(ett
, array_length(ett
));
537 expert_gearman
= expert_register_protocol(proto_gearman
);
538 expert_register_field_array(expert_gearman
, ei
, array_length(ei
));
540 gearman_module
= prefs_register_protocol(proto_gearman
, NULL
);
541 prefs_register_bool_preference(gearman_module
, "desegment",
542 "Desegment all Gearman messages spanning multiple TCP segments",
543 "Whether the Gearman dissector should desegment all messages spanning multiple TCP segments",
549 proto_reg_handoff_gearman(void)
551 dissector_handle_t gearman_handle
;
553 gearman_handle
= new_create_dissector_handle(dissect_gearman
, proto_gearman
);
554 dissector_add_uint("tcp.port", GEARMAN_PORT
, gearman_handle
);
558 * Editor modelines - http://www.wireshark.org/tools/modelines.html
563 * indent-tabs-mode: nil
566 * vi: set shiftwidth=2 tabstop=8 expandtab:
567 * :indentSize=2:tabSize=8:noTabs=true: