Coverage Report

Created: 2025-12-27 06:52

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
7
{
77
7
  proto_item *ti = NULL;
78
7
  proto_tree *jpeg_tree = NULL;
79
7
  proto_tree *main_hdr_tree = NULL;
80
7
  proto_tree *restart_hdr_tree = NULL;
81
7
  proto_tree *qtable_hdr_tree = NULL;
82
7
  uint32_t fragment_offset = 0;
83
7
  uint16_t len = 0;
84
7
  uint8_t type = 0;
85
7
  uint8_t q = 0;
86
7
  int h = 0;
87
7
  int w = 0;
88
89
7
  unsigned int offset       = 0;
90
91
7
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "JPEG");
92
93
7
  col_set_str(pinfo->cinfo, COL_INFO, "JPEG message");
94
95
7
  if ( tree ) {
96
7
    ti = proto_tree_add_item( tree, proto_jpeg, tvb, offset, -1, ENC_NA );
97
7
    jpeg_tree = proto_item_add_subtree( ti, ett_jpeg );
98
99
7
    ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_main_hdr, tvb, offset, 8, ENC_NA);
100
7
    main_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
101
102
7
    proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_ts, tvb, offset, 1, ENC_BIG_ENDIAN);
103
7
    offset += 1;
104
7
    proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_offs, tvb, offset, 3, ENC_BIG_ENDIAN);
105
7
    fragment_offset = tvb_get_ntoh24(tvb, offset);
106
7
    offset += 3;
107
7
    proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
108
7
    type = tvb_get_uint8(tvb, offset);
109
7
    offset += 1;
110
7
    proto_tree_add_item(main_hdr_tree, hf_rtp_jpeg_main_hdr_q, tvb, offset, 1, ENC_BIG_ENDIAN);
111
7
    q = tvb_get_uint8(tvb, offset);
112
7
    offset += 1;
113
7
    w = tvb_get_uint8(tvb, offset) * 8;
114
7
    proto_tree_add_uint(main_hdr_tree, hf_rtp_jpeg_main_hdr_width, tvb, offset, 1, w);
115
7
    offset += 1;
116
7
    h = tvb_get_uint8(tvb, offset) * 8;
117
7
    proto_tree_add_uint(main_hdr_tree, hf_rtp_jpeg_main_hdr_height, tvb, offset, 1, h);
118
7
    offset += 1;
119
120
7
    if (type >= 64 && type <= 127) {
121
1
      ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_restart_hdr, tvb, offset, 4, ENC_NA);
122
1
      restart_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
123
1
      proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_interval, tvb, offset, 2, ENC_BIG_ENDIAN);
124
1
      offset += 2;
125
1
      proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_f, tvb, offset, 2, ENC_BIG_ENDIAN);
126
1
      proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_l, tvb, offset, 2, ENC_BIG_ENDIAN);
127
1
      proto_tree_add_item(restart_hdr_tree, hf_rtp_jpeg_restart_hdr_count, tvb, offset, 2, ENC_BIG_ENDIAN);
128
1
      offset += 2;
129
1
    }
130
131
7
    if (q >= 128 && fragment_offset == 0) {
132
1
      ti = proto_tree_add_item(jpeg_tree, hf_rtp_jpeg_qtable_hdr, tvb, offset, -1, ENC_NA);
133
1
      qtable_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
134
1
      proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_mbz, tvb, offset, 1, ENC_BIG_ENDIAN);
135
1
      offset += 1;
136
1
      proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_prec, tvb, offset, 1, ENC_BIG_ENDIAN);
137
1
      offset += 1;
138
1
      proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
139
1
      len = tvb_get_ntohs(tvb, offset);
140
1
      offset += 2;
141
1
      if (len > 0) {
142
1
        proto_tree_add_item(qtable_hdr_tree, hf_rtp_jpeg_qtable_hdr_data, tvb, offset, len, ENC_NA);
143
1
        offset += len;
144
1
      }
145
1
      proto_item_set_len(ti, len + 4);
146
1
    }
147
148
    /* The rest of the packet is the JPEG data */
149
7
    proto_tree_add_item( jpeg_tree, hf_rtp_jpeg_payload, tvb, offset, -1, ENC_NA );
150
7
  }
151
7
  return tvb_captured_length(tvb);
152
7
}
153
154
void
155
proto_register_jpeg(void)
156
14
{
157
14
  static hf_register_info hf[] = {
158
14
    { &hf_rtp_jpeg_main_hdr,
159
14
      { "Main Header", "jpeg.main_hdr",
160
14
        FT_NONE, BASE_NONE, NULL, 0,
161
14
        NULL, HFILL }
162
14
    },
163
14
    { &hf_rtp_jpeg_main_hdr_ts,
164
14
      { "Type Specific", "jpeg.main_hdr.ts",
165
14
        FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(jpeg_ts_rvals), 0,
166
14
        NULL, HFILL }
167
14
    },
168
14
    { &hf_rtp_jpeg_main_hdr_offs,
169
14
      { "Fragment Offset", "jpeg.main_hdr.offset",
170
14
        FT_UINT24, BASE_DEC, NULL, 0,
171
14
        NULL, HFILL }
172
14
    },
173
14
    { &hf_rtp_jpeg_main_hdr_type,
174
14
      { "Type", "jpeg.main_hdr.type",
175
14
        FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(jpeg_type_rvals), 0,
176
14
        NULL, HFILL }
177
14
    },
178
14
    { &hf_rtp_jpeg_main_hdr_q,
179
14
      { "Q", "jpeg.main_hdr.q",
180
14
        FT_UINT8, BASE_DEC, NULL, 0,
181
14
        NULL, HFILL }
182
14
    },
183
14
    { &hf_rtp_jpeg_main_hdr_width,
184
14
      { "Width", "jpeg.main_hdr.width",
185
14
        FT_UINT8, BASE_DEC, NULL, 0,
186
14
        NULL, HFILL }
187
14
    },
188
14
    { &hf_rtp_jpeg_main_hdr_height,
189
14
      { "Height", "jpeg.main_hdr.height",
190
14
        FT_UINT8, BASE_DEC, NULL, 0,
191
14
        NULL, HFILL }
192
14
    },
193
14
    { &hf_rtp_jpeg_restart_hdr,
194
14
      { "Restart Marker Header", "jpeg.restart_hdr",
195
14
        FT_NONE, BASE_NONE, NULL, 0,
196
14
        NULL, HFILL }
197
14
    },
198
14
    { &hf_rtp_jpeg_restart_hdr_interval,
199
14
      { "Restart Interval", "jpeg.restart_hdr.interval",
200
14
        FT_UINT16, BASE_DEC, NULL, 0,
201
14
        NULL, HFILL }
202
14
    },
203
14
    { &hf_rtp_jpeg_restart_hdr_f,
204
14
      { "F", "jpeg.restart_hdr.f",
205
14
        FT_UINT16, BASE_DEC, NULL, 0x8000,
206
14
        NULL, HFILL }
207
14
    },
208
14
    { &hf_rtp_jpeg_restart_hdr_l,
209
14
      { "L", "jpeg.restart_hdr.l",
210
14
        FT_UINT16, BASE_DEC, NULL, 0x4000,
211
14
        NULL, HFILL }
212
14
    },
213
14
    { &hf_rtp_jpeg_restart_hdr_count,
214
14
      { "Restart Count", "jpeg.restart_hdr.count",
215
14
        FT_UINT16, BASE_DEC, NULL, 0x3FFF,
216
14
        NULL, HFILL }
217
14
    },
218
14
    { &hf_rtp_jpeg_qtable_hdr,
219
14
      { "Quantization Table Header", "jpeg.qtable_hdr",
220
14
        FT_NONE, BASE_NONE, NULL, 0,
221
14
        NULL, HFILL }
222
14
    },
223
14
    { &hf_rtp_jpeg_qtable_hdr_mbz,
224
14
      { "MBZ", "jpeg.qtable_hdr.mbz",
225
14
        FT_UINT8, BASE_DEC, NULL, 0,
226
14
        NULL, HFILL }
227
14
    },
228
14
    { &hf_rtp_jpeg_qtable_hdr_prec,
229
14
      { "Precision", "jpeg.qtable_hdr.precision",
230
14
        FT_UINT8, BASE_DEC, NULL, 0,
231
14
        NULL, HFILL }
232
14
    },
233
14
    { &hf_rtp_jpeg_qtable_hdr_length,
234
14
      { "Length", "jpeg.qtable_hdr.length",
235
14
        FT_UINT16, BASE_DEC, NULL, 0,
236
14
        NULL, HFILL }
237
14
    },
238
14
    { &hf_rtp_jpeg_qtable_hdr_data,
239
14
      { "Quantization Table Data", "jpeg.qtable_hdr.data",
240
14
        FT_BYTES, BASE_NONE, NULL, 0,
241
14
        NULL, HFILL }
242
14
    },
243
14
    { &hf_rtp_jpeg_payload,
244
14
      { "Payload", "jpeg.payload",
245
14
        FT_BYTES, BASE_NONE, NULL, 0,
246
14
        NULL, HFILL }
247
14
    },
248
14
  };
249
250
14
  static int *ett[] = {
251
14
    &ett_jpeg,
252
14
  };
253
254
14
  proto_jpeg = proto_register_protocol("RFC 2435 JPEG","JPEG","jpeg");
255
14
  proto_register_field_array(proto_jpeg, hf, array_length(hf));
256
14
  proto_register_subtree_array(ett, array_length(ett));
257
258
14
  jpeg_handle = register_dissector("jpeg", dissect_jpeg, proto_jpeg);
259
260
  /* RFC 2798 */
261
14
  register_ber_oid_dissector_handle("0.9.2342.19200300.100.1.60", jpeg_handle, proto_jpeg, "jpegPhoto");
262
14
}
263
264
void
265
proto_reg_handoff_jpeg(void)
266
14
{
267
14
  dissector_add_uint("rtp.pt", PT_JPEG, jpeg_handle);
268
14
}
269
270
/*
271
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
272
 *
273
 * Local variables:
274
 * c-basic-offset: 8
275
 * tab-width: 8
276
 * indent-tabs-mode: t
277
 * End:
278
 *
279
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
280
 * :indentSize=8:tabSize=8:noTabs=false:
281
 */