Coverage Report

Created: 2025-12-27 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-uaudp.c
Line
Count
Source
1
/* packet-uaudp.c
2
 * Routines for UA/UDP (Universal Alcatel over UDP) packet dissection.
3
 * Copyright 2012, Alcatel-Lucent Enterprise <lars.ruoff@alcatel-lucent.com>
4
 * Copyright 2018, Alcatel-Lucent Enterprise <nicolas.bertin@al-enterprise.com>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
13
#include "config.h"
14
15
#include <epan/packet.h>
16
#include <epan/prefs.h>
17
#include <epan/expert.h>
18
#include <wsutil/report_message.h>
19
#include <wsutil/inet_addr.h>
20
21
#include "packet-uaudp.h"
22
23
void proto_register_uaudp(void);
24
void proto_reg_handoff_uaudp(void);
25
26
/* GLOBALS */
27
28
static dissector_handle_t uaudp_handle;
29
30
static int proto_uaudp;
31
32
static int hf_uaudp_opcode;
33
static int hf_uaudp_version;
34
static int hf_uaudp_window_size;
35
static int hf_uaudp_mtu;
36
static int hf_uaudp_udp_lost;
37
static int hf_uaudp_udp_lost_reinit;
38
static int hf_uaudp_keepalive;
39
static int hf_uaudp_qos_ip_tos;
40
static int hf_uaudp_qos_8021_vlid;
41
static int hf_uaudp_qos_8021_pri;
42
static int hf_uaudp_superfast_connect;
43
static int hf_uaudp_expseq;
44
static int hf_uaudp_sntseq;
45
static int hf_uaudp_type;
46
static int hf_uaudp_length;
47
static int hf_uaudp_startsig_reserved;
48
static int hf_uaudp_startsig_filename;
49
50
static int ett_uaudp;
51
static int ett_uaudp_tlv;
52
53
static expert_field ei_uaudp_tlv_length;
54
55
/* pref */
56
14
#define UAUDP_PORT_RANGE "32000,32512" /* Not IANA registered */
57
static range_t *ua_udp_range;
58
static address cs_address = ADDRESS_INIT_NONE;
59
static ws_in4_addr cs_ipv4;
60
static ws_in6_addr cs_ipv6;
61
static const char* pref_sys_ip_s = "";
62
63
static bool use_sys_ip;
64
65
static const value_string uaudp_opcode_str[] =
66
{
67
    { UAUDP_CONNECT,        "Connect" },
68
    { UAUDP_CONNECT_ACK,    "Connect ACK" },
69
    { UAUDP_RELEASE,        "Release" },
70
    { UAUDP_RELEASE_ACK,    "Release ACK" },
71
    { UAUDP_KEEPALIVE,      "Keepalive" },
72
    { UAUDP_KEEPALIVE_ACK,  "Keepalive ACK" },
73
    { UAUDP_NACK,           "NACK" },
74
    { UAUDP_DATA,           "Data" },
75
    { UAUDP_START_SIG,      "StartSig" },
76
    { UAUDP_START_SIG_ACK,  "StartSig ACK" },
77
    { 0, NULL }
78
};
79
value_string_ext uaudp_opcode_str_ext = VALUE_STRING_EXT_INIT(uaudp_opcode_str);
80
81
static const value_string uaudp_connect_vals[] =
82
{
83
    { UAUDP_CONNECT_VERSION,        "Version" },
84
    { UAUDP_CONNECT_WINDOW_SIZE,    "Window Size" },
85
    { UAUDP_CONNECT_MTU,            "MTU" },
86
    { UAUDP_CONNECT_UDP_LOST,       "UDP lost" },
87
    { UAUDP_CONNECT_UDP_LOST_REINIT,"UDP lost reinit" },
88
    { UAUDP_CONNECT_KEEPALIVE,      "Keepalive" },
89
    { UAUDP_CONNECT_QOS_IP_TOS,     "QoS IP TOS" },
90
    { UAUDP_CONNECT_QOS_8021_VLID,  "QoS 802.1 VLID" },
91
    { UAUDP_CONNECT_QOS_8021_PRI,   "QoS 802.1 PRI"},
92
    { UAUDP_CONNECT_SUPERFAST_CONNECT, "SuperFast Connect"},
93
    { 0, NULL }
94
};
95
value_string_ext uaudp_connect_vals_ext = VALUE_STRING_EXT_INIT(uaudp_connect_vals);
96
97
static dissector_handle_t ua_sys_to_term_handle;
98
static dissector_handle_t ua_term_to_sys_handle;
99
100
/* UA/UDP DISSECTOR */
101
static void _dissect_uaudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
102
                           e_ua_direction direction)
103
621
{
104
621
    int         offset = 0;
105
621
    uint32_t    type, length;
106
621
    uint8_t     opcode;
107
621
    proto_item *uaudp_item, *tlv_item, *tlv_len_item;
108
621
    proto_tree *uaudp_tree, *connect_tree;
109
110
621
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "UAUDP");
111
112
    /* get the identifier; it means operation code */
113
621
    opcode = tvb_get_uint8(tvb, offset);
114
621
    offset += 1;
115
116
    /* print in "INFO" column the type of UAUDP message */
117
621
    col_add_str(pinfo->cinfo,
118
621
                COL_INFO,
119
621
                val_to_str_ext(pinfo->pool, opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));
120
121
621
    uaudp_item = proto_tree_add_protocol_format(tree, proto_uaudp, tvb, 0, tvb_reported_length(tvb),
122
621
                            "Universal Alcatel/UDP Encapsulation Protocol, %s",
123
621
                            val_to_str_ext(pinfo->pool, opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));
124
125
621
    uaudp_tree = proto_item_add_subtree(uaudp_item, ett_uaudp);
126
127
    /* print the identifier */
128
621
    proto_tree_add_uint(uaudp_tree, hf_uaudp_opcode, tvb, 0, 1, opcode);
129
130
621
    switch(opcode)
131
621
    {
132
61
    case UAUDP_CONNECT:
133
61
    {
134
1.27k
        while(tvb_reported_length_remaining(tvb, offset) > 0)
135
1.21k
        {
136
1.21k
            type = tvb_get_uint8(tvb, offset+0);
137
1.21k
            connect_tree = proto_tree_add_subtree(uaudp_tree, tvb, offset, 0, ett_uaudp_tlv, &tlv_item,
138
1.21k
                                                    val_to_str_ext(pinfo->pool, type, &uaudp_connect_vals_ext, "Unknown %d"));
139
1.21k
            proto_tree_add_uint(connect_tree, hf_uaudp_type, tvb, offset, 1, type);
140
1.21k
            offset++;
141
1.21k
            tlv_len_item = proto_tree_add_item_ret_uint(connect_tree, hf_uaudp_length, tvb, offset, 1, ENC_NA, &length);
142
1.21k
            proto_item_set_len(tlv_item, length+2);
143
1.21k
            offset++;
144
145
1.21k
            if ((length >= 1) && (length <= 4))
146
322
            {
147
322
                switch(type)
148
322
                {
149
25
                    case UAUDP_CONNECT_VERSION:
150
25
                        proto_tree_add_item(connect_tree, hf_uaudp_version, tvb, offset, length, ENC_BIG_ENDIAN);
151
25
                        break;
152
97
                    case UAUDP_CONNECT_WINDOW_SIZE:
153
97
                        proto_tree_add_item(connect_tree, hf_uaudp_window_size, tvb, offset, length, ENC_BIG_ENDIAN);
154
97
                        break;
155
55
                    case UAUDP_CONNECT_MTU:
156
55
                        proto_tree_add_item(connect_tree, hf_uaudp_mtu, tvb, offset, length, ENC_BIG_ENDIAN);
157
55
                        break;
158
43
                    case UAUDP_CONNECT_UDP_LOST:
159
43
                        proto_tree_add_item(connect_tree, hf_uaudp_udp_lost, tvb, offset, length, ENC_BIG_ENDIAN);
160
43
                        break;
161
42
                    case UAUDP_CONNECT_UDP_LOST_REINIT:
162
42
                        proto_tree_add_item(connect_tree, hf_uaudp_udp_lost_reinit, tvb, offset, length, ENC_BIG_ENDIAN);
163
42
                        break;
164
2
                    case UAUDP_CONNECT_KEEPALIVE:
165
2
                        proto_tree_add_item(connect_tree, hf_uaudp_keepalive, tvb, offset, length, ENC_BIG_ENDIAN);
166
2
                        break;
167
2
                    case UAUDP_CONNECT_QOS_IP_TOS:
168
2
                        proto_tree_add_item(connect_tree, hf_uaudp_qos_ip_tos, tvb, offset, length, ENC_BIG_ENDIAN);
169
2
                        break;
170
5
                    case UAUDP_CONNECT_QOS_8021_VLID:
171
5
                        proto_tree_add_item(connect_tree, hf_uaudp_qos_8021_vlid, tvb, offset, length, ENC_BIG_ENDIAN);
172
5
                        break;
173
19
                    case UAUDP_CONNECT_QOS_8021_PRI:
174
19
                        proto_tree_add_item(connect_tree, hf_uaudp_qos_8021_pri, tvb, offset, length, ENC_BIG_ENDIAN);
175
19
                        break;
176
1
                    case UAUDP_CONNECT_SUPERFAST_CONNECT:
177
1
                        proto_tree_add_item(connect_tree, hf_uaudp_superfast_connect, tvb, offset, length, ENC_BIG_ENDIAN);
178
1
                        break;
179
322
                }
180
322
            }
181
893
            else
182
893
            {
183
893
                expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
184
893
            }
185
1.21k
            offset += length;
186
1.21k
        }
187
56
        break;
188
61
    }
189
190
56
    case UAUDP_NACK:
191
1
    {
192
1
        proto_tree_add_item(uaudp_tree,
193
1
                    hf_uaudp_expseq,
194
1
                    tvb,
195
1
                    offset,
196
1
                    2,
197
1
                    ENC_BIG_ENDIAN);
198
1
        break;
199
61
    }
200
201
552
    case UAUDP_DATA:
202
552
    {
203
552
        int datalen;
204
205
552
        proto_tree_add_item(uaudp_tree,
206
552
                    hf_uaudp_expseq,
207
552
                    tvb,
208
552
                    offset+0,
209
552
                    2,
210
552
                    ENC_BIG_ENDIAN);
211
212
552
        proto_tree_add_item(uaudp_tree,
213
552
                    hf_uaudp_sntseq,
214
552
                    tvb,
215
552
                    offset+2,
216
552
                    2,
217
552
                    ENC_BIG_ENDIAN);
218
219
552
        offset  += 4;
220
552
        datalen  = tvb_reported_length(tvb) - offset;
221
222
        /* if there is remaining data, call the UA dissector */
223
552
        if (datalen > 0)
224
551
        {
225
551
            if (direction == SYS_TO_TERM)
226
441
                call_dissector(ua_sys_to_term_handle,
227
441
                           tvb_new_subset_length(tvb, offset, datalen),
228
441
                           pinfo,
229
441
                           tree);
230
110
            else if (direction == TERM_TO_SYS)
231
110
                call_dissector(ua_term_to_sys_handle,
232
110
                           tvb_new_subset_length(tvb, offset, datalen),
233
110
                           pinfo,
234
110
                           tree);
235
0
            else {
236
                /* XXX: expert ?? */
237
0
                col_set_str(pinfo->cinfo,
238
0
                            COL_INFO,
239
0
                            "Data - Couldn't resolve direction. Check UAUDP Preferences.");
240
0
            }
241
551
        }
242
1
        else {
243
            /* print in "INFO" column */
244
1
            col_set_str(pinfo->cinfo,
245
1
                        COL_INFO,
246
1
                        "Data ACK");
247
1
        }
248
552
        break;
249
61
    }
250
251
1
    case UAUDP_START_SIG:
252
1
    {
253
1
        proto_tree_add_item(uaudp_tree, hf_uaudp_startsig_reserved, tvb, offset, 6, ENC_NA);
254
1
        offset += 6;
255
1
        proto_tree_add_item(uaudp_tree, hf_uaudp_startsig_filename, tvb, offset, tvb_strsize(tvb, offset)-1, ENC_ASCII);
256
1
        break;
257
61
    }
258
259
6
    default:
260
6
        break;
261
621
    }
262
621
}
263
264
/*
265
 * UA/UDP DISSECTOR
266
 Wireshark packet dissector entry point
267
*/
268
static int dissect_uaudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
269
621
{
270
    /* server address, if present, has precedence on ports */
271
621
    if (use_sys_ip) {
272
        /* use server address to find direction*/
273
0
        if (addresses_equal((address *)&pinfo->src, (address *)&cs_address))
274
0
        {
275
0
            _dissect_uaudp(tvb, pinfo, tree, SYS_TO_TERM);
276
0
            return tvb_captured_length(tvb);
277
0
        }
278
0
        else if (addresses_equal((address *)&pinfo->dst, (address *)&cs_address))
279
0
        {
280
0
            _dissect_uaudp(tvb, pinfo, tree, TERM_TO_SYS);
281
0
            return tvb_captured_length(tvb);
282
0
        }
283
0
    }
284
285
    /* use ports to find direction */
286
621
    if (value_is_in_range(ua_udp_range, pinfo->srcport))
287
138
    {
288
138
        _dissect_uaudp(tvb, pinfo, tree, TERM_TO_SYS);
289
138
        return tvb_captured_length(tvb);
290
138
    }
291
483
    else if (value_is_in_range(ua_udp_range, pinfo->destport))
292
483
    {
293
483
        _dissect_uaudp(tvb, pinfo, tree, SYS_TO_TERM);
294
483
        return tvb_captured_length(tvb);
295
483
    }
296
297
0
    _dissect_uaudp(tvb, pinfo, tree, DIR_UNKNOWN);
298
0
    return tvb_captured_length(tvb);
299
621
}
300
301
static void
302
14
apply_uaudp_prefs(void) {
303
14
    ua_udp_range = prefs_get_range_value("uaudp", "udp.port");
304
305
14
    use_sys_ip = false;
306
14
    if (*pref_sys_ip_s) {
307
0
        use_sys_ip = ws_inet_pton4(pref_sys_ip_s, &cs_ipv4);
308
0
        if (use_sys_ip) {
309
0
            set_address((address *)&cs_address, AT_IPv4, sizeof(ws_in4_addr), &cs_ipv4);
310
0
            return;
311
0
        }
312
0
        use_sys_ip = ws_inet_pton6(pref_sys_ip_s, &cs_ipv6);
313
0
        if (use_sys_ip) {
314
0
            set_address((address *)&cs_address, AT_IPv6, sizeof(ws_in6_addr), &cs_ipv6);
315
0
            return;
316
0
        }
317
0
        report_failure("Invalid value for pref uaudp.system_ip: %s", pref_sys_ip_s);
318
0
    }
319
14
}
320
321
void proto_register_uaudp(void)
322
14
{
323
14
    module_t *uaudp_module;
324
325
    /* Setup list of header fields. See Section 1.6.1 for details */
326
14
    static hf_register_info hf_uaudp[] = {
327
14
        {
328
14
            &hf_uaudp_opcode,
329
14
            {
330
14
                "Opcode",
331
14
                "uaudp.opcode",
332
14
                FT_UINT8,
333
14
                BASE_DEC | BASE_EXT_STRING,
334
14
                &uaudp_opcode_str_ext,
335
14
                0x0,
336
14
                "UA/UDP Opcode",
337
14
                HFILL
338
14
            }
339
14
        },
340
14
        {
341
14
            &hf_uaudp_version,
342
14
            {
343
14
                "Version",
344
14
                "uaudp.version",
345
14
                FT_UINT8,
346
14
                BASE_DEC,
347
14
                NULL, 0x0,
348
14
                "UA/UDP Version",
349
14
                HFILL
350
14
            }
351
14
        },
352
14
        {
353
14
            &hf_uaudp_window_size,
354
14
            {
355
14
                "Window Size",
356
14
                "uaudp.window_size",
357
14
                FT_UINT8,
358
14
                BASE_DEC,
359
14
                NULL,
360
14
                0x0,
361
14
                "UA/UDP Window Size",
362
14
                HFILL
363
14
            }
364
14
        },
365
14
        {
366
14
            &hf_uaudp_mtu,
367
14
            {
368
14
                "MTU",
369
14
                "uaudp.mtu",
370
14
                FT_UINT8,
371
14
                BASE_DEC,
372
14
                NULL,
373
14
                0x0,
374
14
                "UA/UDP MTU",
375
14
                HFILL
376
14
            }
377
14
        },
378
14
        {
379
14
            &hf_uaudp_udp_lost,
380
14
            {
381
14
                "UDP Lost",
382
14
                "uaudp.udp_lost",
383
14
                FT_UINT8,
384
14
                BASE_DEC,
385
14
                NULL,
386
14
                0x0,
387
14
                "UA/UDP Lost",
388
14
                HFILL
389
14
            }
390
14
        },
391
14
        {
392
14
            &hf_uaudp_udp_lost_reinit,
393
14
            {
394
14
                "UDP lost reinit",
395
14
                "uaudp.udp_lost_reinit",
396
14
                FT_UINT8,
397
14
                BASE_DEC,
398
14
                NULL, 0x0,
399
14
                "UA/UDP Lost Re-Init",
400
14
                HFILL
401
14
            }
402
14
        },
403
14
        {
404
14
            &hf_uaudp_keepalive,
405
14
            {
406
14
                "Keepalive",
407
14
                "uaudp.keepalive",
408
14
                FT_UINT8,
409
14
                BASE_DEC,
410
14
                NULL,
411
14
                0x0,
412
14
                "UA/UDP Keepalive",
413
14
                HFILL
414
14
            }
415
14
        },
416
14
        {
417
14
            &hf_uaudp_qos_ip_tos,
418
14
            {
419
14
                "QoS IP TOS",
420
14
                "uaudp.qos_ip_tos",
421
14
                FT_UINT8,
422
14
                BASE_DEC,
423
14
                NULL,
424
14
                0x0,
425
14
                "UA/UDP QoS IP TOS",
426
14
                HFILL
427
14
            }
428
14
        },
429
14
        {
430
14
            &hf_uaudp_qos_8021_vlid,
431
14
            {
432
14
                "QoS 802.1 VLID",
433
14
                "uaudp.qos_8021_vlid",
434
14
                FT_UINT8,
435
14
                BASE_DEC,
436
14
                NULL,
437
14
                0x0,
438
14
                "UA/UDP QoS 802.1 VLID",
439
14
                HFILL
440
14
            }
441
14
        },
442
14
        {
443
14
            &hf_uaudp_qos_8021_pri,
444
14
            {
445
14
                "QoS 802.1 PRI",
446
14
                "uaudp.qos_8021_pri",
447
14
                FT_UINT8,
448
14
                BASE_DEC,
449
14
                NULL,
450
14
                0x0,
451
14
                "UA/UDP QoS 802.1 PRI",
452
14
                HFILL
453
14
            }
454
14
        },
455
14
        {
456
14
            &hf_uaudp_superfast_connect,
457
14
            {
458
14
                "SuperFast Connect",
459
14
                "uaudp.superfast_connect",
460
14
                FT_UINT8,
461
14
                BASE_DEC,
462
14
                NULL,
463
14
                0x0,
464
14
                "UA/UDP SuperFast Connect",
465
14
                HFILL
466
14
            }
467
14
        },
468
14
        {
469
14
            &hf_uaudp_expseq,
470
14
            {
471
14
                "Sequence Number (expected)",
472
14
                "uaudp.expseq",
473
14
                FT_UINT16,
474
14
                BASE_DEC,
475
14
                NULL,
476
14
                0x0,
477
14
                "UA/UDP Expected Sequence Number",
478
14
                HFILL
479
14
            }
480
14
        },
481
14
        {
482
14
            &hf_uaudp_sntseq,
483
14
            {
484
14
                "Sequence Number (sent)",
485
14
                "uaudp.sntseq",
486
14
                FT_UINT16,
487
14
                BASE_DEC,
488
14
                NULL,
489
14
                0x0,
490
14
                "UA/UDP Sent Sequence Number",
491
14
                HFILL
492
14
            }
493
14
        },
494
14
        {
495
14
            &hf_uaudp_type,
496
14
            {
497
14
                "Type",
498
14
                "uaudp.type",
499
14
                FT_UINT8,
500
14
                BASE_DEC|BASE_EXT_STRING,
501
14
                &uaudp_connect_vals_ext,
502
14
                0x0,
503
14
                NULL,
504
14
                HFILL
505
14
            }
506
14
        },
507
14
        {
508
14
            &hf_uaudp_length,
509
14
            {
510
14
                "Length",
511
14
                "uaudp.length",
512
14
                FT_UINT8,
513
14
                BASE_DEC,
514
14
                NULL,
515
14
                0x0,
516
14
                NULL,
517
14
                HFILL
518
14
            }
519
14
        },
520
14
        {
521
14
            &hf_uaudp_startsig_reserved,
522
14
            {
523
14
                "Reserved",
524
14
                "uaudp.startsig.reserved",
525
14
                FT_BYTES,
526
14
                BASE_NONE,
527
14
                NULL,
528
14
                0x0,
529
14
                NULL,
530
14
                HFILL
531
14
            }
532
14
        },
533
14
        {
534
14
            &hf_uaudp_startsig_filename,
535
14
            {
536
14
                "Filename",
537
14
                "uaudp.startsig.filename",
538
14
                FT_STRING,
539
14
                BASE_NONE,
540
14
                NULL,
541
14
                0x0,
542
14
                NULL,
543
14
                HFILL
544
14
            }
545
14
        },
546
547
14
    };
548
549
    /* Setup protocol subtree array */
550
14
    static int *ett[] =
551
14
        {
552
14
            &ett_uaudp,
553
14
            &ett_uaudp_tlv,
554
14
        };
555
556
14
    static ei_register_info ei[] = {
557
14
        { &ei_uaudp_tlv_length, { "uaudp.tlv_length_invalid", PI_PROTOCOL, PI_WARN, "Invalid length", EXPFILL }},
558
14
    };
559
14
    expert_module_t* expert_uaudp;
560
561
    /* Register the protocol name and description */
562
14
    proto_uaudp = proto_register_protocol("UA/UDP Encapsulation Protocol", "UAUDP", "uaudp");
563
564
14
    uaudp_handle = register_dissector("uaudp", dissect_uaudp, proto_uaudp);
565
566
14
    proto_register_field_array(proto_uaudp, hf_uaudp, array_length(hf_uaudp));
567
14
    proto_register_subtree_array(ett, array_length(ett));
568
14
    expert_uaudp = expert_register_protocol(proto_uaudp);
569
14
    expert_register_field_array(expert_uaudp, ei, array_length(ei));
570
571
    /* Register preferences */
572
14
    uaudp_module = prefs_register_protocol(proto_uaudp, apply_uaudp_prefs);
573
574
14
    prefs_register_string_preference(uaudp_module, "system_ip",
575
14
                     "Call Server IP Address (optional)",
576
14
                     "IPv4 (or IPv6) address of the call server."
577
14
                     " (Used only in case of identical source and destination ports)",
578
14
                     &pref_sys_ip_s);
579
14
}
580
581
void proto_reg_handoff_uaudp(void)
582
14
{
583
14
    ua_sys_to_term_handle = find_dissector_add_dependency("ua_sys_to_term", proto_uaudp);
584
14
    ua_term_to_sys_handle = find_dissector_add_dependency("ua_term_to_sys", proto_uaudp);
585
586
14
    dissector_add_uint_range_with_preference("udp.port", UAUDP_PORT_RANGE, uaudp_handle);
587
14
    apply_uaudp_prefs();
588
14
}
589
590
/*
591
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
592
 *
593
 * Local variables:
594
 * c-basic-offset: 4
595
 * tab-width: 8
596
 * indent-tabs-mode: nil
597
 * End:
598
 *
599
 * vi: set shiftwidth=4 tabstop=8 expandtab:
600
 * :indentSize=4:tabSize=8:noTabs=true:
601
 */