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-kdp.c
Line
Count
Source
1
/* packet-kdp.c
2
 * Routines for KDP (Kontiki Delivery Protocol) packet disassembly
3
 *
4
 * Copyright (c) 2008 by Kontiki Inc.
5
 *                    Wade Hennessey <wade@kontiki.com>
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1999 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
void proto_register_kdp(void);
18
void proto_reg_handoff_kdp(void);
19
20
static dissector_handle_t kdp_handle;
21
22
14
#define KDP_PORT 19948 /* Not IANA registered */
23
#define BUFFER_SIZE 80
24
static int proto_kdp;
25
static int ett_kdp;
26
static int ett_kdp_flags;
27
28
static int hf_kdp_version;
29
static int hf_kdp_headerlen;
30
static int hf_kdp_flags;
31
static int hf_kdp_errors;
32
static int hf_kdp_destflowid;
33
static int hf_kdp_srcflowid;
34
static int hf_kdp_sequence;
35
static int hf_kdp_ack;
36
static int hf_kdp_maxsegmentsize;
37
static int hf_kdp_optionnumber;
38
static int hf_kdp_optionlen;
39
static int hf_kdp_option1;
40
static int hf_kdp_option2;
41
static int hf_kdp_option3;
42
static int hf_kdp_option4;
43
static int hf_kdp_option5;
44
static int hf_kdp_option6;
45
static int hf_kdp_option7;
46
static int hf_kdp_option8;
47
static int hf_kdp_option9;
48
static int hf_kdp_option_unknown;
49
static int hf_kdp_fragment;
50
static int hf_kdp_fragtotal;
51
static int hf_kdp_body;
52
static int hf_kdp_xml_body;
53
54
19
#define KDP_DROP_FLAG (1 << 0)
55
58
#define KDP_SYN_FLAG  (1 << 1)
56
53
#define KDP_ACK_FLAG  (1 << 2)
57
19
#define KDP_RST_FLAG  (1 << 3)
58
41
#define KDP_BCST_FLAG (1 << 4)
59
19
#define KDP_DUP_FLAG  (1 << 5)
60
61
static int hf_kdp_drop_flag;
62
static int hf_kdp_syn_flag;
63
static int hf_kdp_ack_flag;
64
static int hf_kdp_rst_flag;
65
static int hf_kdp_bcst_flag;
66
static int hf_kdp_dup_flag;
67
68
static int dissect_kdp(tvbuff_t *tvb,
69
                        packet_info *pinfo,
70
18
                        proto_tree *tree, void* data _U_) {
71
18
  proto_item *ti;
72
18
  proto_tree *kdp_tree;
73
18
  unsigned body_len;
74
18
  uint8_t version;
75
18
  uint8_t header_len = 0;
76
18
  uint8_t packet_flags = 0;
77
18
  uint8_t packet_errors = 0;
78
18
  uint32_t sequence_number = UINT32_MAX;
79
18
  uint32_t ack_number = UINT32_MAX;
80
18
  uint32_t src_flowid = UINT32_MAX;
81
82
18
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "KDP");
83
18
  col_clear(pinfo->cinfo, COL_INFO);
84
85
18
  ti = proto_tree_add_item(tree, proto_kdp, tvb, 0, -1, ENC_NA);
86
18
  kdp_tree = proto_item_add_subtree(ti, ett_kdp);
87
88
18
  version = tvb_get_uint8(tvb, 0);
89
18
  if (version != 2) {
90
    /* Version other than 2 is really SDDP in UDP */
91
1
    proto_tree_add_item(kdp_tree, hf_kdp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
92
1
    proto_tree_add_item(kdp_tree, hf_kdp_xml_body, tvb, 0, -1, ENC_ASCII);
93
17
  } else {
94
17
    proto_tree *flags_tree;
95
17
    header_len = tvb_get_uint8(tvb, 1) * 4;
96
17
    body_len = tvb_reported_length(tvb);
97
17
    if (header_len > body_len) {
98
11
      body_len = 0;           /* malformed packet */
99
11
    } else {
100
6
      body_len = body_len - header_len;
101
6
    }
102
17
    packet_flags = tvb_get_uint8(tvb, 2);
103
17
    packet_errors = tvb_get_uint8(tvb, 3);
104
17
    proto_tree_add_item(kdp_tree, hf_kdp_version, tvb, 0, 1, ENC_BIG_ENDIAN);
105
17
    proto_tree_add_item(kdp_tree, hf_kdp_headerlen, tvb, 1, 1, ENC_BIG_ENDIAN);
106
17
    ti = proto_tree_add_item(kdp_tree, hf_kdp_flags, tvb, 2, 1, ENC_BIG_ENDIAN);
107
17
    flags_tree = proto_item_add_subtree(ti, ett_kdp_flags);
108
109
17
    proto_tree_add_item(flags_tree, hf_kdp_drop_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
110
17
    proto_tree_add_item(flags_tree, hf_kdp_syn_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
111
17
    proto_tree_add_item(flags_tree, hf_kdp_ack_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
112
17
    proto_tree_add_item(flags_tree, hf_kdp_rst_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
113
17
    proto_tree_add_item(flags_tree, hf_kdp_bcst_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
114
17
    proto_tree_add_item(flags_tree, hf_kdp_dup_flag, tvb, 2, 1, ENC_BIG_ENDIAN);
115
116
17
    proto_tree_add_item(kdp_tree, hf_kdp_errors, tvb, 3, 1, ENC_BIG_ENDIAN);
117
118
17
    if (header_len > 4) {
119
17
      int offset;
120
17
      offset = 4;
121
17
      if (packet_flags & KDP_ACK_FLAG) {
122
12
        proto_tree_add_item(kdp_tree, hf_kdp_destflowid, tvb, offset, 4, ENC_BIG_ENDIAN);
123
12
        offset = offset + 4;
124
12
      }
125
126
17
      if (packet_flags & (KDP_SYN_FLAG | KDP_BCST_FLAG)) {
127
15
        proto_tree_add_item(kdp_tree, hf_kdp_srcflowid, tvb, offset, 4, ENC_BIG_ENDIAN);
128
15
        src_flowid = tvb_get_ntohl(tvb, offset);
129
15
        offset = offset + 4;
130
15
      }
131
132
17
      proto_tree_add_item(kdp_tree, hf_kdp_sequence, tvb, offset, 4, ENC_BIG_ENDIAN);
133
17
      sequence_number = tvb_get_ntohl(tvb, offset);
134
17
      offset = offset + 4;
135
136
17
      if (packet_flags & KDP_ACK_FLAG) {
137
12
        proto_tree_add_item(kdp_tree, hf_kdp_ack, tvb, offset, 4, ENC_BIG_ENDIAN);
138
12
        ack_number = tvb_get_ntohl(tvb, offset);
139
12
        offset = offset + 4;
140
12
      }
141
17
      if (packet_flags & KDP_SYN_FLAG) {
142
11
        proto_tree_add_item(kdp_tree, hf_kdp_maxsegmentsize, tvb, offset, 4, ENC_BIG_ENDIAN);
143
11
        offset = offset + 4;
144
11
      }
145
146
402
      while (offset < ((body_len > 0) ? header_len - 4 : header_len)) {
147
397
        uint8_t option_number;
148
397
        uint8_t option_len = 0;
149
150
397
        option_number = tvb_get_uint8(tvb, offset);
151
152
397
        proto_tree_add_item(kdp_tree, hf_kdp_optionnumber, tvb, offset, 1, ENC_BIG_ENDIAN);
153
397
        offset = offset + 1;
154
397
        if (option_number > 0) {
155
97
          option_len = tvb_get_uint8(tvb, offset);
156
97
          proto_tree_add_item(kdp_tree, hf_kdp_optionlen, tvb, offset, 1, ENC_BIG_ENDIAN);
157
97
          offset = offset + 1;
158
97
        }
159
160
397
        switch (option_number) {
161
298
        case 0:
162
298
          break;
163
21
        case 1:
164
21
          proto_tree_add_item(kdp_tree, hf_kdp_option1, tvb, offset, 2, ENC_BIG_ENDIAN);
165
21
          offset = offset + 2;
166
21
          break;
167
3
        case 2:
168
3
          proto_tree_add_item(kdp_tree, hf_kdp_option2, tvb, offset, 2, ENC_BIG_ENDIAN);
169
3
          offset = offset + 2;
170
3
          break;
171
10
        case 3:
172
10
          proto_tree_add_item(kdp_tree, hf_kdp_option3, tvb, offset, 2, ENC_BIG_ENDIAN);
173
10
          offset = offset + 2;
174
10
          break;
175
0
        case 4:
176
0
          proto_tree_add_item(kdp_tree, hf_kdp_option4, tvb, offset, 0, ENC_NA);
177
0
          break;
178
0
        case 5:
179
0
          proto_tree_add_item(kdp_tree, hf_kdp_option5, tvb, offset, 0, ENC_NA);
180
0
          break;
181
9
        case 6:
182
9
          proto_tree_add_item(kdp_tree, hf_kdp_option6, tvb, offset, option_len - 2, ENC_NA);
183
9
          offset = offset + option_len - 2;
184
9
          break;
185
9
        case 7:
186
9
          proto_tree_add_item(kdp_tree, hf_kdp_option7, tvb, offset, 2, ENC_BIG_ENDIAN);
187
9
          offset = offset + 2;
188
9
          break;
189
2
        case 8:
190
2
          proto_tree_add_item(kdp_tree, hf_kdp_option8, tvb, offset, 2, ENC_BIG_ENDIAN);
191
2
          offset = offset + 2;
192
2
          break;
193
3
        case 9:
194
3
          proto_tree_add_item(kdp_tree, hf_kdp_option9, tvb, offset, 2, ENC_BIG_ENDIAN);
195
3
          offset = offset + 2;
196
3
          break;
197
40
        default:
198
40
          proto_tree_add_item(kdp_tree, hf_kdp_option_unknown, tvb, offset, option_len - 2, ENC_NA);
199
40
          offset = offset + option_len - 2;
200
40
          break;
201
397
        }
202
397
      }
203
204
5
      if (body_len > 0) {
205
5
        proto_tree_add_item(kdp_tree, hf_kdp_fragment, tvb, offset, 2, ENC_BIG_ENDIAN);
206
5
        offset = offset + 2;
207
208
5
        proto_tree_add_item(kdp_tree, hf_kdp_fragtotal, tvb, offset, 2, ENC_BIG_ENDIAN);
209
5
        offset = offset + 2;
210
211
5
        proto_tree_add_item(kdp_tree, hf_kdp_body, tvb, offset, -1, ENC_NA);
212
5
      }
213
5
    }
214
17
  }
215
  /* Now that we know sequence number and optional ack number, we can
216
     print more detailed summary info */
217
6
  if (version != 2) {
218
1
      col_set_str(pinfo->cinfo, COL_INFO, "SDDP message");
219
5
  } else {
220
5
      char ack_string[BUFFER_SIZE];
221
5
      char seq_num_string[BUFFER_SIZE];
222
5
      char src_flowid_string[BUFFER_SIZE];
223
224
5
      if (packet_flags & KDP_ACK_FLAG) {
225
3
        snprintf(ack_string, sizeof(ack_string), "ACK=%x ", ack_number);
226
3
      } else {
227
2
        ack_string[0] = '\0';
228
2
      }
229
5
      if (header_len > 4) {
230
5
        snprintf(seq_num_string, sizeof(seq_num_string), "SEQ=%x ", sequence_number);
231
5
      } else {
232
0
        seq_num_string[0] = '\0';
233
0
      }
234
5
      if (packet_flags & (KDP_SYN_FLAG | KDP_BCST_FLAG)) {
235
5
        snprintf(src_flowid_string, sizeof(src_flowid_string), "SRC_FLOWID=%x ", src_flowid);
236
5
      } else {
237
0
        src_flowid_string[0] = '\0';
238
0
      }
239
5
      col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s%s%s%s%s%serrors=%d",
240
5
                   ((packet_flags & KDP_DROP_FLAG) ? "DROP " : ""),
241
5
                   ((packet_flags & KDP_SYN_FLAG) ? "SYN " : ""),
242
5
                   ((packet_flags & KDP_RST_FLAG) ? "RST " : ""),
243
5
                   ((packet_flags & KDP_BCST_FLAG) ? "BCST " : ""),
244
5
                   ((packet_flags & KDP_DUP_FLAG) ? "DUP " : ""),
245
5
                   ack_string,
246
5
                   seq_num_string,
247
5
                   src_flowid_string,
248
5
                   packet_errors);
249
5
  }
250
251
6
  return tvb_captured_length(tvb);
252
18
}
253
254
14
void proto_register_kdp(void) {
255
256
14
  static hf_register_info hf[] = {
257
14
    { &hf_kdp_version,
258
14
      {"KDP version", "kdp.version",
259
14
       FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
260
14
    },
261
14
    { &hf_kdp_headerlen,
262
14
      {"KDP header len", "kdp.headerlen",
263
14
       FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
264
14
    },
265
14
    { &hf_kdp_flags,
266
14
      {"KDP flags", "kdp.flags",
267
14
       FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
268
14
    },
269
14
    { &hf_kdp_drop_flag,
270
14
      {"KDP DROP Flag", "kdp.flags.drop",
271
14
       FT_BOOLEAN, 8, NULL, KDP_DROP_FLAG, NULL, HFILL}
272
14
    },
273
14
    { &hf_kdp_syn_flag,
274
14
      {"KDP SYN Flag", "kdp.flags.syn",
275
14
       FT_BOOLEAN, 8, NULL, KDP_SYN_FLAG, NULL, HFILL}
276
14
    },
277
14
    { &hf_kdp_ack_flag,
278
14
      {"KDP ACK Flag", "kdp.flags.ack",
279
14
       FT_BOOLEAN, 8, NULL, KDP_ACK_FLAG, NULL, HFILL}
280
14
    },
281
14
    { &hf_kdp_rst_flag,
282
14
      {"KDP RST Flag", "kdp.flags.rst",
283
14
       FT_BOOLEAN, 8, NULL, KDP_RST_FLAG, NULL, HFILL}
284
14
    },
285
14
    { &hf_kdp_bcst_flag,
286
14
      {"KDP BCST Flag", "kdp.flags.bcst",
287
14
       FT_BOOLEAN, 8, NULL, KDP_BCST_FLAG, NULL, HFILL}
288
14
    },
289
14
    { &hf_kdp_dup_flag,
290
14
      {"KDP DUP Flag", "kdp.flags.dup",
291
14
       FT_BOOLEAN, 8, NULL, KDP_DUP_FLAG, NULL, HFILL}
292
14
    },
293
14
    { &hf_kdp_errors,
294
14
      {"KDP errors", "kdp.errors",
295
14
       FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}
296
14
    },
297
14
    { &hf_kdp_destflowid,
298
14
      { "DestFlowID", "kdp.destflowid",
299
14
        FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}
300
14
    },
301
14
    { &hf_kdp_srcflowid,
302
14
      { "SrcFlowID", "kdp.srcflowid",
303
14
        FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}
304
14
    },
305
14
    { &hf_kdp_sequence,
306
14
      { "Sequence", "kdp.sequence",
307
14
        FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}
308
14
    },
309
14
    { &hf_kdp_ack,
310
14
      { "Ack", "kdp.ack",
311
14
        FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}
312
14
    },
313
14
    { &hf_kdp_maxsegmentsize,
314
14
      { "MaxSegmentSize", "kdp.maxsegmentsize",
315
14
        FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}
316
14
    },
317
14
    { &hf_kdp_optionnumber,
318
14
      { "Option Number", "kdp.optionnumber",
319
14
        FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
320
14
    },
321
14
    { &hf_kdp_optionlen,
322
14
      { "Option Len", "kdp.option",
323
14
        FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL}
324
14
    },
325
14
    { &hf_kdp_option1,
326
14
      { "Option1 - Max Window", "kdp.option1",
327
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}
328
14
    },
329
14
    { &hf_kdp_option2,
330
14
      { "Option2 - TCP Fraction", "kdp.option2",
331
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}
332
14
    },
333
14
    { &hf_kdp_option3,
334
14
      { "Option3 - KDP Version", "kdp.option3",
335
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}
336
14
    },
337
14
    { &hf_kdp_option4,
338
14
      { "Option4 - Enable Reliable", "kdp.option4",
339
14
        FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}
340
14
    },
341
14
    { &hf_kdp_option5,
342
14
      { "Option5 - Disable Reliable", "kdp.option5",
343
14
        FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}
344
14
    },
345
14
    { &hf_kdp_option6,
346
14
      { "Option6 - SACK", "kdp.option6",
347
14
        FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
348
14
    },
349
14
    { &hf_kdp_option7,
350
14
      { "Option7 - COS", "kdp.option7",
351
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}
352
14
    },
353
14
    { &hf_kdp_option8,
354
14
      { "Option8 - BWMIN", "kdp.option8",
355
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}
356
14
    },
357
14
    { &hf_kdp_option9,
358
14
      { "Option9 - INT", "kdp.option9",
359
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}
360
14
    },
361
14
    { &hf_kdp_option_unknown,
362
14
      { "Unknown option", "kdp.option_unknown",
363
14
        FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
364
14
    },
365
14
    { &hf_kdp_fragment,
366
14
      { "Fragment", "kdp.fragment",
367
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}
368
14
    },
369
14
    { &hf_kdp_fragtotal,
370
14
      { "FragTotal", "kdp.fragtotal",
371
14
        FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL}
372
14
    },
373
14
    { &hf_kdp_body,
374
14
      { "Encrypted Body", "kdp.body",
375
14
        FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}
376
14
    },
377
14
    { &hf_kdp_xml_body,
378
14
      { "XML Body", "kdp.xml_body",
379
14
        FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL}
380
14
    }
381
14
  };
382
383
  /* Setup protocol subtree array */
384
14
  static int *ett[] = {
385
14
    &ett_kdp, &ett_kdp_flags
386
14
  };
387
388
14
  proto_kdp = proto_register_protocol("Kontiki Delivery Protocol", "KDP", "kdp"); /* name, short name, abbreviation */
389
14
  proto_register_field_array(proto_kdp, hf, array_length(hf));
390
14
  proto_register_subtree_array(ett, array_length(ett));
391
392
14
  kdp_handle = register_dissector("kdp", dissect_kdp, proto_kdp);
393
14
}
394
395
void
396
14
proto_reg_handoff_kdp(void) {
397
14
  dissector_add_uint_with_preference("udp.port", KDP_PORT, kdp_handle);
398
14
}
399
400
/*
401
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
402
 *
403
 * Local Variables:
404
 * c-basic-offset: 2
405
 * tab-width: 8
406
 * indent-tabs-mode: nil
407
 * End:
408
 *
409
 * ex: set shiftwidth=2 tabstop=8 expandtab:
410
 * :indentSize=2:tabSize=8:noTabs=true:
411
 */