Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-ixiatrailer.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-ixiatrailer.c
2
 * Routines for Ixia trailer parsing
3
 *
4
 * Dissector for Ixia Network Visibility Solutions trailer
5
 * Copyright Ixia 2012
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
#include "config.h"
15
16
#include <epan/packet.h>
17
#include <wsutil/pint.h>
18
#include <epan/prefs.h>
19
#include <epan/in_cksum.h>
20
#include <epan/expert.h>
21
22
void proto_register_ixiatrailer(void);
23
void proto_reg_handoff_ixiatrailer(void);
24
25
/* Trailer "magic number". */
26
1.05k
#define IXIA_PATTERN    0xAF12
27
28
/* Trailer TLV types.
29
30
   TODO: which of these typestamp types are currently supported?
31
   Should lose the rest!! */
32
0
#define IXIATRAILER_FTYPE_ORIGINAL_PACKET_SIZE 1
33
0
#define IXIATRAILER_FTYPE_TIMESTAMP_LOCAL      3
34
0
#define IXIATRAILER_FTYPE_TIMESTAMP_NTP        4
35
0
#define IXIATRAILER_FTYPE_TIMESTAMP_GPS        5
36
0
#define IXIATRAILER_FTYPE_TIMESTAMP_1588       6 /* PTP */
37
0
#define IXIATRAILER_FTYPE_TIMESTAMP_HOLDOVER   7
38
39
static const value_string ixiatrailer_ftype_timestamp[] = {
40
  { IXIATRAILER_FTYPE_TIMESTAMP_LOCAL,      "Local" },
41
  { IXIATRAILER_FTYPE_TIMESTAMP_NTP,        "NTP" },
42
  { IXIATRAILER_FTYPE_TIMESTAMP_GPS,        "GPS" },
43
  { IXIATRAILER_FTYPE_TIMESTAMP_1588,       "PTP" },
44
  { IXIATRAILER_FTYPE_TIMESTAMP_HOLDOVER,   "Holdover" },
45
  { 0,                                      NULL }
46
};
47
48
/* Preference settings */
49
static bool ixiatrailer_summary_in_tree = true;
50
51
static int proto_ixiatrailer;
52
static int ett_ixiatrailer;
53
54
static int hf_ixiatrailer_packetlen;
55
static int hf_ixiatrailer_timestamp;
56
static int hf_ixiatrailer_generic;
57
58
static expert_field ei_ixiatrailer_field_length_invalid;
59
60
/* The trailer begins with a sequence of TLVs, each of which has a
61
   1-byte type, a 1-byte value length (not TLV length, so the TLV
62
   length is the value length + 2), and a variable-length value.
63
64
   Following the sequence of TLVs is:
65
66
      a 1-byte field giving the length of the sequence of TLVs;
67
      a 2-byte big-endian signature field with the value 0xAF12;
68
      a 2-byte big-endian checksum field, covering the sequence
69
      of TLVs, the sequence length, and the signature.
70
*/
71
static int
72
dissect_ixiatrailer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
73
620
{
74
620
  proto_tree *ti;
75
620
  unsigned tvblen, trailer_length, field_length;
76
620
  bool matched_without_fcs, matched_with_fcs;
77
620
  proto_tree *ixiatrailer_tree = NULL;
78
620
  unsigned offset = 0;
79
620
  uint16_t cksum, comp_cksum;
80
620
  vec_t vec;
81
620
  uint8_t field_type;
82
83
  /* A trailer must, at minimum, include:
84
85
       a "original packet size" TLV, with 1 byte of type, 1 byte of
86
       value length, and 2 bytes of original packet ize;
87
88
       1 byte of trailer length;
89
90
       2 bytes of signature;
91
92
       2 bytes of trailer checksum;
93
94
     for a total of 9 bytes. */
95
620
  tvblen = tvb_reported_length(tvb);
96
620
  if (tvblen != tvb_captured_length(tvb)) {
97
    /* The heuristic check includes a checksum check, so we need the
98
       *entire* trailer to have been captured; if it wasn't, we don't
99
       try to check it. */
100
0
    return 0;
101
0
  }
102
620
  if (tvblen < 9) {
103
    /* This is too short, so it cannot be a valid Ixia trailer. */
104
69
    return 0;
105
69
  }
106
107
  /* Depending upon the ethernet preference "Assume packets have FCS", we
108
     may be given those 4 bytes too.
109
110
     Try checking two locations for our pattern. */
111
112
551
  if (tvblen == 23) {
113
3
    tvblen = 19;
114
3
  }
115
116
  /* 3rd & 4th bytes from the end must match our pattern.
117
     First, try under the assumption that the tvbuff doesn't include
118
     the FCS. */
119
551
  matched_without_fcs = (tvb_get_ntohs(tvb, tvblen-4) == IXIA_PATTERN);
120
121
  /* If that didn't match, is the tvbuff big enough to include an Ixia
122
     trailer *and* an FCS? If so, try under that assumption. */
123
551
  if (!matched_without_fcs && tvblen >= 13)
124
505
    matched_with_fcs = (tvb_get_ntohs(tvb, tvblen-(4+4)) == IXIA_PATTERN);
125
46
  else
126
46
    matched_with_fcs = false;
127
551
  if (!matched_without_fcs) {
128
551
    if (!matched_with_fcs) {
129
      /* Neither matched, so no Ixia trailer. */
130
551
      return 0;
131
551
    }
132
133
    /* Matched under the assumption that we have an FCS, so let's
134
       act as if that's the case.  Remove the FCS length from the
135
       tvbuff. */
136
0
    tvblen -= 4;
137
0
  }
138
139
  /* Read Trailer-length field */
140
0
  trailer_length  = tvb_get_uint8(tvb, tvblen-5);
141
  /* Should match overall length of trailer */
142
0
  if ((tvblen-5) != trailer_length) {
143
0
    return 0;
144
0
  }
145
146
  /* Last 2 bytes are the checksum */
147
0
  cksum = tvb_get_ntohs(tvb, tvblen-2);
148
149
  /* Verify the checksum; if not valid, it means that the trailer is not valid */
150
0
  SET_CKSUM_VEC_TVB(vec, tvb, offset, trailer_length + 3);
151
0
  comp_cksum = in_cksum(&vec, 1);
152
0
  if (pntoh16(&comp_cksum) != cksum) {
153
0
    return 0;
154
0
  }
155
156
  /* OK: We have our trailer - create protocol root */
157
0
  ti = proto_tree_add_item(tree, proto_ixiatrailer, tvb, offset, trailer_length + 5, ENC_NA);
158
159
  /* Append summary to item, if configured to */
160
0
  if (ixiatrailer_summary_in_tree) {
161
0
    proto_item_append_text(ti, ", Length: %u, Checksum: 0x%x", trailer_length, cksum);
162
0
  }
163
164
  /* Create subtree */
165
0
  ixiatrailer_tree = proto_item_add_subtree(ti, ett_ixiatrailer);
166
167
0
  while (offset < trailer_length - 2)
168
0
  {
169
0
    field_type = tvb_get_uint8(tvb, offset++);
170
0
    field_length = tvb_get_uint8(tvb, offset++);
171
0
    switch (field_type) {
172
0
      case IXIATRAILER_FTYPE_ORIGINAL_PACKET_SIZE:
173
0
        if (field_length != 2){
174
0
          expert_add_info_format(pinfo, ti, &ei_ixiatrailer_field_length_invalid, "Field length %u invalid", field_length);
175
0
          break;
176
0
        }
177
0
        ti = proto_tree_add_item(ixiatrailer_tree, hf_ixiatrailer_packetlen, tvb, offset, field_length, ENC_BIG_ENDIAN);
178
0
        proto_item_append_text(ti, " bytes");
179
0
      break;
180
0
      case IXIATRAILER_FTYPE_TIMESTAMP_LOCAL:
181
0
      case IXIATRAILER_FTYPE_TIMESTAMP_NTP:
182
0
      case IXIATRAILER_FTYPE_TIMESTAMP_GPS:
183
0
      case IXIATRAILER_FTYPE_TIMESTAMP_1588:
184
0
      case IXIATRAILER_FTYPE_TIMESTAMP_HOLDOVER:
185
0
        if (field_length != 8) {
186
0
          expert_add_info_format(pinfo, ti, &ei_ixiatrailer_field_length_invalid, "Field length %u invalid", field_length);
187
0
          break;
188
0
        }
189
        /* Timestamp */
190
0
        ti = proto_tree_add_item(ixiatrailer_tree, hf_ixiatrailer_timestamp, tvb, offset, field_length, ENC_TIME_SECS_NSECS|ENC_BIG_ENDIAN);
191
0
        proto_item_append_text(ti, "; Source: %s", val_to_str_const(field_type, ixiatrailer_ftype_timestamp, "Unknown"));
192
0
      break;
193
0
      default:
194
        /* Not a recognized time format - just show as bytes */
195
0
        ti = proto_tree_add_item(ixiatrailer_tree, hf_ixiatrailer_generic, tvb, offset, field_length, ENC_NA);
196
0
        proto_item_append_text(ti, " [Id: %u, Length: %u bytes]", field_type, field_length);
197
0
      break;
198
0
    };
199
0
    offset += field_length;
200
0
  }
201
  /* We are claiming all of the bytes */
202
0
  return tvblen;
203
0
}
204
205
static bool
206
dissect_ixiatrailer_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
207
620
{
208
620
    return dissect_ixiatrailer(tvb, pinfo, tree, data) > 0;
209
620
}
210
211
void
212
proto_register_ixiatrailer(void)
213
14
{
214
215
14
  static hf_register_info hf[] = {
216
14
    { &hf_ixiatrailer_packetlen, {
217
14
        "Original packet length", "ixiatrailer.packetlen", FT_UINT16, BASE_DEC,
218
14
        NULL, 0x0, NULL, HFILL }},
219
14
    { &hf_ixiatrailer_timestamp, {
220
14
        "Time Stamp", "ixiatrailer.timestamp", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL,
221
14
        NULL, 0x0, NULL, HFILL }},
222
14
    { &hf_ixiatrailer_generic, {
223
14
        "Generic Field", "ixiatrailer.generic", FT_BYTES, BASE_NONE,
224
14
        NULL, 0x0, NULL, HFILL }},
225
14
  };
226
227
14
  static int *ixiatrailer_ett[] = {
228
14
    &ett_ixiatrailer
229
14
  };
230
231
14
  static ei_register_info ei[] = {
232
14
     { &ei_ixiatrailer_field_length_invalid, { "ixiatrailer.field_length_invalid", PI_MALFORMED, PI_ERROR, "Field length invalid", EXPFILL }},
233
14
  };
234
235
14
  module_t *ixiatrailer_module;
236
14
  expert_module_t* expert_ixiatrailer;
237
238
14
  proto_ixiatrailer = proto_register_protocol("Ixia Trailer", "IXIATRAILER", "ixiatrailer");
239
14
  proto_register_field_array(proto_ixiatrailer, hf, array_length(hf));
240
14
  proto_register_subtree_array(ixiatrailer_ett, array_length(ixiatrailer_ett));
241
14
  expert_ixiatrailer = expert_register_protocol(proto_ixiatrailer);
242
14
  expert_register_field_array(expert_ixiatrailer, ei, array_length(ei));
243
244
14
  ixiatrailer_module = prefs_register_protocol(proto_ixiatrailer, NULL);
245
14
  prefs_register_bool_preference(ixiatrailer_module, "summary_in_tree",
246
14
        "Show trailer summary in protocol tree",
247
14
        "Whether the trailer summary line should be shown in the protocol tree",
248
14
        &ixiatrailer_summary_in_tree);
249
14
}
250
251
252
void
253
proto_reg_handoff_ixiatrailer(void)
254
14
{
255
  /* Check for Ixia format in the ethernet trailer */
256
14
  heur_dissector_add("eth.trailer", dissect_ixiatrailer_heur, "Ixia Trailer", "ixiatrailer_eth", proto_ixiatrailer, HEURISTIC_ENABLE);
257
14
}
258
259
/*
260
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
261
 *
262
 * Local Variables:
263
 * c-basic-offset: 2
264
 * tab-width: 8
265
 * indent-tabs-mode: nil
266
 * End:
267
 *
268
 * ex: set shiftwidth=2 tabstop=8 expandtab:
269
 * :indentSize=2:tabSize=8:noTabs=true:
270
 */