Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-rpl.c
Line
Count
Source
1
/* packet-rpl.c
2
 * Routines for RPL
3
 * Jochen Friedrich <jochen@scram.de>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
16
#include "packet-llc.h"
17
18
void proto_register_rpl(void);
19
void proto_reg_handoff_rpl(void);
20
21
static int proto_rpl;
22
23
static int hf_rpl_type;
24
static int hf_rpl_len;
25
static int hf_rpl_corrval;
26
static int hf_rpl_respval;
27
static int hf_rpl_maxframe;
28
static int hf_rpl_connclass;
29
static int hf_rpl_lmac;
30
static int hf_rpl_smac;
31
static int hf_rpl_sap;
32
static int hf_rpl_equipment;
33
static int hf_rpl_memsize;
34
static int hf_rpl_bsmversion;
35
static int hf_rpl_adapterid;
36
static int hf_rpl_shortname;
37
static int hf_rpl_laddress;
38
static int hf_rpl_xaddress;
39
static int hf_rpl_sequence;
40
static int hf_rpl_config;
41
static int hf_rpl_flags;
42
static int hf_rpl_data;
43
static int hf_rpl_ec;
44
45
static int ett_rpl;
46
static int ett_rpl_0004;
47
static int ett_rpl_0008;
48
static int ett_rpl_4003;
49
static int ett_rpl_4006;
50
static int ett_rpl_4007;
51
static int ett_rpl_4009;
52
static int ett_rpl_400a;
53
static int ett_rpl_400b;
54
static int ett_rpl_400c;
55
static int ett_rpl_4011;
56
static int ett_rpl_4018;
57
static int ett_rpl_c005;
58
static int ett_rpl_c014;
59
static int ett_rpl_unkn;
60
61
static dissector_handle_t rpl_handle;
62
63
static const value_string rpl_type_vals[] = {
64
  { 1,    "FIND Command" },
65
  { 2,    "FOUND Frame" },
66
  { 4,    "Search Vector" },
67
  { 8,    "Connect Info Vector" },
68
  { 0x10,   "Send File Request" },
69
  { 0x20,   "File Data Response" },
70
  { 0x4003, "Correlator Vector" },
71
  { 0x4006, "Loader Address Vector" },
72
  { 0x4007, "Loader SAP Vector" },
73
  { 0x4009, "Frame Size Sub-Vector" },
74
  { 0x400a, "Connect Class Sub-Vector" },
75
  { 0x400b, "Response Correlator" },
76
  { 0x400c, "Set Address Vector" },
77
  { 0x4011, "Sequence Header" },
78
  { 0x4018, "File Data Vector" },
79
  { 0xc005, "Loader Info Sub-Vector" },
80
  { 0xc014, "Loader Header" },
81
  { 0x0,  NULL }
82
};
83
84
static void
85
// NOLINTNEXTLINE(misc-no-recursion)
86
dissect_rpl_container(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
87
25
{
88
25
  uint16_t len, type, sublen, subtyp;
89
25
  proto_tree *rpl_container_tree;
90
25
  uint16_t offset;
91
25
  int ett_type;
92
25
  int reported_length;
93
94
25
  proto_tree_add_item_ret_uint16(tree, hf_rpl_len, tvb, 0, 2, ENC_BIG_ENDIAN, &len);
95
96
25
  proto_tree_add_item_ret_uint16(tree, hf_rpl_type, tvb, 2, 2, ENC_BIG_ENDIAN, &type);
97
25
  offset = 4;
98
99
25
  switch (type) {
100
0
    case 1:
101
4
    case 2:
102
7
    case 4:
103
7
    case 8:
104
8
    case 0x10:
105
8
    case 0x20:
106
15
      while (len >= offset+4) {
107
12
        sublen = tvb_get_ntohs(tvb, offset);
108
12
        subtyp = tvb_get_ntohs(tvb, offset+2);
109
12
        ett_type = ett_rpl_unkn;
110
12
        if(subtyp == 0x0004) ett_type = ett_rpl_0004;
111
12
        if(subtyp == 0x0008) ett_type = ett_rpl_0008;
112
12
        if(subtyp == 0x4003) ett_type = ett_rpl_4003;
113
12
        if(subtyp == 0x4006) ett_type = ett_rpl_4006;
114
12
        if(subtyp == 0x4007) ett_type = ett_rpl_4007;
115
12
        if(subtyp == 0x4009) ett_type = ett_rpl_4009;
116
12
        if(subtyp == 0x400a) ett_type = ett_rpl_400a;
117
12
        if(subtyp == 0x400b) ett_type = ett_rpl_400b;
118
12
        if(subtyp == 0x400c) ett_type = ett_rpl_400c;
119
12
        if(subtyp == 0x4011) ett_type = ett_rpl_4011;
120
12
        if(subtyp == 0x4018) ett_type = ett_rpl_4018;
121
12
        if(subtyp == 0xc005) ett_type = ett_rpl_c005;
122
12
        if(subtyp == 0xc014) ett_type = ett_rpl_c014;
123
12
        rpl_container_tree = proto_tree_add_subtree(tree, tvb,
124
12
          offset, sublen, ett_type, NULL,
125
12
          val_to_str_const(subtyp,
126
12
            rpl_type_vals,
127
12
            "Unknown Type"));
128
12
        reported_length = tvb_reported_length_remaining(tvb, offset);
129
12
        if (reported_length > sublen)
130
4
          reported_length = sublen;
131
12
        if ( reported_length > 0) {
132
7
          dissect_rpl_container(tvb_new_subset_length(tvb,
133
7
          offset, reported_length),
134
7
          pinfo, rpl_container_tree);
135
7
          offset += reported_length;
136
7
        } else {
137
          /* no more data, exit the loop */
138
5
          offset += reported_length;
139
5
          break;
140
5
        }
141
12
      }
142
8
      break;
143
144
0
    case 0x4003:
145
0
      proto_tree_add_item(tree, hf_rpl_corrval,
146
0
        tvb, offset, 4, ENC_BIG_ENDIAN);
147
0
      offset += 4;
148
0
      break;
149
150
0
    case 0x4006:
151
0
      proto_tree_add_item(tree, hf_rpl_lmac,
152
0
        tvb, offset, 6, ENC_NA);
153
0
      offset += 6;
154
0
      break;
155
156
0
    case 0x4007:
157
0
      proto_tree_add_item(tree, hf_rpl_sap,
158
0
        tvb, offset, 1, ENC_BIG_ENDIAN);
159
0
      offset ++;
160
0
      break;
161
162
0
    case 0x4009:
163
0
      proto_tree_add_item(tree, hf_rpl_maxframe,
164
0
        tvb, offset, 2, ENC_BIG_ENDIAN);
165
0
      offset += 2;
166
0
      break;
167
168
0
    case 0x400a:
169
0
      proto_tree_add_item(tree, hf_rpl_connclass,
170
0
        tvb, offset, 2, ENC_BIG_ENDIAN);
171
0
      offset += 2;
172
0
      break;
173
174
0
    case 0x400b:
175
0
      proto_tree_add_item(tree, hf_rpl_respval,
176
0
        tvb, offset, 1, ENC_BIG_ENDIAN);
177
0
      offset ++;
178
0
      break;
179
180
0
    case 0x400c:
181
0
      proto_tree_add_item(tree, hf_rpl_smac,
182
0
        tvb, offset, 6, ENC_NA);
183
0
      offset += 6;
184
0
      break;
185
186
0
    case 0x4011:
187
0
      proto_tree_add_item(tree, hf_rpl_sequence,
188
0
        tvb, offset, 4, ENC_BIG_ENDIAN);
189
0
      offset += 4;
190
0
      break;
191
192
0
    case 0x4018:
193
0
      proto_tree_add_item(tree, hf_rpl_data,
194
0
        tvb, offset, len-4, ENC_NA);
195
0
      offset += len - 4;
196
0
      break;
197
198
0
    case 0xc005:
199
0
      proto_tree_add_item(tree, hf_rpl_config,
200
0
        tvb, offset, 8, ENC_NA);
201
0
      offset += 8;
202
0
      proto_tree_add_item(tree, hf_rpl_equipment,
203
0
        tvb, offset, 2, ENC_BIG_ENDIAN);
204
0
      offset += 2;
205
0
      proto_tree_add_item(tree, hf_rpl_memsize,
206
0
        tvb, offset, 2, ENC_BIG_ENDIAN);
207
0
      offset += 2;
208
0
      proto_tree_add_item(tree, hf_rpl_bsmversion,
209
0
        tvb, offset, 2, ENC_BIG_ENDIAN);
210
0
      offset += 2;
211
0
      proto_tree_add_item(tree, hf_rpl_ec,
212
0
        tvb, offset, 6, ENC_NA);
213
0
      offset += 6;
214
0
      proto_tree_add_item(tree, hf_rpl_adapterid,
215
0
        tvb, offset, 2, ENC_BIG_ENDIAN);
216
0
      offset += 2;
217
0
      proto_tree_add_item(tree, hf_rpl_shortname,
218
0
        tvb, offset, 10, ENC_NA);
219
0
      offset += 10;
220
0
      break;
221
222
0
    case 0xc014:
223
0
      proto_tree_add_item(tree, hf_rpl_laddress,
224
0
        tvb, offset, 4, ENC_BIG_ENDIAN);
225
0
      offset += 4;
226
0
      proto_tree_add_item(tree, hf_rpl_xaddress,
227
0
        tvb, offset, 4, ENC_BIG_ENDIAN);
228
0
      offset += 4;
229
0
      proto_tree_add_item(tree, hf_rpl_flags,
230
0
        tvb, offset, 1, ENC_BIG_ENDIAN);
231
0
      offset ++;
232
0
      break;
233
234
14
    default:
235
14
      call_data_dissector(tvb_new_subset_remaining(tvb, 4), pinfo,
236
14
        tree);
237
14
      break;
238
25
  }
239
16
  if (tvb_reported_length(tvb) > offset)
240
14
    call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, tree);
241
16
}
242
243
static int
244
dissect_rpl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
245
18
{
246
18
  uint16_t rpl_len, rpl_type;
247
18
  proto_item *ti;
248
18
  proto_tree *rpl_tree;
249
18
  tvbuff_t *next_tvb;
250
251
18
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "RPL");
252
253
18
  rpl_len  = tvb_get_ntohs(tvb, 0);
254
18
  rpl_type = tvb_get_ntohs(tvb, 2);
255
256
18
  col_set_str(pinfo->cinfo, COL_INFO,
257
18
        val_to_str_const(rpl_type, rpl_type_vals, "Unknown Type"));
258
259
18
  ti = proto_tree_add_item(tree, proto_rpl, tvb, 0,
260
18
    rpl_len, ENC_NA);
261
18
  rpl_tree = proto_item_add_subtree(ti, ett_rpl);
262
18
  next_tvb = tvb_new_subset_remaining(tvb, 0);
263
18
  set_actual_length(next_tvb, rpl_len);
264
18
  dissect_rpl_container(next_tvb, pinfo, rpl_tree);
265
266
18
  if (tvb_reported_length(tvb) > rpl_len)
267
2
    call_data_dissector(tvb_new_subset_remaining(tvb, rpl_len), pinfo,
268
2
        tree);
269
270
18
  return tvb_captured_length(tvb);
271
18
}
272
273
void
274
proto_register_rpl(void)
275
15
{
276
15
  static hf_register_info hf[] = {
277
15
    { &hf_rpl_type,
278
15
      { "Type", "rpl.type",
279
15
        FT_UINT16, BASE_DEC, VALS(rpl_type_vals), 0x0,
280
15
        "RPL Packet Type", HFILL }},
281
15
    { &hf_rpl_len,
282
15
      { "Length", "rpl.len",
283
15
        FT_UINT16, BASE_DEC, NULL, 0x0,
284
15
        "RPL Packet Length", HFILL }},
285
15
    { &hf_rpl_corrval,
286
15
      { "Correlator Value", "rpl.corrval",
287
15
        FT_UINT32, BASE_HEX, NULL, 0x0,
288
15
        "RPL Correlator Value", HFILL }},
289
15
    { &hf_rpl_respval,
290
15
      { "Response Code", "rpl.respval",
291
15
        FT_UINT8, BASE_DEC, NULL, 0x0,
292
15
        "RPL Response Code", HFILL }},
293
15
    { &hf_rpl_maxframe,
294
15
      { "Maximum Frame Size", "rpl.maxframe",
295
15
        FT_UINT16, BASE_DEC, NULL, 0x0,
296
15
        "RPL Maximum Frame Size", HFILL }},
297
15
    { &hf_rpl_connclass,
298
15
      { "Connection Class", "rpl.connclass",
299
15
        FT_UINT16, BASE_HEX, NULL, 0x0,
300
15
        "RPL Connection Class", HFILL }},
301
15
    { &hf_rpl_lmac,
302
15
      { "Loader MAC Address", "rpl.lmac",
303
15
        FT_ETHER, BASE_NONE, NULL, 0x0,
304
15
        "RPL Loader MAC Address", HFILL }},
305
15
    { &hf_rpl_smac,
306
15
      { "Set MAC Address", "rpl.smac",
307
15
        FT_ETHER, BASE_NONE, NULL, 0x0,
308
15
        "RPL Set MAC Address", HFILL }},
309
15
    { &hf_rpl_sap,
310
15
      { "SAP", "rpl.sap",
311
15
        FT_UINT8, BASE_HEX, VALS(sap_vals), 0x0,
312
15
        "RPL SAP", HFILL }},
313
15
    { &hf_rpl_equipment,
314
15
      { "Equipment", "rpl.equipment",
315
15
        FT_UINT16, BASE_HEX, NULL, 0x0,
316
15
        "RPL Equipment - AX from INT 11h", HFILL }},
317
15
    { &hf_rpl_memsize,
318
15
      { "Memory Size", "rpl.memsize",
319
15
        FT_UINT16, BASE_DEC, NULL, 0x0,
320
15
        "RPL Memory Size - AX from INT 12h MINUS 32k MINUS the Boot ROM Size", HFILL }},
321
15
    { &hf_rpl_bsmversion,
322
15
      { "BSM Version", "rpl.bsmversion",
323
15
        FT_UINT16, BASE_HEX, NULL, 0x0,
324
15
        "RPL Version of BSM.obj", HFILL }},
325
15
    { &hf_rpl_adapterid,
326
15
      { "Adapter ID", "rpl.adapterid",
327
15
        FT_UINT16, BASE_HEX, NULL, 0x0,
328
15
        "RPL Adapter ID", HFILL }},
329
15
    { &hf_rpl_shortname,
330
15
      { "Short Name", "rpl.shortname",
331
15
        FT_BYTES, BASE_NONE, NULL, 0x0,
332
15
        "RPL BSM Short Name", HFILL }},
333
15
    { &hf_rpl_laddress,
334
15
      { "Locate Address", "rpl.laddress",
335
15
        FT_UINT32, BASE_HEX, NULL, 0x0,
336
15
        "RPL Locate Address", HFILL }},
337
15
    { &hf_rpl_xaddress,
338
15
      { "XFER Address", "rpl.xaddress",
339
15
        FT_UINT32, BASE_HEX, NULL, 0x0,
340
15
        "RPL Transfer Control Address", HFILL }},
341
15
    { &hf_rpl_sequence,
342
15
      { "Sequence Number", "rpl.sequence",
343
15
        FT_UINT32, BASE_HEX, NULL, 0x0,
344
15
        "RPL Sequence Number", HFILL }},
345
15
    { &hf_rpl_config,
346
15
      { "Configuration", "rpl.config",
347
15
        FT_BYTES, BASE_NONE, NULL, 0x0,
348
15
         "RPL Configuration", HFILL }},
349
15
    { &hf_rpl_flags,
350
15
      { "Flags", "rpl.flags",
351
15
        FT_UINT8, BASE_HEX, NULL, 0x0,
352
15
        "RPL Bit Significant Option Flags", HFILL }},
353
15
    { &hf_rpl_data,
354
15
      { "Data", "rpl.data",
355
15
        FT_BYTES, BASE_NONE, NULL, 0x0,
356
15
        "RPL Binary File Data", HFILL }},
357
15
    { &hf_rpl_ec,
358
15
      { "EC", "rpl.ec",
359
15
        FT_BYTES, BASE_NONE, NULL, 0x0,
360
15
        "RPL EC", HFILL }},
361
15
  };
362
363
15
  static int *ett[] = {
364
15
    &ett_rpl,
365
15
    &ett_rpl_0004,
366
15
    &ett_rpl_0008,
367
15
    &ett_rpl_4003,
368
15
    &ett_rpl_4006,
369
15
    &ett_rpl_4007,
370
15
    &ett_rpl_4009,
371
15
    &ett_rpl_400a,
372
15
    &ett_rpl_400b,
373
15
    &ett_rpl_400c,
374
15
    &ett_rpl_4011,
375
15
    &ett_rpl_4018,
376
15
    &ett_rpl_c005,
377
15
    &ett_rpl_c014,
378
15
    &ett_rpl_unkn
379
15
  };
380
381
15
  proto_rpl = proto_register_protocol("Remote Program Load", "RPL", "rpl");
382
15
  proto_register_field_array(proto_rpl, hf, array_length(hf));
383
15
  proto_register_subtree_array(ett, array_length(ett));
384
15
  rpl_handle = register_dissector("rpl", dissect_rpl, proto_rpl);
385
15
}
386
387
void
388
proto_reg_handoff_rpl(void)
389
15
{
390
15
  dissector_add_uint("llc.dsap", SAP_RPL, rpl_handle);
391
15
}
392
393
/*
394
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
395
 *
396
 * Local variables:
397
 * c-basic-offset: 8
398
 * tab-width: 8
399
 * indent-tabs-mode: t
400
 * End:
401
 *
402
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
403
 * :indentSize=8:tabSize=8:noTabs=false:
404
 */