Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-rtps-virtual-transport.c
Line
Count
Source
1
/* packet-rtps-virtual-transport.c
2
 * Dissector for the Real-Time Publish-Subscribe (RTPS) Virtual Transport
3
 * Protocol.
4
 *
5
 * (c) 2020 Copyright, Real-Time Innovations, Inc.
6
 * Real-Time Innovations, Inc.
7
 * 232 East Java Drive
8
 * Sunnyvale, CA 94089
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
 * -----------------------------------------------------------------------------
17
 * RTI Connext DDS can capture RTPS-related traffic by using the Network Capture
18
 * Utility. The generated .pcap capture files will follow the RTPS-VT protocol,
19
 * which establishes a format for how information must be saved, and then
20
 * parsed.
21
 *
22
 * The protocol is divided into two layers: transport
23
 * (packet-rtps-virtual-transport.c) and advanced (packet-rtps-processed.c).
24
 * This file is about the transport dissector. For more information about the
25
 * advanced dissector, read the documentation at the beginning of
26
 * packet-rtps-processed.c.
27
 *
28
 * Every packet saved in the capture file follows the PCAP file format.
29
 * As a consequence, there are two headers: a global one (unique per file) and
30
 * a per-packet header. These headers have the typical content described in the
31
 * PCAP format: a magic number, version number, some timestamps, information
32
 * describing the length of the packet and the data link layer (0x000000fc, i.e.
33
 * custom protocol), etc. Then, we have a header that indicates Wireshark the
34
 * name of the protocol: "rtpsvt". The transport dissector is called when
35
 * Wireshark finds "rtpsvt" as the protocol name.
36
 *
37
 * After the RTPS-VT header, we have the frame type. The frame type determines
38
 * what kind of information has the dumped packet. RTPS-VT data comes as a
39
 * series of [parameter identifier, content length, content]. Depending on the
40
 * type of frame (RTPS or lossInfo), the dissector will expect some parameters
41
 * or others.
42
 *
43
 * If the frame type is RTPS, we will continue parsing transport-layer data.
44
 * The transport layer contains all information about the source and destination
45
 * of a packet. This corresponds to data typically found on Network or Transport
46
 * protocols. However, because RTI Connext DDS generates the capture file
47
 * directly at application-level, this information is added at the moment of
48
 * writing the capture file.
49
 * After the transport-layer information, we will call the advanced dissector.
50
 *
51
 * If the frame type is lossInfo, the dissector will generate a packet
52
 * indicating that there were missing frames (and the range of sequence
53
 * numbers).
54
 */
55
#include "config.h"
56
57
#include <epan/packet.h>
58
#include <epan/expert.h>
59
#include <epan/prefs.h>
60
#include <epan/addr_resolv.h>
61
#include <epan/wmem_scopes.h>
62
#include <epan/conversation.h>
63
#include "packet-tcp.h"
64
#include "packet-rtps.h"
65
66
67
0
#define CONTENT_KIND_RTPS                        0x01
68
0
#define CONTENT_KIND_LOSS_INFO                   0x02
69
70
0
#define PARAM_ID_TRANSPORT_CLASS                 0x0001
71
0
#define PARAM_ID_MONITORING_GUID                 0x0002
72
0
#define PARAM_ID_MONITORING_SN                   0x0003
73
0
#define PARAM_ID_SOURCE_IP_ADDRESS               0x0004
74
0
#define PARAM_ID_SOURCE_PORT                     0x0005
75
0
#define PARAM_ID_DESTINATION_IP_ADDRESS          0x0006
76
0
#define PARAM_ID_DESTINATION_RTPS_PORT           0x0007
77
0
#define PARAM_ID_DESTINATION_PORT                0x0008
78
0
#define PARAM_ID_DIRECTION                       0x0009
79
0
#define FIRST_PARAM_ID_RTPS  PARAM_ID_TRANSPORT_CLASS
80
0
#define LAST_PARAM_ID_RTPS   PARAM_ID_DIRECTION
81
82
/* First parameter Identifier that the "rtpsproc" protocol accepts */
83
0
#define PARAM_ID_MAIN_FRAME                      0x00C0
84
85
0
#define PARAM_ID_LOST_MESSAGES                   0x0001
86
87
void proto_register_rtps_virtual_transport(void);
88
static int dissect_rtps_virtual_transport(
89
        tvbuff_t *tvb,
90
        packet_info *pinfo,
91
        proto_tree *tree,
92
        void *data _U_);
93
static int dissect_rtps_virtual_transport_rtps_type(
94
        tvbuff_t *tvb,
95
        packet_info *pinfo,
96
        proto_tree *tree,
97
        proto_tree *tree_transport,
98
        int offset,
99
        struct rtpsvt_data *transport_data);
100
static int dissect_parameter_transport_rtps_type(
101
        tvbuff_t *tvb,
102
        proto_tree *rtpsvt_tree_general,
103
        proto_tree *rtpsvt_tree_identifier,
104
        proto_tree *rtpsvt_tree_information,
105
        int offset,
106
        packet_info *pinfo,
107
        struct rtpsvt_data *transport_data);
108
static int dissect_rtps_virtual_transport_loss_info_type(
109
        tvbuff_t *tvb,
110
        packet_info *pinfo,
111
        proto_tree *tree_transport,
112
        int offset);
113
114
/* Subtree pointers */
115
static int proto_rtpsvt;
116
static int ett_rtpsvt;
117
static int ett_rtpsvt_version;
118
static int ett_rtpsvt_identifier;
119
static int ett_rtpsvt_information;
120
static int ett_rtpsvt_information_class;
121
static int ett_rtpsvt_information_src_port;
122
static int ett_rtpsvt_information_dst_port;
123
static int ett_rtpsvt_information_src_addr;
124
static int ett_rtpsvt_information_dst_addr;
125
static int ett_rtpsvt_information_direction;
126
static int ett_rtpsvt_monitoring_sn;
127
static int ett_rtpsvt_frame;
128
129
/* Initialize the protocol and registered fields */
130
static header_field_info *rtpsvt_hf;
131
static int hf_rtpsvt_version;
132
static int hf_rtpsvt_version_major;
133
static int hf_rtpsvt_version_minor;
134
static int hf_rtpsvt_content_kind;
135
static int hf_rtpsvt_param_id;
136
static int hf_rtpsvt_param_length;
137
static int hf_rtpsvt_packet_identifier;
138
static int hf_rtpsvt_monitoring_guid;
139
static int hf_rtpsvt_monitoring_seqNr;
140
static int hf_rtpsvt_information;
141
static int hf_rtpsvt_class;
142
static int hf_rtpsvt_source_port;
143
static int hf_rtpsvt_source_address;
144
static int hf_rtpsvt_source_pid;
145
static int hf_rtpsvt_destination_port;
146
static int hf_rtpsvt_destination_rtps_port;
147
static int hf_rtpsvt_destination_address;
148
static int hf_rtpsvt_direction;
149
static int hf_rtpsvt_destination_pid;
150
static int hf_rtpsvt_missing_messages;
151
152
/* expert info fields */
153
static expert_field ei_missing_msg;
154
155
/* Vendor specific: RTI */
156
static const value_string ndds_transport_class_id_vals[] = {
157
    { NDDS_TRANSPORT_CLASSID_ANY,           "ANY" },
158
    { NDDS_TRANSPORT_CLASSID_UDPv4,         "UDPv4" },
159
    { NDDS_TRANSPORT_CLASSID_UDPv4_WAN,     "UDPv4_WAN"},
160
    { NDDS_TRANSPORT_CLASSID_SHMEM,         "SHMEM" },
161
    { NDDS_TRANSPORT_CLASSID_INTRA,         "INTRA" },
162
    { NDDS_TRANSPORT_CLASSID_UDPv6,         "UDPv6" },
163
    { NDDS_TRANSPORT_CLASSID_DTLS,          "DTLS" },
164
    { NDDS_TRANSPORT_CLASSID_WAN,           "WAN" },
165
    { NDDS_TRANSPORT_CLASSID_TCPV4_LAN,     "TCPv4_LAN" },
166
    { NDDS_TRANSPORT_CLASSID_TCPV4_WAN,     "TCPv4_WAN" },
167
    { NDDS_TRANSPORT_CLASSID_TLSV4_LAN,     "TLSv4_LAN" },
168
    { NDDS_TRANSPORT_CLASSID_TLSV4_WAN,     "TLSv4_WAN" },
169
    { NDDS_TRANSPORT_CLASSID_PCIE,          "PCIE" },
170
    { NDDS_TRANSPORT_CLASSID_ITP,           "ITP" },
171
    { 0, NULL }
172
};
173
174
static int dissect_rtps_virtual_transport(
175
        tvbuff_t *tvb,
176
        packet_info *pinfo,
177
        proto_tree *tree,
178
        void *data _U_)
179
0
{
180
0
    proto_tree *rtpsvt_tree_transport;
181
0
    proto_item *rtpsvt_ti_transport;
182
0
    proto_item *rtpsvt_ti_version;
183
0
    proto_tree *rtpsvt_tree_version;
184
0
    proto_item *rtpsvt_ti_content_kind;
185
    /* XXX - What if some of the parameters are missing, such as the
186
     * direction? Should RTPS-PROC, which tries to use those parameter
187
     * values, not be called? */
188
0
    struct rtpsvt_data transport_data = {0};
189
0
    uint16_t version;
190
0
    uint8_t content_type;
191
0
    const char *content_type_label;
192
0
    unsigned offset = 0;
193
0
    int output = 0;
194
195
    /* Add transport tree, used for the fields of our proto_rtpsvt */
196
0
    rtpsvt_ti_transport = proto_tree_add_item(
197
0
            tree,
198
0
            proto_rtpsvt,
199
0
            tvb,
200
0
            offset,
201
0
            -1,
202
0
            ENC_BIG_ENDIAN);
203
0
    rtpsvt_tree_transport = proto_item_add_subtree(rtpsvt_ti_transport, ett_rtpsvt);
204
205
    /* Add the version to the transport protocol */
206
0
    version = tvb_get_ntohs(tvb, offset);
207
0
    transport_data.version_major = version >> 8;
208
0
    transport_data.version_minor = version & 0xff;
209
0
    rtpsvt_ti_version = proto_tree_add_uint_format(
210
0
            rtpsvt_tree_transport,
211
0
            hf_rtpsvt_version,
212
0
            tvb,
213
0
            offset,
214
0
            2, /* 2B: sizeof(uint16_t) */
215
0
            version,
216
0
            "Version: %d.%d",
217
0
            transport_data.version_major,
218
0
            transport_data.version_minor);
219
0
    rtpsvt_tree_version = proto_item_add_subtree(
220
0
            rtpsvt_ti_version,
221
0
            ett_rtpsvt_version);
222
223
0
    proto_tree_add_item(
224
0
            rtpsvt_tree_version,
225
0
            hf_rtpsvt_version_major,
226
0
            tvb,
227
0
            offset,
228
0
            1, /* length: sizeof(uint8_t) */
229
0
            ENC_NA);
230
0
    proto_tree_add_item(
231
0
            rtpsvt_tree_version,
232
0
            hf_rtpsvt_version_minor,
233
0
            tvb,
234
0
            offset + 1,
235
0
            1, /* length: sizeof(uint8_t) */
236
0
            ENC_NA);
237
0
    offset += 2;
238
239
    /* Add the content kind. */
240
0
    content_type = tvb_get_uint8(tvb, offset);
241
0
    rtpsvt_ti_content_kind = proto_tree_add_item(
242
0
            rtpsvt_ti_transport,
243
0
            hf_rtpsvt_content_kind,
244
0
            tvb,
245
0
            offset,
246
0
            1, /* length: sizeof(uint8_t) */
247
0
            ENC_NA);
248
0
    if (content_type == CONTENT_KIND_RTPS) {
249
0
        content_type_label = "RTPS";
250
0
    } else {
251
0
        content_type_label = "LOST_INFO";
252
0
    }
253
0
    proto_item_append_text(rtpsvt_ti_content_kind, " (%s)", content_type_label);
254
0
    offset += 1;
255
256
0
    switch(content_type) {
257
0
        case CONTENT_KIND_RTPS:
258
0
            output = dissect_rtps_virtual_transport_rtps_type(
259
0
                    tvb,
260
0
                    pinfo,
261
0
                    tree,
262
0
                    rtpsvt_tree_transport,
263
0
                    offset,
264
0
                    &transport_data);
265
0
            break;
266
267
0
        case CONTENT_KIND_LOSS_INFO:
268
0
            output = dissect_rtps_virtual_transport_loss_info_type(
269
0
                    tvb,
270
0
                    pinfo,
271
0
                    rtpsvt_tree_transport,
272
0
                    offset);
273
0
            break;
274
0
    }
275
0
    return output;
276
0
}
277
278
static int dissect_rtps_virtual_transport_rtps_type(
279
        tvbuff_t *tvb,
280
        packet_info *pinfo,
281
        proto_tree *tree,
282
        proto_tree *tree_transport,
283
        int offset,
284
        struct rtpsvt_data *transport_data)
285
0
{
286
0
    proto_item *rtpsvt_ti_identifier;
287
0
    proto_tree *rtpsvt_tree_identifier;
288
0
    proto_item *rtpsvt_ti_information;
289
0
    proto_tree *rtpsvt_tree_information;
290
0
    tvbuff_t *advanced_payload;
291
0
    static dissector_handle_t advanced_handle = NULL;
292
0
    unsigned int idx = FIRST_PARAM_ID_RTPS;
293
0
    uint16_t param_id;
294
0
    uint16_t param_length;
295
296
    /*
297
     * Add the tree for the packet identifier, which will be populated in
298
     * dissect_parameter_transport_rtps_type.
299
     */
300
0
    rtpsvt_ti_identifier = proto_tree_add_item(
301
0
            tree_transport,
302
0
            hf_rtpsvt_packet_identifier,
303
0
            tvb,
304
0
            offset,
305
0
            -1,
306
0
            ENC_NA);
307
0
    rtpsvt_tree_identifier = proto_item_add_subtree(
308
0
            rtpsvt_ti_identifier,
309
0
            ett_rtpsvt_identifier);
310
311
    /*
312
     * Add the tree for the transport information, which will be populated in
313
     * dissect_parameter_transport_rtps_type.
314
     */
315
0
    rtpsvt_ti_information = proto_tree_add_item(
316
0
            tree_transport,
317
0
            hf_rtpsvt_information,
318
0
            tvb,
319
0
            offset,
320
0
            -1,
321
0
            ENC_NA);
322
0
    rtpsvt_tree_information = proto_item_add_subtree(
323
0
            rtpsvt_ti_information,
324
0
            ett_rtpsvt_information);
325
326
    /*
327
     * Each parameter has an id, a length and a value.
328
     */
329
0
    for (idx = FIRST_PARAM_ID_RTPS; idx <= LAST_PARAM_ID_RTPS; idx++) {
330
0
        offset = dissect_parameter_transport_rtps_type(
331
0
                tvb,
332
0
                tree_transport,
333
0
                rtpsvt_tree_identifier,
334
0
                rtpsvt_tree_information,
335
0
                offset,
336
0
                pinfo,
337
0
                transport_data);
338
0
    }
339
340
    /*
341
     * In the future we may have more transport parameters.
342
     * These parameters will have an identifier less than PARAM_ID_MAIN_FRAME
343
     * (which is parsed by the rtpsproc dissector).
344
     * If we open a "future" capture file with this dissector, we will skip all
345
     * of those parameters and parse only the ones we know about.
346
     */
347
0
    do {
348
0
        param_id = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
349
0
        offset += 2;
350
0
        param_length = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
351
0
        offset += 2;
352
0
        if (param_id == PARAM_ID_MAIN_FRAME) {
353
0
            proto_tree *rtpsvt_tree_frame;
354
0
            transport_data->rtps_length = param_length;
355
0
            rtpsvt_tree_frame = proto_tree_add_subtree_format(
356
0
                    tree_transport,
357
0
                    tvb,
358
0
                    offset,
359
0
                    0,
360
0
                    ett_rtpsvt_frame,
361
0
                    NULL,
362
0
                    "Real-Time Publish-Subscribe Wire Protocol (content)");
363
364
0
            proto_tree_add_uint(
365
0
                    rtpsvt_tree_frame,
366
0
                    hf_rtpsvt_param_id,
367
0
                    tvb,
368
0
                    offset,
369
0
                    2, /* 2B: sizeof(uint16_t) */
370
0
                    param_id);
371
0
            proto_tree_add_uint(
372
0
                    rtpsvt_tree_frame,
373
0
                    hf_rtpsvt_param_length,
374
0
                    tvb,
375
0
                    offset + 2,
376
0
                    2,
377
0
                    param_length);
378
0
            break;
379
0
        }
380
0
        offset += param_length;
381
0
    } while (tvb_reported_length_remaining(tvb, offset) > 0);
382
383
0
    if (param_id != PARAM_ID_MAIN_FRAME || param_length <= 0) {
384
        /*
385
         * Reject the packet if we don't have an RTPS frame.
386
         * The rtpsproc dissector assumes that the contents start with the
387
         * RTPS frame (parameter value; the length is obtained from
388
         * transport_data).
389
         */
390
0
        return 0;
391
0
    }
392
393
0
    advanced_payload = tvb_new_subset_remaining(tvb, offset);
394
0
    advanced_handle = find_dissector("rtpsproc");
395
0
    call_dissector_with_data(
396
0
            advanced_handle,
397
0
            advanced_payload,
398
0
            pinfo,
399
0
            tree,
400
0
            (void *) transport_data);
401
402
0
    return tvb_captured_length(tvb);
403
0
}
404
405
static int dissect_parameter_transport_rtps_type(
406
        tvbuff_t *tvb,
407
        proto_tree *rtpsvt_tree_general,
408
        proto_tree *rtpsvt_tree_identifier,
409
        proto_tree *rtpsvt_tree_information,
410
        int offset,
411
        packet_info *pinfo,
412
        struct rtpsvt_data *transport_data)
413
0
{
414
    /*
415
     * We will add the parameter id and length later, as part of a subtree
416
     * dependent of the parameter.
417
     * That is why value of the parameter is now at offset + 4
418
     * (i.e. offset + sizeof(param_id) + sizeof(param_length))
419
     */
420
0
    uint16_t param_id = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
421
0
    uint16_t param_length = tvb_get_uint16(tvb, offset + 2, ENC_BIG_ENDIAN);
422
0
    const int OFFSET_TO_VAL = offset + 4;
423
0
    if (param_length <=0) {
424
        /* Length not valid: skip parameter (id + length) */
425
0
        return OFFSET_TO_VAL;
426
0
    }
427
428
0
    switch(param_id) {
429
0
        case PARAM_ID_TRANSPORT_CLASS:
430
0
            {
431
0
                proto_tree *rtpsvt_tree_information_class;
432
0
                int32_t classId = tvb_get_int32(tvb, OFFSET_TO_VAL, ENC_BIG_ENDIAN);
433
0
                const char *className = val_to_str(pinfo->pool,
434
0
                        classId,
435
0
                        ndds_transport_class_id_vals,
436
0
                        "%d");
437
438
0
                rtpsvt_tree_information_class = proto_tree_add_subtree_format(
439
0
                        rtpsvt_tree_information,
440
0
                        tvb,
441
0
                        offset,
442
0
                        0,
443
0
                        ett_rtpsvt_information_class,
444
0
                        NULL,
445
0
                        "Class: %s",
446
0
                        className);
447
448
                /* Add parameter identifier and length */
449
0
                proto_tree_add_uint(
450
0
                        rtpsvt_tree_information_class,
451
0
                        hf_rtpsvt_param_id,
452
0
                        tvb,
453
0
                        offset,
454
0
                        2, /* length: sizeof(uint16_t) */
455
0
                        param_id);
456
0
                offset += 2;
457
0
                proto_tree_add_uint(
458
0
                        rtpsvt_tree_information_class,
459
0
                        hf_rtpsvt_param_length,
460
0
                        tvb,
461
0
                        offset,
462
0
                        2, /* length: sizeof(uint16_t) */
463
0
                        param_length);
464
0
                offset += 2;
465
466
                /*
467
                 * Add transport class as item to the tree.
468
                 * This is useful to apply as column or filter.
469
                 */
470
0
                proto_tree_add_string(
471
0
                        rtpsvt_tree_information_class,
472
0
                        hf_rtpsvt_class,
473
0
                        tvb,
474
0
                        offset,
475
0
                        param_length,
476
0
                        className);
477
0
                offset += param_length;
478
479
                /* Add summary to protocol header */
480
0
                proto_item_append_text(rtpsvt_tree_general, ", %s", className);
481
482
                /* Add summary to the transport information header */
483
0
                proto_item_append_text(
484
0
                        rtpsvt_tree_information,
485
0
                        ", %s",
486
0
                        className);
487
0
            }
488
0
            break;
489
490
0
        case PARAM_ID_MONITORING_GUID:
491
0
            {
492
0
                proto_tree *rtpsvt_tree_monitoring_guid;
493
0
                const uint8_t *guid_bytes = tvb_get_ptr(
494
0
                        tvb,
495
0
                        OFFSET_TO_VAL,
496
0
                        param_length);
497
0
                const char *guid_string = bytes_to_str_punct(
498
0
                        pinfo->pool,
499
0
                        guid_bytes,
500
0
                        MIN(param_length, 12),
501
0
                        0);
502
503
0
                rtpsvt_tree_monitoring_guid = proto_tree_add_subtree_format(
504
0
                        rtpsvt_tree_identifier,
505
0
                        tvb,
506
0
                        offset,
507
0
                        0,
508
0
                        ett_rtpsvt_information_src_addr,
509
0
                        NULL,
510
0
                        "Monitoring GUID Prefix: %s",
511
0
                        guid_string);
512
513
                /* Add parameter identifier and length */
514
0
                proto_tree_add_uint(
515
0
                        rtpsvt_tree_monitoring_guid,
516
0
                        hf_rtpsvt_param_id,
517
0
                        tvb,
518
0
                        offset,
519
0
                        2, /* length: sizeof(uint16_t) */
520
0
                        param_id);
521
0
                offset += 2;
522
0
                proto_tree_add_uint(
523
0
                        rtpsvt_tree_monitoring_guid,
524
0
                        hf_rtpsvt_param_length,
525
0
                        tvb,
526
0
                        offset,
527
0
                        2, /* length: sizeof(uint16_t) */
528
0
                        param_length);
529
0
                offset += 2;
530
531
0
                proto_tree_add_item(
532
0
                        rtpsvt_tree_monitoring_guid,
533
0
                        hf_rtpsvt_monitoring_guid,
534
0
                        tvb,
535
0
                        offset,
536
0
                        param_length,
537
0
                        ENC_NA);
538
0
                offset += param_length;
539
540
                /* Add summary to packet identifier header */
541
0
                proto_item_append_text(
542
0
                        rtpsvt_tree_identifier,
543
0
                       ", GUID: %s",
544
0
                       guid_string);
545
0
            }
546
0
            break;
547
0
        case PARAM_ID_MONITORING_SN:
548
0
            {
549
0
                proto_tree *rtpsvt_tree_seqNr;
550
0
                uint64_t seqNr = tvb_get_uint64(tvb, OFFSET_TO_VAL, ENC_BIG_ENDIAN);
551
552
0
                rtpsvt_tree_seqNr = proto_tree_add_subtree_format(
553
0
                        rtpsvt_tree_identifier,
554
0
                        tvb,
555
0
                        offset,
556
0
                        0,
557
0
                        ett_rtpsvt_monitoring_sn,
558
0
                        NULL,
559
0
                        "Monitoring Sequence Number: %" PRIu64,
560
0
                        seqNr);
561
562
                /* Add parameter identifier and length */
563
0
                proto_tree_add_uint(
564
0
                        rtpsvt_tree_seqNr,
565
0
                        hf_rtpsvt_param_id,
566
0
                        tvb,
567
0
                        offset,
568
0
                        2, /* length: sizeof(uint16_t) */
569
0
                        param_id);
570
0
                offset += 2;
571
0
                proto_tree_add_uint(
572
0
                        rtpsvt_tree_seqNr,
573
0
                        hf_rtpsvt_param_length,
574
0
                        tvb,
575
0
                        offset,
576
0
                        2, /* length: sizeof(uint16_t) */
577
0
                        param_length);
578
0
                offset += 2;
579
580
0
                proto_tree_add_uint64(
581
0
                        rtpsvt_tree_seqNr,
582
0
                        hf_rtpsvt_monitoring_seqNr,
583
0
                        tvb,
584
0
                        offset,
585
0
                        param_length,
586
0
                        seqNr);
587
0
                offset += param_length;
588
589
                /* Add summary to packet identifier header */
590
0
                proto_item_append_text(
591
0
                        rtpsvt_tree_identifier,
592
0
                        ", SeqNum: %" PRIu64,
593
0
                        seqNr);
594
0
            }
595
0
            break;
596
0
        case PARAM_ID_SOURCE_IP_ADDRESS:
597
0
            {
598
0
                proto_tree *rtpsvt_tree_information_address;
599
0
                int temporary_hf = hf_rtpsvt_source_address;
600
0
                const char *prefix = "shmem_prefix";
601
0
                const char *title_tree = "Source address";
602
0
                char addr[COL_MAX_LEN];
603
0
                ws_in6_addr addr_raw;
604
0
                static const uint8_t bytes_zeroed[12] = {0};
605
0
                tvb_get_ipv6(tvb, OFFSET_TO_VAL, &addr_raw);
606
607
                /* shared memory pid or address? */
608
0
                if (memcmp(&addr_raw.bytes, prefix, strlen(prefix)) == 0) {
609
0
                    temporary_hf = hf_rtpsvt_source_pid;
610
0
                    title_tree = "Source process ID";
611
0
                    uint32_t pid = tvb_get_uint32(
612
0
                            tvb,
613
0
                            OFFSET_TO_VAL + (int) (strlen(prefix)),
614
0
                            ENC_BIG_ENDIAN);
615
0
                    snprintf(addr, sizeof(addr), "%u", pid);
616
0
                } else if (memcmp(
617
0
                        &addr_raw.bytes,
618
0
                        bytes_zeroed,
619
0
                        sizeof(bytes_zeroed)) == 0){
620
0
                    snprintf(
621
0
                            addr,
622
0
                            sizeof(addr),
623
0
                            "%s",
624
0
                            tvb_ip_to_str(pinfo->pool, tvb, OFFSET_TO_VAL + sizeof(bytes_zeroed)));
625
0
                } else {
626
0
                    snprintf(
627
0
                            addr,
628
0
                            sizeof(addr),
629
0
                            "%s",
630
0
                            tvb_ip6_to_str(pinfo->pool, tvb, OFFSET_TO_VAL));
631
0
                }
632
633
                /* Add source to destination column field */
634
0
                if (pinfo->cinfo) {
635
0
                    col_append_str(pinfo->cinfo, COL_DEF_SRC, addr);
636
0
                }
637
638
0
                rtpsvt_tree_information_address = proto_tree_add_subtree_format(
639
0
                        rtpsvt_tree_information,
640
0
                        tvb,
641
0
                        offset,
642
0
                        0,
643
0
                        ett_rtpsvt_information_src_addr,
644
0
                        NULL,
645
0
                        "%s: %s",
646
0
                        title_tree,
647
0
                        addr);
648
649
                /* Add parameter identifier and length */
650
0
                proto_tree_add_uint(
651
0
                        rtpsvt_tree_information_address,
652
0
                        hf_rtpsvt_param_id,
653
0
                        tvb,
654
0
                        offset,
655
0
                        2, /* length: sizeof(uint16_t) */
656
0
                        param_id);
657
0
                offset += 2;
658
0
                proto_tree_add_uint(
659
0
                        rtpsvt_tree_information_address,
660
0
                        hf_rtpsvt_param_length,
661
0
                        tvb,
662
0
                        offset,
663
0
                        2, /* length: sizeof(uint16_t) */
664
0
                        param_length);
665
0
                offset += 2;
666
667
                /* Add source to the transport information tree */
668
0
                proto_tree_add_string(
669
0
                        rtpsvt_tree_information_address,
670
0
                        temporary_hf,
671
0
                        tvb,
672
0
                        offset,
673
0
                        param_length,
674
0
                        addr);
675
0
                offset += param_length;
676
677
                /* Add summary to protocol header */
678
0
                proto_item_append_text(rtpsvt_tree_general, ", Src: (%s", addr);
679
680
                /* Add summary to transport information header */
681
0
                proto_item_append_text(
682
0
                        rtpsvt_tree_information,
683
0
                        ", Src: (%s",
684
0
                        addr);
685
0
            }
686
0
            break;
687
0
        case PARAM_ID_SOURCE_PORT:
688
0
            {
689
0
                proto_tree *rtpsvt_tree_information_port;
690
0
                uint32_t port = tvb_get_uint32(
691
0
                        tvb,
692
0
                        OFFSET_TO_VAL,
693
0
                        ENC_BIG_ENDIAN);
694
695
0
                rtpsvt_tree_information_port = proto_tree_add_subtree_format(
696
0
                        rtpsvt_tree_information,
697
0
                        tvb,
698
0
                        offset,
699
0
                        0,
700
0
                        ett_rtpsvt_information_src_port,
701
0
                        NULL,
702
0
                        "Source port: %d",
703
0
                        port);
704
705
                /* Add parameter identifier and length */
706
0
                proto_tree_add_uint(
707
0
                        rtpsvt_tree_information_port,
708
0
                        hf_rtpsvt_param_id,
709
0
                        tvb,
710
0
                        offset,
711
0
                        2, /* length: sizeof(uint16_t) */
712
0
                        param_id);
713
0
                offset += 2;
714
0
                proto_tree_add_uint(
715
0
                        rtpsvt_tree_information_port,
716
0
                        hf_rtpsvt_param_length,
717
0
                        tvb,
718
0
                        offset,
719
0
                        2, /* length: sizeof(uint16_t) */
720
0
                        param_length);
721
0
                offset += 2;
722
723
0
                proto_tree_add_uint(
724
0
                        rtpsvt_tree_information_port,
725
0
                        hf_rtpsvt_source_port,
726
0
                        tvb,
727
0
                        offset,
728
0
                        param_length,
729
0
                        port);
730
0
                offset += param_length;
731
732
                /* Add summary to protocol header */
733
0
                proto_item_append_text(rtpsvt_tree_general, ":%d)", port);
734
735
                /* Add summary to transport information header */
736
0
                proto_item_append_text(
737
0
                        rtpsvt_tree_information,
738
0
                        ":%d)",
739
0
                        port);
740
741
                /*
742
                 * Add the source port to pinfo.
743
                 * This is used by the RTPS dissector to get the domainId and
744
                 * participantIdx information displayed in discovery packets.
745
                 */
746
0
                pinfo->srcport = port;
747
0
            }
748
0
            break;
749
0
        case PARAM_ID_DESTINATION_IP_ADDRESS:
750
0
            {
751
0
                proto_tree *rtpsvt_tree_information_address;
752
0
                int temporary_hf= hf_rtpsvt_destination_address;
753
0
                const char *prefix = "shmem_prefix";
754
0
                const char *title_tree = "Destination address";
755
0
                char addr[COL_MAX_LEN];
756
0
                ws_in6_addr addr_raw;
757
0
                static const uint8_t bytes_zeroed[12] = {0};
758
0
                tvb_get_ipv6(tvb, OFFSET_TO_VAL, &addr_raw);
759
760
                /* shared memory pid or address? */
761
0
                if (memcmp(&addr_raw.bytes, prefix, strlen(prefix)) == 0) {
762
0
                    temporary_hf = hf_rtpsvt_destination_pid;
763
0
                    title_tree = "Destination process ID";
764
0
                    uint32_t pid = tvb_get_uint32(
765
0
                            tvb,
766
0
                            OFFSET_TO_VAL + (int) (strlen(prefix)),
767
0
                            ENC_BIG_ENDIAN);
768
0
                    snprintf(addr, sizeof(addr), "%u", pid);
769
0
                } else if (memcmp(
770
0
                        &addr_raw.bytes,
771
0
                        bytes_zeroed,
772
0
                        sizeof(bytes_zeroed)) == 0){
773
0
                    snprintf(
774
0
                            addr,
775
0
                            sizeof(addr),
776
0
                            "%s",
777
0
                            tvb_ip_to_str(pinfo->pool, tvb, OFFSET_TO_VAL + sizeof(bytes_zeroed)));
778
0
                } else {
779
0
                    snprintf(
780
0
                            addr,
781
0
                            sizeof(addr),
782
0
                            "%s",
783
0
                            tvb_ip6_to_str(pinfo->pool, tvb, OFFSET_TO_VAL));
784
0
                }
785
786
                /* Add address to destination column field */
787
0
                if (pinfo->cinfo) {
788
0
                    col_append_str(pinfo->cinfo, COL_DEF_DST, addr);
789
0
                }
790
791
0
                rtpsvt_tree_information_address = proto_tree_add_subtree_format(
792
0
                        rtpsvt_tree_information,
793
0
                        tvb,
794
0
                        offset,
795
0
                        0,
796
0
                        ett_rtpsvt_information_dst_addr,
797
0
                        NULL,
798
0
                        "%s: %s",
799
0
                        title_tree,
800
0
                        addr);
801
802
                /* Add parameter identifier and length */
803
0
                proto_tree_add_uint(
804
0
                        rtpsvt_tree_information_address,
805
0
                        hf_rtpsvt_param_id,
806
0
                        tvb,
807
0
                        offset,
808
0
                        2, /* length: sizeof(uint16_t) */
809
0
                        param_id);
810
0
                offset += 2;
811
0
                proto_tree_add_uint(
812
0
                        rtpsvt_tree_information_address,
813
0
                        hf_rtpsvt_param_length,
814
0
                        tvb,
815
0
                        offset,
816
0
                        2, /* length: sizeof(uint16_t) */
817
0
                        param_length);
818
0
                offset += 2;
819
820
                /* Add destination to the transport information tree */
821
0
                proto_tree_add_string(
822
0
                        rtpsvt_tree_information_address,
823
0
                        temporary_hf,
824
0
                        tvb,
825
0
                        offset,
826
0
                        param_length,
827
0
                        addr);
828
0
                offset += param_length;
829
830
                /* Add summary to protocol header */
831
0
                proto_item_append_text(rtpsvt_tree_general, ", Dst: (%s", addr);
832
833
                /* Add summary to transport information header */
834
0
                proto_item_append_text(
835
0
                        rtpsvt_tree_information,
836
0
                        ", Dst: (%s",
837
0
                        addr);
838
0
            }
839
0
            break;
840
0
        case PARAM_ID_DESTINATION_RTPS_PORT:
841
0
            {
842
0
                uint32_t port = tvb_get_uint32(tvb, OFFSET_TO_VAL, ENC_BIG_ENDIAN);
843
844
0
                proto_tree_add_uint(
845
0
                        rtpsvt_tree_information,
846
0
                        hf_rtpsvt_destination_rtps_port,
847
0
                        tvb,
848
0
                        OFFSET_TO_VAL,
849
0
                        param_length,
850
0
                        port);
851
852
0
                offset = OFFSET_TO_VAL + param_length;
853
0
            }
854
0
            break;
855
0
        case PARAM_ID_DESTINATION_PORT:
856
0
            {
857
0
                proto_tree *rtpsvt_tree_information_port;
858
0
                uint32_t port = tvb_get_uint32(tvb, OFFSET_TO_VAL, ENC_BIG_ENDIAN);
859
860
0
                rtpsvt_tree_information_port = proto_tree_add_subtree_format(
861
0
                        rtpsvt_tree_information,
862
0
                        tvb,
863
0
                        offset,
864
0
                        0,
865
0
                        ett_rtpsvt_information_dst_port,
866
0
                        NULL,
867
0
                        "Destination port: %d",
868
0
                        port);
869
870
                /* Add parameter identifier and length */
871
0
                proto_tree_add_uint(
872
0
                        rtpsvt_tree_information_port,
873
0
                        hf_rtpsvt_param_id,
874
0
                        tvb,
875
0
                        offset,
876
0
                        2, /* length: sizeof(uint16_t) */
877
0
                        param_id);
878
0
                offset += 2;
879
0
                proto_tree_add_uint(
880
0
                        rtpsvt_tree_information_port,
881
0
                        hf_rtpsvt_param_length,
882
0
                        tvb,
883
0
                        offset,
884
0
                        2, /* length: sizeof(uint16_t) */
885
0
                        param_length);
886
0
                offset += 2;
887
888
0
                proto_tree_add_uint(
889
0
                        rtpsvt_tree_information_port,
890
0
                        hf_rtpsvt_destination_port,
891
0
                        tvb,
892
0
                        offset,
893
0
                        param_length,
894
0
                        port);
895
0
                offset += param_length;
896
897
                /* Add summary to protocol header */
898
0
                proto_item_append_text(rtpsvt_tree_general, ":%d)", port);
899
900
                /* Add summary to transport information header */
901
0
                proto_item_append_text(
902
0
                        rtpsvt_tree_information,
903
0
                        ":%d)",
904
0
                        port);
905
906
                /*
907
                 * Add the destination port to pinfo.
908
                 * This is used by the RTPS dissector to get the domainId and
909
                 * participantIdx information displayed in discovery packets.
910
                 */
911
0
                pinfo->destport = port;
912
0
            }
913
0
            break;
914
0
        case PARAM_ID_DIRECTION:
915
0
            {
916
0
                proto_tree *rtpsvt_tree_direction;
917
0
                uint8_t value = tvb_get_uint8(tvb, OFFSET_TO_VAL);
918
0
                const char *direction = value ? "INBOUND" : "OUTBOUND";
919
920
0
                rtpsvt_tree_direction = proto_tree_add_subtree_format(
921
0
                        rtpsvt_tree_general,
922
0
                        tvb,
923
0
                        offset,
924
0
                        0,
925
0
                        ett_rtpsvt_information_src_addr,
926
0
                        NULL,
927
0
                        "Traffic Direction: %s",
928
0
                        direction);
929
930
                /* Add parameter identifier and length */
931
0
                proto_tree_add_uint(
932
0
                        rtpsvt_tree_direction,
933
0
                        hf_rtpsvt_param_id,
934
0
                        tvb,
935
0
                        offset,
936
0
                        2, /* length: sizeof(uint16_t) */
937
0
                        param_id);
938
0
                offset += 2;
939
0
                proto_tree_add_uint(
940
0
                        rtpsvt_tree_direction,
941
0
                        hf_rtpsvt_param_length,
942
0
                        tvb,
943
0
                        offset,
944
0
                        2, /* length: sizeof(uint16_t) */
945
0
                        param_length);
946
947
0
                proto_tree_add_string(
948
0
                        rtpsvt_tree_direction,
949
0
                        hf_rtpsvt_direction,
950
0
                        tvb,
951
0
                        OFFSET_TO_VAL,
952
0
                        param_length,
953
0
                        direction);
954
0
                offset = OFFSET_TO_VAL + param_length;
955
956
                /* Save transport direction for the RTPS-PROC protocol */
957
0
                transport_data->direction = value;
958
0
            }
959
0
            break;
960
0
    }
961
0
    return offset;
962
0
}
963
964
static int dissect_rtps_virtual_transport_loss_info_type(
965
        tvbuff_t *tvb,
966
        packet_info *pinfo,
967
        proto_tree *tree_transport,
968
        int offset)
969
0
{
970
971
0
    uint16_t param_id;
972
973
0
    param_id = tvb_get_uint16(tvb, offset, ENC_BIG_ENDIAN);
974
0
    offset += 2;
975
0
    offset += 2; /* parameter length */
976
0
    if (param_id == PARAM_ID_LOST_MESSAGES) {
977
0
        uint64_t first_lost = tvb_get_uint64(tvb, offset, ENC_BIG_ENDIAN);
978
0
        uint64_t last_lost = tvb_get_uint64(tvb, offset+8, ENC_BIG_ENDIAN);
979
980
0
        if (pinfo->cinfo) {
981
0
            char info[COL_MAX_INFO_LEN] = {'\0'};
982
0
            snprintf(
983
0
                    info,
984
0
                    sizeof(info),
985
0
                    "Missing RTPS messages [%" PRIu64 "-%" PRIu64 "]",
986
0
                    first_lost,
987
0
                    last_lost);
988
0
            col_append_str(pinfo->cinfo, COL_INFO, info);
989
0
        }
990
0
        expert_add_info(NULL, tree_transport, &ei_missing_msg);
991
0
    }
992
993
0
    return tvb_captured_length(tvb);
994
0
}
995
996
/* Register the protocol with Wireshark */
997
void
998
proto_register_rtps_virtual_transport(void)
999
16
{
1000
16
    expert_module_t* expert_info;
1001
1002
16
    static hf_register_info hf[] = {
1003
16
        {
1004
16
            &hf_rtpsvt_version,
1005
16
            {
1006
16
                "Version", "rtpsvt.version",
1007
16
                FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL
1008
16
            }
1009
16
        },
1010
16
        {
1011
16
            &hf_rtpsvt_version_major,
1012
16
            {
1013
16
                "Major", "rtpsvt.version.major",
1014
16
                FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL
1015
16
            }
1016
16
        },
1017
16
        {
1018
16
            &hf_rtpsvt_version_minor,
1019
16
            {
1020
16
                "Minor", "rtpsvt.version.minor",
1021
16
                FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL
1022
16
            }
1023
16
        },
1024
16
        {
1025
16
            &hf_rtpsvt_content_kind,
1026
16
            {
1027
16
                "Content kind", "rtpsvt.content.kind",
1028
16
                FT_INT8, BASE_DEC, NULL, 0, NULL, HFILL
1029
16
            }
1030
16
        },
1031
16
        {
1032
16
            &hf_rtpsvt_param_id,
1033
16
            {
1034
16
                "Parameter Identifier", "rtpsvt.param.id",
1035
16
                FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL
1036
16
            },
1037
16
        },
1038
16
        {
1039
16
            &hf_rtpsvt_param_length,
1040
16
            {
1041
16
                "Parameter Length", "rtpsvt.param.length",
1042
16
                FT_UINT16, BASE_DEC, NULL, 0, NULL, HFILL
1043
16
            }
1044
16
        },
1045
16
        {
1046
16
            &hf_rtpsvt_direction,
1047
16
            {
1048
16
                "Traffic Direction", "rtpsvt.direction",
1049
16
                FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL
1050
16
            }
1051
16
        },
1052
16
        {
1053
16
            &hf_rtpsvt_packet_identifier,
1054
16
            {
1055
16
                "Packet identifier", "rtpsvt.identifier",
1056
16
                FT_NONE, BASE_NONE, NULL, 0, NULL, HFILL
1057
16
            }
1058
16
        },
1059
16
        {
1060
16
            &hf_rtpsvt_monitoring_guid,
1061
16
            {
1062
16
                "GUID", "rtpsvt.monitoring_guid",
1063
16
                FT_BYTES, BASE_NONE, NULL, 0, NULL, HFILL
1064
16
            }
1065
16
        },
1066
16
        {
1067
16
            &hf_rtpsvt_monitoring_seqNr,
1068
16
            {
1069
16
                "SeqNum", "rtpsvt.seqNr",
1070
16
                FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL
1071
16
            }
1072
16
        },
1073
16
        {
1074
16
            &hf_rtpsvt_information,
1075
16
            {
1076
16
                "Transport Information", "rtpsvt.information",
1077
16
                FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL
1078
16
            }
1079
16
        },
1080
16
        {
1081
16
            &hf_rtpsvt_source_port,
1082
16
            {
1083
16
                "Source Port", "rtpsvt.source_port",
1084
16
                FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL
1085
16
            }
1086
16
        },
1087
16
        {
1088
16
            &hf_rtpsvt_source_address,
1089
16
            {
1090
16
                "Source address", "rtpsvt.source_address",
1091
16
                FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL
1092
16
            }
1093
16
        },
1094
16
        {
1095
16
            &hf_rtpsvt_source_pid,
1096
16
            {
1097
16
                "Source process ID", "rtpsvt.source_pid",
1098
16
                FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL
1099
16
            }
1100
16
        },
1101
16
        {
1102
16
            &hf_rtpsvt_destination_port,
1103
16
            {
1104
16
                "Destination Port", "rtpsvt.port",
1105
16
                FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL
1106
16
            }
1107
16
        },
1108
16
        {
1109
16
            &hf_rtpsvt_destination_rtps_port,
1110
16
            {
1111
16
                "Destination RTPS Port", "rtpsvt.rtps_port",
1112
16
                FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL
1113
16
            }
1114
16
        },
1115
16
        {
1116
16
            &hf_rtpsvt_destination_address,
1117
16
            {
1118
16
                "Destination address", "rtpsvt.destination_address",
1119
16
                FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL
1120
16
            }
1121
16
        },
1122
16
        {
1123
16
            &hf_rtpsvt_destination_pid,
1124
16
            {
1125
16
                "Destination process ID", "rtpsvt.destination_pid",
1126
16
                FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL
1127
16
            }
1128
16
        },
1129
16
        {
1130
16
            &hf_rtpsvt_class,
1131
16
            {
1132
16
                "Transport class", "rtpsvt.class",
1133
16
                FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL
1134
16
            }
1135
16
        },
1136
16
        {
1137
            /* Information related to the 'lost' content type */
1138
16
            &hf_rtpsvt_missing_messages,
1139
16
            {
1140
16
                "Packets lost", "rtpsvt.missing_messages",
1141
16
                FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL
1142
16
            }
1143
16
        }
1144
16
    };
1145
1146
16
    static int *ett[] = {
1147
16
        &ett_rtpsvt,
1148
16
        &ett_rtpsvt_version,
1149
16
        &ett_rtpsvt_identifier,
1150
16
        &ett_rtpsvt_information,
1151
16
        &ett_rtpsvt_information_class,
1152
16
        &ett_rtpsvt_information_src_port,
1153
16
        &ett_rtpsvt_information_dst_port,
1154
16
        &ett_rtpsvt_information_src_addr,
1155
16
        &ett_rtpsvt_information_dst_addr,
1156
16
        &ett_rtpsvt_information_direction,
1157
16
        &ett_rtpsvt_monitoring_sn,
1158
16
        &ett_rtpsvt_frame
1159
16
    };
1160
1161
16
    static ei_register_info ei[] = {
1162
16
        {
1163
16
        &ei_missing_msg,
1164
16
        {
1165
16
            "rtpsvt.expert.missing_messages",
1166
16
            PI_PROTOCOL,
1167
16
            PI_NOTE,
1168
16
            "Missing RTPS Messages because of full buffer pool",
1169
16
            EXPFILL
1170
16
        }
1171
16
    },
1172
16
    };
1173
1174
    /* Register the protocol name and description */
1175
16
    proto_rtpsvt = proto_register_protocol("Real-Time Publish-Subscribe Virtual Transport", "RTPS-VT", "rtpsvt");
1176
1177
    /* Required function calls to register the header fields and subtrees */
1178
16
    rtpsvt_hf = proto_registrar_get_nth(proto_rtpsvt);
1179
16
    proto_register_field_array(proto_rtpsvt, hf, array_length(hf));
1180
16
    proto_register_subtree_array(ett, array_length(ett));
1181
1182
    /* Register expert information */
1183
16
    expert_info = expert_register_protocol(proto_rtpsvt);
1184
16
    expert_register_field_array(expert_info, ei, array_length(ei));
1185
1186
16
    register_dissector("rtpsvt", dissect_rtps_virtual_transport, proto_rtpsvt);
1187
16
}
1188
1189
/*
1190
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1191
 *
1192
 * Local variables:
1193
 * c-basic-offset: 4
1194
 * tab-width: 8
1195
 * indent-tabs-mode: nil
1196
 * End:
1197
 *
1198
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1199
 * :indentSize=4:tabSize=8:noTabs=true:
1200
 */