Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-jpeg.c
Line
Count
Source
1
/* packet-jpeg.c
2
 *
3
 * Routines for RFC 2435 JPEG dissection
4
 *
5
 * Copyright 2006
6
 * Erwin Rol <erwin@erwinrol.com>
7
 * Copyright 2001,
8
 * Francisco Javier Cabello Torres, <fjcabello@vtools.es>
9
 *
10
 * Wireshark - Network traffic analyzer
11
 * By Gerald Combs <gerald@wireshark.org>
12
 * Copyright 1998 Gerald Combs
13
 *
14
 * SPDX-License-Identifier: GPL-2.0-or-later
15
 */
16
#include "config.h"
17
18
#include <epan/packet.h>
19
20
#include "packet-ber.h"
21
#include "packet-rtp_pt.h"
22
23
void proto_register_jpeg(void);
24
void proto_reg_handoff_jpeg(void);
25
26
static dissector_handle_t jpeg_handle;
27
28
static const range_string jpeg_ts_rvals [] = {
29
    {0, 0,      "Progressively scanned"},
30
    {1, 1,      "Odd field of interlaced signal"},
31
    {2, 2,      "Even field of interlaced signal"},
32
    {3, 3,      "Interlaced field to be line doubled"},
33
    {3, 0xff,   "Unspecified"},
34
    {0, 0,      NULL}
35
};
36
37
static const range_string jpeg_type_rvals [] = {
38
    {  0,   0,  "4:2:2 Video"},
39
    {  1,   1,  "4:2:0 Video"},
40
    {  2,   5,  "Reserved"}, /* Previously assigned by RFC 2035 */
41
    {  6,  63,  "Unassigned"},
42
    { 64,  64,  "4:2:0 Video, Restart Markers present"},
43
    { 65,  65,  "4:2:0 Video, Restart Markers present"},
44
    { 66,  69,  "Reserved"}, /* Since [2,5] are reserved */
45
    { 70, 127,  "Unassigned, Restart Markers present"},
46
    {128, 255,  "Dynamically assigned"},
47
    {  0,   0,  NULL}
48
};
49
50
static int proto_jpeg;
51
52
static int hf_rtp_jpeg_main_hdr;
53
static int hf_rtp_jpeg_main_hdr_height;
54
static int hf_rtp_jpeg_main_hdr_offs;
55
static int hf_rtp_jpeg_main_hdr_q;
56
static int hf_rtp_jpeg_main_hdr_ts;
57
static int hf_rtp_jpeg_main_hdr_type;
58
static int hf_rtp_jpeg_main_hdr_width;
59
static int hf_rtp_jpeg_payload;
60
static int hf_rtp_jpeg_qtable_hdr;
61
static int hf_rtp_jpeg_qtable_hdr_data;
62
static int hf_rtp_jpeg_qtable_hdr_length;
63
static int hf_rtp_jpeg_qtable_hdr_mbz;
64
static int hf_rtp_jpeg_qtable_hdr_prec;
65
static int hf_rtp_jpeg_restart_hdr;
66
static int hf_rtp_jpeg_restart_hdr_count;
67
static int hf_rtp_jpeg_restart_hdr_f;
68
static int hf_rtp_jpeg_restart_hdr_interval;
69
static int hf_rtp_jpeg_restart_hdr_l;
70
71
/* JPEG fields defining a sub tree */
72
static int ett_jpeg;
73
74
static int
75
dissect_jpeg( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ )
76
3
{
77
3
  proto_item *ti = NULL;
78
3
  proto_tree *jpeg_tree = NULL;
79
3
  proto_tree *main_hdr_tree = NULL;
80
3
  proto_tree *restart_hdr_tree = NULL;
81
3
  proto_tree *qtable_hdr_tree = NULL;
82
3
  uint32_t fragment_offset = 0;
83
3
  uint16_t len = 0;
84
3
  uint8_t type = 0;
85
3
  uint8_t q = 0;
86
3
  int h = 0;
87
3
  int w = 0;
88
89
3
  unsigned int offset       = 0;
90
91
3
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "JPEG");
92
93
3
  col_set_str(pinfo->cinfo, COL_INFO, "JPEG message");
94
95
3
  if ( tree ) {
96
3
    ti = proto_tree_add_item( tree, proto_jpeg, tvb, offset, -1, ENC_NA );
97
3
    jpeg_tree = proto_item_add_subtree( ti, ett_jpeg );
98
99
3
    ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_main_hdr, tvb, offset, 8, ENC_NA);
100
3
    main_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
101
102
3
    proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_ts, tvb, offset, 1, ENC_BIG_ENDIAN);
103
3
    offset += 1;
104
3
    proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_offs, tvb, offset, 3, ENC_BIG_ENDIAN);
105
3
    fragment_offset = tvb_get_ntoh24(tvb, offset);
106
3
    offset += 3;
107
3
    proto_tree_add_item_ret_uint8(main_hdr_tree, hf_rtp_jpeg_main_hdr_type, tvb, offset, 1, ENC_BIG_ENDIAN, &type);
108
3
    offset += 1;
109
3
    proto_tree_add_item_ret_uint8(main_hdr_tree, hf_rtp_jpeg_main_hdr_q, tvb, offset, 1, ENC_BIG_ENDIAN, &q);
110
3
    offset += 1;
111
3
    w = tvb_get_uint8(tvb, offset) * 8;
112
3
    proto_tree_add_uint(main_hdr_tree, hf_rtp_jpeg_main_hdr_width, tvb, offset, 1, w);
113
3
    offset += 1;
114
3
    h = tvb_get_uint8(tvb, offset) * 8;
115
3
    proto_tree_add_uint(main_hdr_tree, hf_rtp_jpeg_main_hdr_height, tvb, offset, 1, h);
116
3
    offset += 1;
117
118
3
    if (type >= 64 && type <= 127) {
119
1
      ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_restart_hdr, tvb, offset, 4, ENC_NA);
120
1
      restart_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
121
1
      proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_interval, tvb, offset, 2, ENC_BIG_ENDIAN);
122
1
      offset += 2;
123
1
      proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_f, tvb, offset, 2, ENC_BIG_ENDIAN);
124
1
      proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_l, tvb, offset, 2, ENC_BIG_ENDIAN);
125
1
      proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_count, tvb, offset, 2, ENC_BIG_ENDIAN);
126
1
      offset += 2;
127
1
    }
128
129
3
    if (q >= 128 && fragment_offset == 0) {
130
0
      ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_qtable_hdr, tvb, offset, -1, ENC_NA);
131
0
      qtable_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
132
0
      proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_mbz, tvb, offset, 1, ENC_BIG_ENDIAN);
133
0
      offset += 1;
134
0
      proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_prec, tvb, offset, 1, ENC_BIG_ENDIAN);
135
0
      offset += 1;
136
0
      proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
137
0
      len = tvb_get_ntohs(tvb, offset);
138
0
      offset += 2;
139
0
      if (len > 0) {
140
0
        proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_data, tvb, offset, len, ENC_NA);
141
0
        offset += len;
142
0
      }
143
0
      proto_item_set_len(ti, len + 4);
144
0
    }
145
146
    /* The rest of the packet is the JPEG data */
147
3
    proto_tree_add_item( jpeg_tree, hf_rtp_jpeg_payload, tvb, offset, -1, ENC_NA );
148
3
  }
149
3
  return tvb_captured_length(tvb);
150
3
}
151
152
void
153
proto_register_jpeg(void)
154
16
{
155
16
  static hf_register_info hf[] = {
156
16
    { &hf_rtp_jpeg_main_hdr,
157
16
      { "Main Header", "jpeg.main_hdr",
158
16
        FT_NONE, BASE_NONE, NULL, 0,
159
16
        NULL, HFILL }
160
16
    },
161
16
    { &hf_rtp_jpeg_main_hdr_ts,
162
16
      { "Type Specific", "jpeg.main_hdr.ts",
163
16
        FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(jpeg_ts_rvals), 0,
164
16
        NULL, HFILL }
165
16
    },
166
16
    { &hf_rtp_jpeg_main_hdr_offs,
167
16
      { "Fragment Offset", "jpeg.main_hdr.offset",
168
16
        FT_UINT24, BASE_DEC, NULL, 0,
169
16
        NULL, HFILL }
170
16
    },
171
16
    { &hf_rtp_jpeg_main_hdr_type,
172
16
      { "Type", "jpeg.main_hdr.type",
173
16
        FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(jpeg_type_rvals), 0,
174
16
        NULL, HFILL }
175
16
    },
176
16
    { &hf_rtp_jpeg_main_hdr_q,
177
16
      { "Q", "jpeg.main_hdr.q",
178
16
        FT_UINT8, BASE_DEC, NULL, 0,
179
16
        NULL, HFILL }
180
16
    },
181
16
    { &hf_rtp_jpeg_main_hdr_width,
182
16
      { "Width", "jpeg.main_hdr.width",
183
16
        FT_UINT8, BASE_DEC, NULL, 0,
184
16
        NULL, HFILL }
185
16
    },
186
16
    { &hf_rtp_jpeg_main_hdr_height,
187
16
      { "Height", "jpeg.main_hdr.height",
188
16
        FT_UINT8, BASE_DEC, NULL, 0,
189
16
        NULL, HFILL }
190
16
    },
191
16
    { &hf_rtp_jpeg_restart_hdr,
192
16
      { "Restart Marker Header", "jpeg.restart_hdr",
193
16
        FT_NONE, BASE_NONE, NULL, 0,
194
16
        NULL, HFILL }
195
16
    },
196
16
    { &hf_rtp_jpeg_restart_hdr_interval,
197
16
      { "Restart Interval", "jpeg.restart_hdr.interval",
198
16
        FT_UINT16, BASE_DEC, NULL, 0,
199
16
        NULL, HFILL }
200
16
    },
201
16
    { &hf_rtp_jpeg_restart_hdr_f,
202
16
      { "F", "jpeg.restart_hdr.f",
203
16
        FT_UINT16, BASE_DEC, NULL, 0x8000,
204
16
        NULL, HFILL }
205
16
    },
206
16
    { &hf_rtp_jpeg_restart_hdr_l,
207
16
      { "L", "jpeg.restart_hdr.l",
208
16
        FT_UINT16, BASE_DEC, NULL, 0x4000,
209
16
        NULL, HFILL }
210
16
    },
211
16
    { &hf_rtp_jpeg_restart_hdr_count,
212
16
      { "Restart Count", "jpeg.restart_hdr.count",
213
16
        FT_UINT16, BASE_DEC, NULL, 0x3FFF,
214
16
        NULL, HFILL }
215
16
    },
216
16
    { &hf_rtp_jpeg_qtable_hdr,
217
16
      { "Quantization Table Header", "jpeg.qtable_hdr",
218
16
        FT_NONE, BASE_NONE, NULL, 0,
219
16
        NULL, HFILL }
220
16
    },
221
16
    { &hf_rtp_jpeg_qtable_hdr_mbz,
222
16
      { "MBZ", "jpeg.qtable_hdr.mbz",
223
16
        FT_UINT8, BASE_DEC, NULL, 0,
224
16
        NULL, HFILL }
225
16
    },
226
16
    { &hf_rtp_jpeg_qtable_hdr_prec,
227
16
      { "Precision", "jpeg.qtable_hdr.precision",
228
16
        FT_UINT8, BASE_DEC, NULL, 0,
229
16
        NULL, HFILL }
230
16
    },
231
16
    { &hf_rtp_jpeg_qtable_hdr_length,
232
16
      { "Length", "jpeg.qtable_hdr.length",
233
16
        FT_UINT16, BASE_DEC, NULL, 0,
234
16
        NULL, HFILL }
235
16
    },
236
16
    { &hf_rtp_jpeg_qtable_hdr_data,
237
16
      { "Quantization Table Data", "jpeg.qtable_hdr.data",
238
16
        FT_BYTES, BASE_NONE, NULL, 0,
239
16
        NULL, HFILL }
240
16
    },
241
16
    { &hf_rtp_jpeg_payload,
242
16
      { "Payload", "jpeg.payload",
243
16
        FT_BYTES, BASE_NONE, NULL, 0,
244
16
        NULL, HFILL }
245
16
    },
246
16
  };
247
248
16
  static int *ett[] = {
249
16
    &ett_jpeg,
250
16
  };
251
252
16
  proto_jpeg = proto_register_protocol("RFC 2435 JPEG","JPEG","jpeg");
253
16
  proto_register_field_array(proto_jpeg, hf, array_length(hf));
254
16
  proto_register_subtree_array(ett, array_length(ett));
255
256
16
  jpeg_handle = register_dissector("jpeg", dissect_jpeg, proto_jpeg);
257
258
  /* RFC 2798 */
259
16
  register_ber_oid_dissector_handle("0.9.2342.19200300.100.1.60", jpeg_handle, proto_jpeg, "jpegPhoto");
260
16
}
261
262
void
263
proto_reg_handoff_jpeg(void)
264
16
{
265
16
  dissector_add_uint("rtp.pt", PT_JPEG, jpeg_handle);
266
16
}
267
268
/*
269
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
270
 *
271
 * Local variables:
272
 * c-basic-offset: 8
273
 * tab-width: 8
274
 * indent-tabs-mode: t
275
 * End:
276
 *
277
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
278
 * :indentSize=8:tabSize=8:noTabs=false:
279
 */