Coverage Report

Created: 2025-02-15 06:25

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