Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
 */