/src/wireshark/epan/dissectors/packet-adb_service.c
Line | Count | Source |
1 | | /* packet-adb_service.c |
2 | | * Routines for Android Debug Bridge Services |
3 | | * |
4 | | * Copyright 2014 Michal Labedzki for Tieto Corporation |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | |
15 | | #include <epan/packet.h> |
16 | | #include <epan/prefs.h> |
17 | | #include <epan/expert.h> |
18 | | |
19 | | #include "packet-adb_service.h" |
20 | | |
21 | | static int proto_adb_service; |
22 | | |
23 | | static int hf_service; |
24 | | static int hf_fragment; |
25 | | static int hf_data; |
26 | | static int hf_hex_ascii_length; |
27 | | static int hf_length; |
28 | | static int hf_version; |
29 | | static int hf_hex_ascii_version; |
30 | | static int hf_framebuffer_version; |
31 | | static int hf_framebuffer_depth; |
32 | | static int hf_framebuffer_size; |
33 | | static int hf_framebuffer_width; |
34 | | static int hf_framebuffer_height; |
35 | | static int hf_framebuffer_red_offset; |
36 | | static int hf_framebuffer_red_length; |
37 | | static int hf_framebuffer_blue_offset; |
38 | | static int hf_framebuffer_blue_length; |
39 | | static int hf_framebuffer_green_offset; |
40 | | static int hf_framebuffer_green_length; |
41 | | static int hf_framebuffer_alpha_offset; |
42 | | static int hf_framebuffer_alpha_length; |
43 | | static int hf_framebuffer_pixel; |
44 | | static int hf_framebuffer_red_5; |
45 | | static int hf_framebuffer_green_6; |
46 | | static int hf_framebuffer_blue_5; |
47 | | static int hf_framebuffer_red; |
48 | | static int hf_framebuffer_green; |
49 | | static int hf_framebuffer_blue; |
50 | | static int hf_framebuffer_alpha; |
51 | | static int hf_framebuffer_unused; |
52 | | static int hf_devices; |
53 | | static int hf_stdin; |
54 | | static int hf_stdout; |
55 | | static int hf_pids; |
56 | | static int hf_result; |
57 | | |
58 | | static expert_field ei_incomplete_message; |
59 | | |
60 | | static int ett_adb_service; |
61 | | static int ett_length; |
62 | | static int ett_version; |
63 | | static int ett_pixel; |
64 | | static int ett_data; |
65 | | |
66 | | static dissector_handle_t adb_service_handle; |
67 | | static dissector_handle_t logcat_handle; |
68 | | |
69 | | static bool pref_dissect_more_detail_framebuffer; |
70 | | |
71 | | static wmem_tree_t *fragments; |
72 | | static wmem_tree_t *framebuffer_infos; |
73 | | static wmem_tree_t *continuation_infos; |
74 | | |
75 | | typedef struct _framebuffer_data_t { |
76 | | uint32_t data_in; |
77 | | uint32_t current_size; |
78 | | uint32_t completed_in_frame; |
79 | | |
80 | | uint32_t size; |
81 | | uint32_t red_offset; |
82 | | uint32_t red_length; |
83 | | uint32_t green_offset; |
84 | | uint32_t green_length; |
85 | | uint32_t blue_offset; |
86 | | uint32_t blue_length; |
87 | | uint32_t alpha_offset; |
88 | | uint32_t alpha_length; |
89 | | } framebuffer_data_t; |
90 | | |
91 | | typedef struct _fragment_t { |
92 | | int64_t reassembled_in_frame; |
93 | | int length; |
94 | | uint8_t *data; |
95 | | } fragment_t; |
96 | | |
97 | | typedef struct _continuation_data_t { |
98 | | uint32_t length_in_frame; |
99 | | uint32_t completed_in_frame; |
100 | | int length; |
101 | | } continuation_data_t; |
102 | | |
103 | | void proto_register_adb_service(void); |
104 | | void proto_reg_handoff_adb_service(void); |
105 | | |
106 | | int |
107 | | dissect_ascii_uint32(proto_tree *tree, int hf_hex_ascii, int ett_hex_ascii, |
108 | | int hf_value, tvbuff_t *tvb, int offset, uint32_t *value) |
109 | 0 | { |
110 | 0 | proto_item *sub_item; |
111 | 0 | proto_tree *sub_tree; |
112 | 0 | char hex_ascii[5]; |
113 | |
|
114 | 0 | DISSECTOR_ASSERT(value); |
115 | |
|
116 | 0 | tvb_memcpy(tvb, hex_ascii, offset, 4); |
117 | 0 | hex_ascii[4]='\0'; |
118 | |
|
119 | 0 | sub_item = proto_tree_add_item(tree, hf_hex_ascii, tvb, offset, 4, ENC_NA | ENC_ASCII); |
120 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_hex_ascii); |
121 | |
|
122 | 0 | *value = (uint32_t) g_ascii_strtoull(hex_ascii, NULL, 16); |
123 | |
|
124 | 0 | proto_tree_add_uint(sub_tree, hf_value, tvb, offset, 4, *value); |
125 | 0 | offset += 4; |
126 | |
|
127 | 0 | return offset; |
128 | 0 | } |
129 | | |
130 | | static int |
131 | | dissect_adb_service(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
132 | 0 | { |
133 | 0 | proto_item *main_item; |
134 | 0 | proto_tree *main_tree; |
135 | 0 | proto_item *sub_item; |
136 | 0 | proto_tree *sub_tree; |
137 | 0 | int offset = 0; |
138 | 0 | adb_service_data_t *adb_service_data = (adb_service_data_t *) data; |
139 | 0 | const char *service; |
140 | 0 | wmem_tree_key_t key[5]; |
141 | 0 | wmem_tree_t *subtree; |
142 | 0 | uint32_t i_key; |
143 | 0 | char *display_str; |
144 | |
|
145 | 0 | main_item = proto_tree_add_item(tree, proto_adb_service, tvb, offset, -1, ENC_NA); |
146 | 0 | main_tree = proto_item_add_subtree(main_item, ett_adb_service); |
147 | |
|
148 | 0 | DISSECTOR_ASSERT(adb_service_data); |
149 | |
|
150 | 0 | service = adb_service_data->service; |
151 | |
|
152 | 0 | sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service); |
153 | 0 | proto_item_set_generated(sub_item); |
154 | |
|
155 | 0 | if (g_strcmp0(service, "host:version") == 0) { |
156 | 0 | uint32_t version; |
157 | 0 | uint32_t data_length; |
158 | 0 | continuation_data_t *continuation_data; |
159 | |
|
160 | 0 | DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= array_length(key), "Tree session key is too small"); |
161 | 0 | for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) { |
162 | 0 | key[i_key].length = 1; |
163 | 0 | key[i_key].key = &adb_service_data->session_key[i_key]; |
164 | 0 | } |
165 | 0 | key[i_key].length = 0; |
166 | 0 | key[i_key].key = NULL; |
167 | |
|
168 | 0 | subtree = (wmem_tree_t *) wmem_tree_lookup32_array(continuation_infos, key); |
169 | 0 | continuation_data = (subtree) ? (continuation_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL; |
170 | 0 | if (continuation_data && continuation_data->completed_in_frame < pinfo->num) |
171 | 0 | continuation_data = NULL; |
172 | |
|
173 | 0 | if (!continuation_data || (continuation_data && continuation_data->length_in_frame == pinfo->num)) |
174 | 0 | offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length); |
175 | |
|
176 | 0 | if (!pinfo->fd->visited && !continuation_data && tvb_reported_length_remaining(tvb, offset) < 4) { |
177 | 0 | key[i_key].length = 1; |
178 | 0 | key[i_key++].key = &pinfo->num; |
179 | 0 | key[i_key].length = 0; |
180 | 0 | key[i_key].key = NULL; |
181 | |
|
182 | 0 | continuation_data = wmem_new(wmem_file_scope(), continuation_data_t); |
183 | 0 | continuation_data->length_in_frame = pinfo->num; |
184 | 0 | continuation_data->completed_in_frame = UINT32_MAX; |
185 | 0 | continuation_data->length = data_length; |
186 | |
|
187 | 0 | wmem_tree_insert32_array(continuation_infos, key, continuation_data); |
188 | 0 | continuation_data = NULL; |
189 | 0 | } |
190 | |
|
191 | 0 | if (tvb_reported_length_remaining(tvb, offset) >= 4 || |
192 | 0 | (continuation_data && continuation_data->completed_in_frame == pinfo->num)) { |
193 | 0 | if (!pinfo->fd->visited && continuation_data) { |
194 | 0 | continuation_data->completed_in_frame = pinfo->num; |
195 | 0 | } |
196 | 0 | offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_version, ett_version, hf_version, tvb, offset, &version); |
197 | |
|
198 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " Version=%u", version); |
199 | 0 | } |
200 | |
|
201 | 0 | } else if (g_strcmp0(service, "host:devices") == 0 || |
202 | 0 | g_strcmp0(service, "host:devices-l") == 0 || |
203 | 0 | g_strcmp0(service, "host:track-devices") == 0) { |
204 | 0 | uint32_t data_length; |
205 | |
|
206 | 0 | offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length); |
207 | |
|
208 | 0 | sub_item = proto_tree_add_item(main_tree, hf_devices, tvb, offset, -1, ENC_ASCII); |
209 | 0 | if ((int64_t) data_length < tvb_reported_length_remaining(tvb, offset)) { |
210 | 0 | expert_add_info(pinfo, sub_item, &ei_incomplete_message); |
211 | 0 | } |
212 | 0 | } else if (g_strcmp0(service, "host:get-state") == 0 || |
213 | 0 | g_strcmp0(service, "host:get-serialno") == 0 || |
214 | 0 | g_strcmp0(service, "host:get-devpath") == 0 || |
215 | 0 | g_str_has_prefix(service, "connect:") || |
216 | 0 | g_str_has_prefix(service, "disconnect:")) { |
217 | 0 | uint32_t data_length; |
218 | |
|
219 | 0 | offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length); |
220 | |
|
221 | 0 | sub_item = proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_ASCII); |
222 | 0 | if ((int64_t) data_length < tvb_reported_length_remaining(tvb, offset)) { |
223 | 0 | expert_add_info(pinfo, sub_item, &ei_incomplete_message); |
224 | 0 | } |
225 | 0 | } else if (g_str_has_prefix(service, "framebuffer:")) { |
226 | 0 | framebuffer_data_t *framebuffer_data = NULL; |
227 | |
|
228 | 0 | DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= array_length(key), "Tree session key is too small"); |
229 | 0 | for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) { |
230 | 0 | key[i_key].length = 1; |
231 | 0 | key[i_key].key = &adb_service_data->session_key[i_key]; |
232 | 0 | } |
233 | 0 | key[i_key].length = 0; |
234 | 0 | key[i_key].key = NULL; |
235 | |
|
236 | 0 | subtree = (wmem_tree_t *) wmem_tree_lookup32_array(framebuffer_infos, key); |
237 | 0 | framebuffer_data = (subtree) ? (framebuffer_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL; |
238 | 0 | if (framebuffer_data && framebuffer_data->completed_in_frame < pinfo->num) |
239 | 0 | framebuffer_data = NULL; |
240 | |
|
241 | 0 | if (!pinfo->fd->visited && !framebuffer_data) { |
242 | 0 | key[i_key].length = 1; |
243 | 0 | key[i_key++].key = &pinfo->num; |
244 | 0 | key[i_key].length = 0; |
245 | 0 | key[i_key].key = NULL; |
246 | |
|
247 | 0 | framebuffer_data = wmem_new(wmem_file_scope(), framebuffer_data_t); |
248 | 0 | framebuffer_data->data_in = pinfo->num; |
249 | 0 | framebuffer_data->current_size = 0; |
250 | 0 | framebuffer_data->completed_in_frame = UINT32_MAX; |
251 | 0 | framebuffer_data->size = tvb_get_letohl(tvb, offset + 4 * 2); |
252 | 0 | framebuffer_data->red_offset = tvb_get_letohl(tvb, offset + 4 * 5); |
253 | 0 | framebuffer_data->red_length = tvb_get_letohl(tvb, offset + 4 * 6); |
254 | 0 | framebuffer_data->green_offset = tvb_get_letohl(tvb, offset + 4 * 7); |
255 | 0 | framebuffer_data->green_length = tvb_get_letohl(tvb, offset + 4 * 8); |
256 | 0 | framebuffer_data->blue_offset = tvb_get_letohl(tvb, offset + 4 * 9); |
257 | 0 | framebuffer_data->blue_length = tvb_get_letohl(tvb, offset + 4 * 10); |
258 | 0 | framebuffer_data->alpha_offset = tvb_get_letohl(tvb, offset + 4 * 11); |
259 | 0 | framebuffer_data->alpha_length = tvb_get_letohl(tvb, offset + 4 * 12); |
260 | |
|
261 | 0 | wmem_tree_insert32_array(framebuffer_infos, key, framebuffer_data); |
262 | 0 | } |
263 | |
|
264 | 0 | if (framebuffer_data && framebuffer_data->data_in == pinfo->num) { |
265 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_version, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
266 | 0 | offset += 4; |
267 | |
|
268 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
269 | 0 | offset += 4; |
270 | |
|
271 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_size, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
272 | 0 | offset += 4; |
273 | |
|
274 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_width, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
275 | 0 | offset += 4; |
276 | |
|
277 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_height, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
278 | 0 | offset += 4; |
279 | |
|
280 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_red_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
281 | 0 | offset += 4; |
282 | |
|
283 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_red_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
284 | 0 | offset += 4; |
285 | |
|
286 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_blue_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
287 | 0 | offset += 4; |
288 | |
|
289 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_blue_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
290 | 0 | offset += 4; |
291 | |
|
292 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_green_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
293 | 0 | offset += 4; |
294 | |
|
295 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_green_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
296 | 0 | offset += 4; |
297 | |
|
298 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_alpha_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
299 | 0 | offset += 4; |
300 | |
|
301 | 0 | proto_tree_add_item(main_tree, hf_framebuffer_alpha_length, tvb, offset, 4, ENC_LITTLE_ENDIAN); |
302 | 0 | offset += 4; |
303 | 0 | } |
304 | |
|
305 | 0 | if (tvb_reported_length_remaining(tvb, offset) > 0) { |
306 | 0 | sub_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); |
307 | 0 | sub_tree = proto_item_add_subtree(sub_item, ett_data); |
308 | |
|
309 | 0 | if (!pinfo->fd->visited && framebuffer_data) { |
310 | 0 | framebuffer_data->current_size += tvb_captured_length_remaining(tvb, offset); |
311 | 0 | if (framebuffer_data->current_size >= framebuffer_data->size) |
312 | 0 | framebuffer_data->completed_in_frame = pinfo->num; |
313 | 0 | } |
314 | |
|
315 | 0 | if (pref_dissect_more_detail_framebuffer) { |
316 | 0 | proto_item *pixel_item; |
317 | 0 | proto_tree *pixel_tree; |
318 | |
|
319 | 0 | if (framebuffer_data && |
320 | 0 | framebuffer_data->red_length == 5 && |
321 | 0 | framebuffer_data->green_length == 6 && |
322 | 0 | framebuffer_data->blue_length == 5 && |
323 | 0 | framebuffer_data->red_offset == 11 && |
324 | 0 | framebuffer_data->green_offset == 5 && |
325 | 0 | framebuffer_data->blue_offset == 0) { |
326 | 0 | while (tvb_reported_length_remaining(tvb, offset) > 0) { |
327 | 0 | if (tvb_reported_length_remaining(tvb, offset) < 2) { |
328 | 0 | proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA); |
329 | 0 | offset += 1; |
330 | 0 | } |
331 | |
|
332 | 0 | pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 2, ENC_NA); |
333 | 0 | pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel); |
334 | |
|
335 | 0 | proto_tree_add_item(pixel_tree, hf_framebuffer_blue_5, tvb, offset, 2, ENC_LITTLE_ENDIAN); |
336 | 0 | proto_tree_add_item(pixel_tree, hf_framebuffer_green_6, tvb, offset, 2, ENC_LITTLE_ENDIAN); |
337 | 0 | proto_tree_add_item(pixel_tree, hf_framebuffer_red_5, tvb, offset, 2, ENC_LITTLE_ENDIAN); |
338 | 0 | offset += 2; |
339 | 0 | } |
340 | 0 | } else if (framebuffer_data && |
341 | 0 | framebuffer_data->red_length == 8 && |
342 | 0 | framebuffer_data->green_length == 8 && |
343 | 0 | framebuffer_data->blue_length == 8 && |
344 | 0 | (framebuffer_data->alpha_length == 0 || |
345 | 0 | framebuffer_data->alpha_length == 8)) { |
346 | 0 | while (tvb_reported_length_remaining(tvb, offset) > 0) { |
347 | 0 | if (tvb_reported_length_remaining(tvb, offset) < 3 || (tvb_reported_length_remaining(tvb, offset) < 4 && framebuffer_data->alpha_offset > 0)) { |
348 | 0 | proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA); |
349 | 0 | offset = tvb_captured_length(tvb); |
350 | 0 | break; |
351 | 0 | } |
352 | | |
353 | 0 | pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 3, ENC_NA); |
354 | 0 | pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel); |
355 | |
|
356 | 0 | proto_tree_add_item(pixel_tree, hf_framebuffer_red, tvb, offset + framebuffer_data->red_offset / 8, 1, ENC_LITTLE_ENDIAN); |
357 | 0 | proto_tree_add_item(pixel_tree, hf_framebuffer_green, tvb, offset + framebuffer_data->green_offset / 8, 1, ENC_LITTLE_ENDIAN); |
358 | 0 | proto_tree_add_item(pixel_tree, hf_framebuffer_blue, tvb, offset + framebuffer_data->blue_offset / 8, 1, ENC_LITTLE_ENDIAN); |
359 | |
|
360 | 0 | if (framebuffer_data->alpha_offset > 0) { |
361 | 0 | if (framebuffer_data->alpha_length == 0) |
362 | 0 | proto_tree_add_item(pixel_tree, hf_framebuffer_unused, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN); |
363 | 0 | else |
364 | 0 | proto_tree_add_item(pixel_tree, hf_framebuffer_alpha, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN); |
365 | 0 | offset += 1; |
366 | 0 | proto_item_set_len(pixel_item, 4); |
367 | 0 | } |
368 | 0 | offset += 3; |
369 | 0 | } |
370 | 0 | } else { |
371 | 0 | offset = tvb_captured_length(tvb); |
372 | 0 | } |
373 | 0 | } else { |
374 | 0 | offset = tvb_captured_length(tvb); |
375 | 0 | } |
376 | 0 | } |
377 | 0 | } else if (g_strcmp0(service, "track-jdwp") == 0) { |
378 | 0 | uint32_t data_length; |
379 | |
|
380 | 0 | offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length); |
381 | |
|
382 | 0 | if (tvb_reported_length_remaining(tvb, offset) > 0) { |
383 | 0 | sub_item = proto_tree_add_item(main_tree, hf_pids, tvb, offset, -1, ENC_ASCII); |
384 | 0 | if ((int64_t) data_length < tvb_reported_length_remaining(tvb, offset)) { |
385 | 0 | expert_add_info(pinfo, sub_item, &ei_incomplete_message); |
386 | 0 | } |
387 | 0 | } |
388 | 0 | offset = tvb_captured_length(tvb); |
389 | 0 | } else if ((g_strcmp0(service, "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -B") == 0) || |
390 | 0 | (g_strcmp0(service, "shell:logcat -B") == 0)) { |
391 | 0 | tvbuff_t *next_tvb; |
392 | 0 | tvbuff_t *new_tvb; |
393 | 0 | uint8_t *buffer = NULL; |
394 | 0 | int size = 0; |
395 | 0 | int i_offset = offset; |
396 | 0 | int old_offset; |
397 | 0 | int i_char = 0; |
398 | 0 | uint8_t c1; |
399 | 0 | uint8_t c2 = '\0'; |
400 | 0 | uint16_t payload_length; |
401 | 0 | uint16_t try_header_size; |
402 | 0 | unsigned logcat_length = 0; |
403 | 0 | fragment_t *fragment; |
404 | |
|
405 | 0 | DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= array_length(key), "Tree session key is too small"); |
406 | 0 | for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) { |
407 | 0 | key[i_key].length = 1; |
408 | 0 | key[i_key].key = &adb_service_data->session_key[i_key]; |
409 | 0 | } |
410 | 0 | key[i_key].length = 0; |
411 | 0 | key[i_key].key = NULL; |
412 | |
|
413 | 0 | subtree = (wmem_tree_t *) wmem_tree_lookup32_array(fragments, key); |
414 | 0 | fragment = (subtree) ? (fragment_t *) wmem_tree_lookup32_le(subtree, pinfo->num - 1) : NULL; |
415 | 0 | if (fragment) { |
416 | 0 | if (!pinfo->fd->visited && fragment->reassembled_in_frame == -1) |
417 | 0 | fragment->reassembled_in_frame = pinfo->num; |
418 | |
|
419 | 0 | if (fragment->reassembled_in_frame == pinfo->num) { |
420 | 0 | size += fragment->length; |
421 | 0 | i_char += fragment->length; |
422 | 0 | } |
423 | 0 | } |
424 | |
|
425 | 0 | size += tvb_reported_length_remaining(tvb, i_offset); |
426 | 0 | if (size > 0) { |
427 | 0 | buffer = (uint8_t *) wmem_alloc(pinfo->pool, size); |
428 | 0 | if (fragment && i_char > 0) |
429 | 0 | memcpy(buffer, fragment->data, i_char); |
430 | |
|
431 | 0 | if (i_char >= 1 && buffer[i_char - 1] == '\r' && tvb_get_uint8(tvb, i_offset) == '\n') { |
432 | 0 | buffer[i_char - 1] = '\n'; |
433 | 0 | i_offset += 1; |
434 | 0 | } |
435 | |
|
436 | 0 | c1 = tvb_get_uint8(tvb, i_offset); |
437 | 0 | i_offset += 1; |
438 | 0 | old_offset = i_offset; |
439 | |
|
440 | 0 | while (tvb_reported_length_remaining(tvb, i_offset) > 0) { |
441 | 0 | c2 = tvb_get_uint8(tvb, i_offset); |
442 | |
|
443 | 0 | if (c1 == '\r' && c2 == '\n') { |
444 | 0 | buffer[i_char] = c2; |
445 | 0 | if (tvb_reported_length_remaining(tvb, i_offset) > 1) { |
446 | 0 | c1 = tvb_get_uint8(tvb, i_offset + 1); |
447 | 0 | i_offset += 2; |
448 | 0 | i_char += 1; |
449 | 0 | } else { |
450 | 0 | i_offset += 1; |
451 | 0 | } |
452 | |
|
453 | 0 | continue; |
454 | 0 | } |
455 | | |
456 | 0 | buffer[i_char] = c1; |
457 | 0 | c1 = c2; |
458 | 0 | i_char += 1; |
459 | 0 | i_offset += 1; |
460 | 0 | } |
461 | |
|
462 | 0 | if (tvb_reported_length_remaining(tvb, old_offset) == 0) { |
463 | 0 | buffer[i_char] = c1; |
464 | 0 | i_char += 1; |
465 | 0 | } else if (tvb_reported_length_remaining(tvb, old_offset) > 0) { |
466 | 0 | buffer[i_char] = c2; |
467 | 0 | i_char += 1; |
468 | 0 | } |
469 | |
|
470 | 0 | next_tvb = tvb_new_child_real_data(tvb, buffer, i_char, i_char); |
471 | 0 | add_new_data_source(pinfo, next_tvb, "Logcat"); |
472 | |
|
473 | 0 | i_offset = 0; |
474 | 0 | while (tvb_reported_length_remaining(next_tvb, i_offset) > 0) { |
475 | 0 | if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4) { |
476 | 0 | payload_length = tvb_get_letohs(next_tvb, i_offset); |
477 | 0 | try_header_size = tvb_get_letohs(next_tvb, i_offset + 2); |
478 | |
|
479 | 0 | if (try_header_size != 24) |
480 | 0 | logcat_length = payload_length + 20; |
481 | 0 | else |
482 | 0 | logcat_length = payload_length + 24; |
483 | 0 | } |
484 | |
|
485 | 0 | if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4 && tvb_reported_length_remaining(next_tvb, i_offset) >= logcat_length) { |
486 | 0 | new_tvb = tvb_new_subset_length(next_tvb, i_offset, logcat_length); |
487 | |
|
488 | 0 | call_dissector(logcat_handle, new_tvb, pinfo, main_tree); |
489 | 0 | i_offset += logcat_length; |
490 | 0 | } else { |
491 | |
|
492 | 0 | if (!pinfo->fd->visited) { |
493 | 0 | DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 2 <= array_length(key), "Tree session key is too small"); |
494 | 0 | for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) { |
495 | 0 | key[i_key].length = 1; |
496 | 0 | key[i_key].key = &adb_service_data->session_key[i_key]; |
497 | 0 | } |
498 | 0 | key[i_key].length = 1; |
499 | 0 | key[i_key++].key = &pinfo->num; |
500 | 0 | key[i_key].length = 0; |
501 | 0 | key[i_key].key = NULL; |
502 | |
|
503 | 0 | fragment = wmem_new(wmem_file_scope(), fragment_t); |
504 | |
|
505 | 0 | fragment->length = tvb_captured_length_remaining(next_tvb, i_offset); |
506 | 0 | fragment->data = (uint8_t *) wmem_alloc(wmem_file_scope(), fragment->length); |
507 | 0 | tvb_memcpy(next_tvb, fragment->data, i_offset, fragment->length); |
508 | 0 | fragment->reassembled_in_frame = -1; |
509 | |
|
510 | 0 | wmem_tree_insert32_array(fragments, key, fragment); |
511 | 0 | } |
512 | |
|
513 | 0 | proto_tree_add_item(main_tree, hf_fragment, next_tvb, i_offset, -1, ENC_NA); |
514 | 0 | i_offset = tvb_captured_length(next_tvb); |
515 | 0 | } |
516 | 0 | } |
517 | 0 | } |
518 | |
|
519 | 0 | offset = tvb_captured_length(tvb); |
520 | 0 | } else if (g_str_has_prefix(service, "shell:")) { |
521 | 0 | if (adb_service_data->direction == P2P_DIR_SENT) { |
522 | 0 | proto_tree_add_item_ret_display_string(main_tree, hf_stdin, tvb, offset, -1, ENC_ASCII, pinfo->pool, &display_str); |
523 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " Stdin=<%s>", display_str); |
524 | |
|
525 | 0 | } else { |
526 | 0 | proto_tree_add_item_ret_display_string(main_tree, hf_stdout, tvb, offset, -1, ENC_ASCII, pinfo->pool, &display_str); |
527 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " Stdout=<%s>", display_str); |
528 | 0 | } |
529 | 0 | offset = tvb_captured_length(tvb); |
530 | 0 | } else if (g_str_has_prefix(service, "jdwp:")) { |
531 | | /* TODO */ |
532 | 0 | proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); |
533 | 0 | offset = tvb_captured_length(tvb); |
534 | 0 | } else if (g_str_has_prefix(service, "sync:")) { |
535 | | /* TODO */ |
536 | 0 | proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); |
537 | 0 | offset = tvb_captured_length(tvb); |
538 | 0 | } else if (g_strcmp0(service, "host:list-forward") == 0 || |
539 | 0 | g_str_has_prefix(service, "root:") || |
540 | 0 | g_str_has_prefix(service, "remount:") || |
541 | 0 | g_str_has_prefix(service, "tcpip:") || |
542 | 0 | g_str_has_prefix(service, "usb:")) { |
543 | 0 | if (tvb_reported_length_remaining(tvb, offset)) { |
544 | 0 | proto_tree_add_item_ret_display_string(main_tree, hf_result, tvb, offset, -1, ENC_ASCII, pinfo->pool, &display_str); |
545 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " Result=<%s>", display_str); |
546 | |
|
547 | 0 | offset = tvb_captured_length(tvb); |
548 | 0 | } |
549 | 0 | } else { |
550 | 0 | proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); |
551 | 0 | offset = tvb_captured_length(tvb); |
552 | 0 | } |
553 | |
|
554 | 0 | return offset; |
555 | 0 | } |
556 | | |
557 | | |
558 | | void |
559 | | proto_register_adb_service(void) |
560 | 14 | { |
561 | 14 | module_t *module; |
562 | 14 | expert_module_t *expert_module; |
563 | | |
564 | 14 | static hf_register_info hf[] = { |
565 | 14 | { &hf_service, |
566 | 14 | { "Service", "adb_service.service", |
567 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
568 | 14 | NULL, HFILL } |
569 | 14 | }, |
570 | 14 | { &hf_fragment, |
571 | 14 | { "Fragment", "adb_service.fragment", |
572 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
573 | 14 | NULL, HFILL } |
574 | 14 | }, |
575 | 14 | { &hf_data, |
576 | 14 | { "Data", "adb_service.data", |
577 | 14 | FT_BYTES, BASE_NONE, NULL, 0x00, |
578 | 14 | NULL, HFILL } |
579 | 14 | }, |
580 | 14 | { &hf_hex_ascii_length, |
581 | 14 | { "Hex ASCII String Length", "adb_service.hex_ascii_length", |
582 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
583 | 14 | NULL, HFILL } |
584 | 14 | }, |
585 | 14 | { &hf_length, |
586 | 14 | { "Length", "adb_service.length", |
587 | 14 | FT_UINT32, BASE_DEC_HEX, NULL, 0x00, |
588 | 14 | NULL, HFILL } |
589 | 14 | }, |
590 | 14 | { &hf_framebuffer_version, |
591 | 14 | { "Version", "adb_service.framebuffer.version", |
592 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
593 | 14 | NULL, HFILL } |
594 | 14 | }, |
595 | 14 | { &hf_hex_ascii_version, |
596 | 14 | { "Hex ASCII String Version", "adb_service.hex_ascii_version", |
597 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
598 | 14 | NULL, HFILL } |
599 | 14 | }, |
600 | 14 | { &hf_version, |
601 | 14 | { "Version", "adb_service.version", |
602 | 14 | FT_UINT32, BASE_DEC_HEX, NULL, 0x00, |
603 | 14 | NULL, HFILL } |
604 | 14 | }, |
605 | 14 | { &hf_framebuffer_depth, |
606 | 14 | { "Depth", "adb_service.framebuffer.depth", |
607 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
608 | 14 | NULL, HFILL } |
609 | 14 | }, |
610 | 14 | { &hf_framebuffer_size, |
611 | 14 | { "Size", "adb_service.framebuffer.size", |
612 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
613 | 14 | NULL, HFILL } |
614 | 14 | }, |
615 | 14 | { &hf_framebuffer_width, |
616 | 14 | { "Width", "adb_service.framebuffer.width", |
617 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
618 | 14 | NULL, HFILL } |
619 | 14 | }, |
620 | 14 | { &hf_framebuffer_height, |
621 | 14 | { "Height", "adb_service.framebuffer.height", |
622 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
623 | 14 | NULL, HFILL } |
624 | 14 | }, |
625 | 14 | { &hf_framebuffer_red_offset, |
626 | 14 | { "Red Offset", "adb_service.framebuffer.red_offset", |
627 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
628 | 14 | NULL, HFILL } |
629 | 14 | }, |
630 | 14 | { &hf_framebuffer_red_length, |
631 | 14 | { "Red Length", "adb_service.framebuffer.red_length", |
632 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
633 | 14 | NULL, HFILL } |
634 | 14 | }, |
635 | 14 | { &hf_framebuffer_blue_offset, |
636 | 14 | { "Blue Offset", "adb_service.framebuffer.blue_offset", |
637 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
638 | 14 | NULL, HFILL } |
639 | 14 | }, |
640 | 14 | { &hf_framebuffer_blue_length, |
641 | 14 | { "Blue Length", "adb_service.framebuffer.blue_length", |
642 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
643 | 14 | NULL, HFILL } |
644 | 14 | }, |
645 | 14 | { &hf_framebuffer_green_offset, |
646 | 14 | { "Green Offset", "adb_service.framebuffer.green_offset", |
647 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
648 | 14 | NULL, HFILL } |
649 | 14 | }, |
650 | 14 | { &hf_framebuffer_green_length, |
651 | 14 | { "Green Length", "adb_service.framebuffer.green_length", |
652 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
653 | 14 | NULL, HFILL } |
654 | 14 | }, |
655 | 14 | { &hf_framebuffer_alpha_offset, |
656 | 14 | { "Alpha Offset", "adb_service.framebuffer.alpha_offset", |
657 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
658 | 14 | NULL, HFILL } |
659 | 14 | }, |
660 | 14 | { &hf_framebuffer_alpha_length, |
661 | 14 | { "Alpha Length", "adb_service.framebuffer.alpha_length", |
662 | 14 | FT_UINT32, BASE_DEC, NULL, 0x00, |
663 | 14 | NULL, HFILL } |
664 | 14 | }, |
665 | 14 | { &hf_framebuffer_pixel, |
666 | 14 | { "Pixel", "adb_service.framebuffer.pixel", |
667 | 14 | FT_NONE, BASE_NONE, NULL, 0x00, |
668 | 14 | NULL, HFILL } |
669 | 14 | }, |
670 | 14 | { &hf_framebuffer_blue_5, |
671 | 14 | { "Blue", "adb_service.framebuffer.pixel.blue", |
672 | 14 | FT_UINT16, BASE_DEC, NULL, 0xF800, |
673 | 14 | NULL, HFILL } |
674 | 14 | }, |
675 | 14 | { &hf_framebuffer_green_6, |
676 | 14 | { "Green", "adb_service.framebuffer.pixel.green", |
677 | 14 | FT_UINT16, BASE_DEC, NULL, 0x07E0, |
678 | 14 | NULL, HFILL } |
679 | 14 | }, |
680 | 14 | { &hf_framebuffer_red_5, |
681 | 14 | { "Red", "adb_service.framebuffer.pixel.red", |
682 | 14 | FT_UINT16, BASE_DEC, NULL, 0x001F, |
683 | 14 | NULL, HFILL } |
684 | 14 | }, |
685 | 14 | { &hf_framebuffer_blue, |
686 | 14 | { "Blue", "adb_service.framebuffer.pixel.blue", |
687 | 14 | FT_UINT8, BASE_DEC, NULL, 0x00, |
688 | 14 | NULL, HFILL } |
689 | 14 | }, |
690 | 14 | { &hf_framebuffer_green, |
691 | 14 | { "Green", "adb_service.framebuffer.pixel.green", |
692 | 14 | FT_UINT8, BASE_DEC, NULL, 0x00, |
693 | 14 | NULL, HFILL } |
694 | 14 | }, |
695 | 14 | { &hf_framebuffer_red, |
696 | 14 | { "Red", "adb_service.framebuffer.pixel.red", |
697 | 14 | FT_UINT8, BASE_DEC, NULL, 0x00, |
698 | 14 | NULL, HFILL } |
699 | 14 | }, |
700 | 14 | { &hf_framebuffer_alpha, |
701 | 14 | { "Alpha", "adb_service.framebuffer.pixel.alpha", |
702 | 14 | FT_UINT8, BASE_DEC, NULL, 0x00, |
703 | 14 | NULL, HFILL } |
704 | 14 | }, |
705 | 14 | { &hf_framebuffer_unused, |
706 | 14 | { "Unused", "adb_service.framebuffer.pixel.unused", |
707 | 14 | FT_UINT8, BASE_DEC, NULL, 0x00, |
708 | 14 | NULL, HFILL } |
709 | 14 | }, |
710 | 14 | { &hf_devices, |
711 | 14 | { "Devices", "adb_service.devices", |
712 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
713 | 14 | NULL, HFILL } |
714 | 14 | }, |
715 | 14 | { &hf_stdin, |
716 | 14 | { "Stdin", "adb_service.stdin", |
717 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
718 | 14 | NULL, HFILL } |
719 | 14 | }, |
720 | 14 | { &hf_stdout, |
721 | 14 | { "Stdout", "adb_service.stdout", |
722 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
723 | 14 | NULL, HFILL } |
724 | 14 | }, |
725 | 14 | { &hf_result, |
726 | 14 | { "Result", "adb_service.result", |
727 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
728 | 14 | NULL, HFILL } |
729 | 14 | }, |
730 | 14 | { &hf_pids, |
731 | 14 | { "PIDs", "adb_service.pids", |
732 | 14 | FT_STRING, BASE_NONE, NULL, 0x00, |
733 | 14 | NULL, HFILL } |
734 | 14 | }, |
735 | 14 | }; |
736 | | |
737 | 14 | static int *ett[] = { |
738 | 14 | &ett_adb_service, |
739 | 14 | &ett_length, |
740 | 14 | &ett_version, |
741 | 14 | &ett_pixel, |
742 | 14 | &ett_data |
743 | 14 | }; |
744 | | |
745 | 14 | static ei_register_info ei[] = { |
746 | 14 | { &ei_incomplete_message, { "adb_service.expert.incomplete_message", PI_PROTOCOL, PI_WARN, "Incomplete message", EXPFILL }}, |
747 | 14 | }; |
748 | | |
749 | 14 | fragments = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); |
750 | 14 | framebuffer_infos = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); |
751 | 14 | continuation_infos = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); |
752 | | |
753 | 14 | proto_adb_service = proto_register_protocol("Android Debug Bridge Service", "ADB Service", "adb_service"); |
754 | 14 | adb_service_handle = register_dissector("adb_service", dissect_adb_service, proto_adb_service); |
755 | | |
756 | 14 | proto_register_field_array(proto_adb_service, hf, array_length(hf)); |
757 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
758 | 14 | expert_module = expert_register_protocol(proto_adb_service); |
759 | 14 | expert_register_field_array(expert_module, ei, array_length(ei)); |
760 | | |
761 | 14 | module = prefs_register_protocol(proto_adb_service, NULL); |
762 | 14 | prefs_register_static_text_preference(module, "version", |
763 | 14 | "ADB Service protocol version is compatible prior to: adb 1.0.31", |
764 | 14 | "Version of protocol supported by this dissector."); |
765 | | |
766 | 14 | prefs_register_bool_preference(module, "framebuffer_more_details", |
767 | 14 | "Dissect more detail for framebuffer service", |
768 | 14 | "Dissect more detail for framebuffer service", |
769 | 14 | &pref_dissect_more_detail_framebuffer); |
770 | 14 | } |
771 | | |
772 | | |
773 | | void |
774 | | proto_reg_handoff_adb_service(void) |
775 | 14 | { |
776 | 14 | logcat_handle = find_dissector_add_dependency("logcat", proto_adb_service); |
777 | 14 | } |
778 | | |
779 | | /* |
780 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
781 | | * |
782 | | * Local variables: |
783 | | * c-basic-offset: 4 |
784 | | * tab-width: 8 |
785 | | * indent-tabs-mode: nil |
786 | | * End: |
787 | | * |
788 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
789 | | * :indentSize=4:tabSize=8:noTabs=true: |
790 | | */ |