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-gsm_r_uus1.c
Line
Count
Source
1
/* packet-gsm_r_uus1.c
2
 * Routines for GSM-R UUS1 dissection
3
 *
4
 * Copyright 2018, Michail Koreshkov <michail.koreshkov [at] bk.ru
5
 *
6
 * Reference [1]
7
 * Railways Telecommunications (RT);
8
 * Global System for Mobile communications (GSM);
9
 * Usage of the User-to-User Information Element
10
 * for GSM Operation on Railways
11
 * (ETSI TS 102 610 V1.2.0 (2012-08))
12
 *
13
 * Reference [2]
14
 * EIRENE SRS: "UIC Project EIRENE System Requirements Specification".
15
 *
16
 * Reference [3]
17
 * MORANE F 10 T 6003 4: "FFFS for Presentation of Functional Numbers
18
 * to Called and Calling Parties".
19
 *
20
 * Reference [4]
21
 * eLDA IRS (V5.0): "Interface Requirements Specification
22
 * enhanced Location Dependent Addressing".
23
 *
24
 * SPDX-License-Identifier: GPL-2.0-or-later
25
 */
26
27
#include "config.h"
28
29
#include <epan/packet.h>
30
#include <epan/expert.h>
31
#include <epan/tfs.h>
32
#include <epan/prefs.h>
33
34
/* forward reference */
35
void proto_register_gsm_r_uus1(void);
36
void proto_reg_handoff_gsm_r_uus1(void);
37
38
39
/* Initialize the protocol and registered fields */
40
static int proto_gsm_r_uus1;
41
42
static int hf_gsm_r_uus1_elem_tag;
43
static int hf_gsm_r_uus1_elem_len;
44
static int hf_gsm_r_uus1_pfn;
45
static int hf_gsm_r_uus1_pfn_digits;
46
47
/* 5.2 and 5.3 */
48
static int hf_gsm_r_uus1_chpc;
49
static int hf_gsm_r_uus1_chpc_t_dur;
50
static int hf_gsm_r_uus1_chpc_t_rel;
51
static int hf_gsm_r_uus1_chpc_pl_call;
52
static int hf_gsm_r_uus1_chpc_cause;
53
static int hf_gsm_r_uus1_chpc_cause_power;
54
static int hf_gsm_r_uus1_chpc_cause_radio;
55
static int hf_gsm_r_uus1_chpc_cause_reserved3;
56
static int hf_gsm_r_uus1_chpc_cause_reserved4;
57
static int hf_gsm_r_uus1_chpc_cause_user_command;
58
static int hf_gsm_r_uus1_chpc_cause_reserved6;
59
static int hf_gsm_r_uus1_chpc_cause_reserved7;
60
static int hf_gsm_r_uus1_chpc_cause_reserved8;
61
static int hf_gsm_r_uus1_chpc_gref;
62
static int hf_gsm_r_uus1_chpc_ack_cause;
63
64
/* 5.4 */
65
static int hf_gsm_r_uus1_epfn;
66
67
/* 5.5 */
68
static int hf_gsm_r_uus1_present_text_str;
69
70
/* 5.6 */
71
static int hf_gsm_r_uus1_elda;
72
static int hf_gsm_r_uus1_elda_lat;
73
static int hf_gsm_r_uus1_elda_lat_deg;
74
static int hf_gsm_r_uus1_elda_lat_min;
75
static int hf_gsm_r_uus1_elda_lat_sec;
76
static int hf_gsm_r_uus1_elda_lat_hem;
77
static int hf_gsm_r_uus1_elda_long;
78
static int hf_gsm_r_uus1_elda_long_deg;
79
static int hf_gsm_r_uus1_elda_long_min;
80
static int hf_gsm_r_uus1_elda_long_sec;
81
static int hf_gsm_r_uus1_elda_long_hem;
82
static int hf_gsm_r_uus1_elda_height;
83
static int hf_gsm_r_uus1_elda_speed;
84
static int hf_gsm_r_uus1_elda_heading;
85
static int hf_gsm_r_uus1_elda_e_time;
86
static int hf_gsm_r_uus1_elda_distance;
87
static int hf_gsm_r_uus1_elda_scale;
88
static int hf_gsm_r_uus1_elda_spare;
89
90
/* 5.7 */
91
static int hf_gsm_r_uus1_present_dsd_alarm;
92
static int hf_gsm_r_uus1_present_dsd_alarm_loco_number;
93
94
/* 5.8 */
95
static int hf_gsm_r_uus1_alert_controller;
96
static int hf_gsm_r_uus1_alert_controller_gref;
97
98
/* Initialize the subtree pointers */
99
static int ett_gsm_r_uus1;
100
static int ett_gsm_r_uus1_pfn;
101
static int ett_gsm_r_uus1_chpc;
102
static int ett_gsm_r_uus1_chpc_cause;
103
static int ett_gsm_r_uus1_epfn;
104
static int ett_gsm_r_uus1_present_text_str;
105
static int ett_gsm_r_uus1_elda;
106
static int ett_gsm_r_uus1_elda_lat;
107
static int ett_gsm_r_uus1_elda_long;
108
static int ett_gsm_r_uus1_present_dsd_alarm;
109
static int ett_gsm_r_uus1_alert_controller;
110
111
112
/* Preferences */
113
static bool q931_u2u;
114
static bool gsm_a_u2u = true;
115
116
117
static expert_field ei_gsm_r_uus1_not_implemented_yet;
118
119
static const value_string gsm_r_uus1_tags[] = {
120
    { 2,  "Acknowledgement by Receiver of a HPC and response from device accepting the acknowledgement" },
121
    { 3,  "Acknowledgement by Initiator of a HPC" },
122
    { 5,  "Presentation of Functional Number" },
123
    { 6,  "enhanced Location Dependent Addressing" },
124
    { 7,  "enhanced Location Dependent Addressing (Reserved for future use)" },
125
    { 8,  "enhanced Location Dependent Addressing (Reserved for future use)" },
126
    { 9,  "ePFN Information" },
127
    { 10, "User specific plain text according to alphabet indicator" },
128
    { 11, "DSD Alarm Notification" },
129
    { 12, "Alerting of a Controller Notification and Response" },
130
    { 0, NULL }
131
};
132
133
134
/*
135
 * 5.1 Presentation of functional number
136
 *
137
 */
138
static uint16_t
139
de_gsm_r_uus1_pfn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset)
140
6
{
141
6
    uint32_t  curr_offset;
142
6
    uint32_t  len;
143
6
    const char *fn_str;
144
6
    proto_item *item;
145
6
    proto_tree *sub_tree;
146
147
6
    curr_offset = offset;
148
149
6
    len = tvb_get_uint8(tvb, offset+1);
150
151
6
    item = proto_tree_add_item(tree, hf_gsm_r_uus1_pfn, tvb, curr_offset, len+2, ENC_NA);
152
6
    sub_tree = proto_item_add_subtree(item, ett_gsm_r_uus1_pfn);
153
154
6
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_tag, tvb, curr_offset, 1, ENC_NA);
155
6
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_len, tvb, curr_offset+1, 1, ENC_NA);
156
6
    curr_offset += 2;
157
158
6
    if(len == 0) {
159
3
        proto_item_append_text(item, ": No FN Available");
160
3
    }else {
161
3
        fn_str = tvb_bcd_dig_to_str(pinfo->pool, tvb, offset+2, len, NULL, false);
162
3
        proto_tree_add_string(sub_tree, hf_gsm_r_uus1_pfn_digits, tvb, curr_offset, len, fn_str);
163
3
        proto_item_append_text(item, ": %s", fn_str);
164
165
3
        curr_offset += len;
166
3
    }
167
168
6
    return (curr_offset - offset);
169
6
}
170
171
172
/*
173
 * 5.2 Confirmation of High Priority Calls
174
 *
175
 */
176
static const range_string gsm_r_uus1_chpc_priority_vals[] = {
177
    { 0x00, 0x00, "no priority specified in call"},
178
    { 0x01, 0x01, "eMLPP priority of 4 (Railway Information)"},
179
    { 0x02, 0x02, "eMLPP priority of 3 (Railway Operation)"},
180
    { 0x03, 0x03, "eMLPP priority of 2 (Public Emergency/Group Calls)"},
181
    { 0x04, 0x04, "eMLPP priority of 1 (Command and Control)"},
182
    { 0x05, 0x05, "eMLPP priority of 0 (Railway Emergency)"},
183
    { 0x06, 0x07, "unknown" },
184
    { 0, 0, NULL }
185
};
186
187
static uint16_t
188
de_gsm_r_uus1_chpc_forward(tvbuff_t *tvb, proto_tree *tree, uint32_t offset)
189
1
{
190
1
    uint32_t  curr_offset;
191
1
    uint32_t  len;
192
1
    uint32_t t_dur;
193
1
    uint32_t t_rel;
194
1
    proto_item *item;
195
1
    proto_tree *sub_tree;
196
197
1
    curr_offset = offset;
198
199
1
    len = tvb_get_uint8(tvb, offset+1);
200
201
1
    item = proto_tree_add_item(tree, hf_gsm_r_uus1_chpc, tvb, curr_offset, len+2, ENC_NA);
202
1
    sub_tree = proto_item_add_subtree(item, ett_gsm_r_uus1_chpc);
203
204
1
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_tag, tvb, curr_offset, 1, ENC_NA);
205
1
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_len, tvb, curr_offset+1, 1, ENC_NA);
206
1
    curr_offset += 2;
207
208
1
    t_dur = tvb_get_uint24(tvb, curr_offset, ENC_LITTLE_ENDIAN);
209
1
    proto_tree_add_uint_format_value(sub_tree, hf_gsm_r_uus1_chpc_t_dur, tvb, curr_offset, 3, t_dur, "%d ms", t_dur*100);
210
1
    curr_offset += 3;
211
212
1
    t_rel = tvb_get_uint32(tvb, curr_offset, ENC_LITTLE_ENDIAN);
213
1
    proto_tree_add_uint_format_value(sub_tree, hf_gsm_r_uus1_chpc_t_rel, tvb, curr_offset, 4, t_rel, "%d ms", t_rel*100);
214
1
    curr_offset += 4;
215
216
1
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_chpc_pl_call, tvb, curr_offset, 1, ENC_NA);
217
1
    curr_offset += 1;
218
219
1
    static int * const cause_flags[] = {
220
1
        &hf_gsm_r_uus1_chpc_cause_power,
221
1
        &hf_gsm_r_uus1_chpc_cause_radio,
222
1
        &hf_gsm_r_uus1_chpc_cause_reserved3,
223
1
        &hf_gsm_r_uus1_chpc_cause_reserved4,
224
1
        &hf_gsm_r_uus1_chpc_cause_user_command,
225
1
        &hf_gsm_r_uus1_chpc_cause_reserved6,
226
1
        &hf_gsm_r_uus1_chpc_cause_reserved7,
227
1
        &hf_gsm_r_uus1_chpc_cause_reserved8,
228
1
        NULL
229
1
    };
230
231
1
    proto_tree_add_bitmask(sub_tree, tvb, curr_offset, hf_gsm_r_uus1_chpc_cause, ett_gsm_r_uus1_chpc_cause, cause_flags, ENC_NA);
232
1
    curr_offset += 1;
233
234
1
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_chpc_gref, tvb, curr_offset, 4, ENC_BCD_DIGITS_0_9|ENC_LITTLE_ENDIAN);
235
1
    curr_offset += 4;
236
237
1
    return (curr_offset - offset);
238
1
}
239
240
/*
241
 * 5.3 CHPC tag definition for collecting network device
242
 *
243
 * The tag is included in a RELEASE_COMPLETE message
244
 * which shall have the release cause value of "Normal Call Clearing".
245
 *
246
 * gsm_a.dtap.msg_cc_type == 0x2a
247
 */
248
static const range_string gsm_r_uus1_chpc_ack_cause_vals[] = {
249
    { 0x00, 0x00, "ACK (no error)" },
250
    { 0x01, 0x01, "NACK-1 (error, repetition should take place)" },
251
    { 0x02, 0x7f, "Reserved for internal use" },
252
    { 0x80, 0x80, "NACK-2 (fatal error, NO repetition to take place)" },
253
    { 0x81, 0xff, "Reserved" },
254
    { 0, 0, NULL }
255
};
256
257
static uint16_t
258
de_gsm_r_uus1_chpc_collect(tvbuff_t *tvb, proto_tree *tree, uint32_t offset)
259
27
{
260
27
    proto_item *item;
261
27
    proto_tree *sub_tree;
262
263
27
    item = proto_tree_add_item(tree, hf_gsm_r_uus1_chpc, tvb, offset, 2, ENC_NA);
264
27
    proto_item_set_text(item, "CHPC for collecting network device");
265
27
    sub_tree = proto_item_add_subtree(item, ett_gsm_r_uus1_chpc);
266
267
27
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_tag, tvb, offset, 1, ENC_NA);
268
27
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_chpc_ack_cause, tvb, offset+1, 1, ENC_NA);
269
270
27
    return 2;
271
27
}
272
273
/*
274
 * Type of field depends on BSSAP message type. SETUP or RELEASE_COMPLETE
275
 * But I don't know how to verify message type.
276
 * That is why use length variable to find type of field
277
 */
278
static uint16_t
279
de_gsm_r_uus1_chpc(tvbuff_t *tvb, proto_tree *tree, uint32_t offset)
280
28
{
281
28
    uint8_t field_length;
282
28
    field_length = tvb_get_uint8(tvb, offset+1);
283
28
    if(field_length == 13)
284
1
        return de_gsm_r_uus1_chpc_forward(tvb, tree, offset);
285
27
    else
286
27
        return de_gsm_r_uus1_chpc_collect(tvb, tree, offset);
287
28
}
288
289
/*
290
 * 5.4 Enhanced presentation of functional number
291
 * (not implemented now)
292
 */
293
static uint16_t
294
de_gsm_r_uus1_epfn(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset)
295
3
{
296
3
    uint32_t  curr_offset;
297
3
    uint32_t  len;
298
3
    proto_item *item;
299
3
    proto_tree *sub_tree;
300
301
3
    curr_offset = offset;
302
303
3
    len = tvb_get_uint8(tvb, offset+1);
304
305
3
    item = proto_tree_add_item(tree, hf_gsm_r_uus1_epfn, tvb, curr_offset, len+2, ENC_NA);
306
3
    sub_tree = proto_item_add_subtree(item, ett_gsm_r_uus1_epfn);
307
308
3
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_tag, tvb, curr_offset, 1, ENC_NA);
309
3
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_len, tvb, curr_offset+1, 1, ENC_NA);
310
3
    curr_offset += 2;
311
312
3
    proto_tree_add_expert(sub_tree, pinfo, &ei_gsm_r_uus1_not_implemented_yet, tvb, curr_offset, len);
313
3
    curr_offset += len;
314
315
3
    return (curr_offset - offset);
316
3
}
317
318
/*
319
 * 5.5 Presentation of text strings
320
 * (not implemented now)
321
 */
322
static uint16_t
323
de_gsm_r_uus1_text_str(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset)
324
8
{
325
8
    uint32_t  curr_offset;
326
8
    uint32_t  len;
327
8
    proto_item *item;
328
8
    proto_tree *sub_tree;
329
330
8
    curr_offset = offset;
331
332
8
    len = tvb_get_uint8(tvb, offset+1);
333
334
8
    item = proto_tree_add_item(tree, hf_gsm_r_uus1_present_text_str, tvb, curr_offset, len+2, ENC_NA);
335
8
    sub_tree = proto_item_add_subtree(item, ett_gsm_r_uus1_present_text_str);
336
337
8
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_tag, tvb, curr_offset, 1, ENC_NA);
338
8
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_len, tvb, curr_offset+1, 1, ENC_NA);
339
8
    curr_offset += 2;
340
341
8
    proto_tree_add_expert(sub_tree, pinfo, &ei_gsm_r_uus1_not_implemented_yet, tvb, curr_offset, len);
342
8
    curr_offset += len;
343
344
8
    return (curr_offset - offset);
345
8
}
346
347
/*
348
 * 5.6 Transfer of train position (eLDA)
349
 *
350
 */
351
static const true_false_string gsm_r_uus1_elda_lat_hem = {
352
    "North",
353
    "South"
354
};
355
356
static const true_false_string gsm_r_uus1_elda_long_hem = {
357
    "West",
358
    "East"
359
};
360
361
static const value_string gsm_r_uus1_elda_scale_vals[] = {
362
    { 0,  "10 cm resolution" },
363
    { 1,  "1 metre resolution" },
364
    { 2,  "10 metre resolution" },
365
    { 3,  "Odometry information not valid" },
366
    { 0, NULL }
367
};
368
369
370
static uint16_t
371
de_gsm_r_uus1_elda(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset)
372
4
{
373
4
    uint32_t  curr_offset;
374
4
    unsigned   bit_offset;
375
376
4
    uint32_t lat_deg_val;
377
4
    uint32_t lat_min_val;
378
4
    uint32_t lat_sec_val;
379
4
    bool     lat_hem_val;
380
381
4
    uint32_t long_deg_val;
382
4
    uint32_t long_min_val;
383
4
    uint32_t long_sec_val;
384
4
    bool     long_hem_val;
385
386
4
    uint32_t t_val;
387
388
4
    proto_item *item;
389
4
    proto_tree *sub_tree;
390
391
4
    proto_item *lat_item;
392
4
    proto_item *long_item;
393
4
    proto_tree *lat_tree;
394
4
    proto_tree *long_tree;
395
4
    proto_item *lat_sec, *long_sec;
396
397
4
    curr_offset = offset;
398
399
4
    item = proto_tree_add_item(tree, hf_gsm_r_uus1_elda, tvb, curr_offset, 16, ENC_NA);
400
4
    sub_tree = proto_item_add_subtree(item, ett_gsm_r_uus1_elda);
401
4
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_tag, tvb, curr_offset, 1, ENC_NA);
402
4
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_len, tvb, curr_offset+1, 1, ENC_NA);
403
4
    curr_offset += 2;
404
405
    /* Latitude (in subtree) - 27 bits */
406
4
    lat_item = proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elda_lat, tvb, curr_offset, 4, ENC_NA);
407
4
    lat_tree = proto_item_add_subtree(lat_item, ett_gsm_r_uus1_elda_lat);
408
409
4
    proto_tree_add_item_ret_uint(lat_tree, hf_gsm_r_uus1_elda_lat_deg, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &lat_deg_val);
410
4
    proto_tree_add_item_ret_uint(lat_tree, hf_gsm_r_uus1_elda_lat_min, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &lat_min_val);
411
4
    lat_sec = proto_tree_add_item_ret_uint(lat_tree, hf_gsm_r_uus1_elda_lat_sec, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &lat_sec_val);
412
4
    proto_item_append_text(lat_sec, " (%.2f)", (float)(lat_sec_val)/100);
413
4
    proto_tree_add_item_ret_boolean(lat_tree, hf_gsm_r_uus1_elda_lat_hem, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &lat_hem_val);
414
415
    /* Add details to subtree */
416
4
    proto_item_set_text(lat_item, "Latitude: %d %d\'%.2f\"%s", lat_deg_val, lat_min_val, (float)(lat_sec_val)/100,
417
4
        lat_hem_val ? "N" : "S");
418
419
    /* Move past 3 bytes */
420
4
    curr_offset += 3;
421
422
    /* Longitude (in subtree) - 28 bits */
423
4
    long_item = proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elda_long, tvb, curr_offset, 4, ENC_NA);
424
4
    long_tree = proto_item_add_subtree(long_item, ett_gsm_r_uus1_elda_long);
425
426
4
    proto_tree_add_item_ret_uint(long_tree, hf_gsm_r_uus1_elda_long_deg, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &long_deg_val);
427
4
    proto_tree_add_item_ret_uint(long_tree, hf_gsm_r_uus1_elda_long_min, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &long_min_val);
428
4
    long_sec = proto_tree_add_item_ret_uint(long_tree, hf_gsm_r_uus1_elda_long_sec, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &long_sec_val);
429
4
    proto_item_append_text(long_sec, " (%.2f)", (float)(long_sec_val)/100);
430
4
    proto_tree_add_item_ret_boolean(long_tree, hf_gsm_r_uus1_elda_long_hem, tvb, curr_offset, 4, ENC_BIG_ENDIAN, &long_hem_val);
431
432
    /* Add details to subtree */
433
4
    proto_item_set_text(long_item, "Longitude: %d %d\'%.2f\"%s", long_deg_val, long_min_val, (float)(long_sec_val)/100,
434
4
        long_hem_val ? "W" : "E");
435
436
4
    curr_offset += 3;
437
438
    /* TODO: would be nice to add masks to the items below and dispense with messy calls to get bit values with explicit offsets */
439
4
    bit_offset = 55;
440
441
    /* Height, Speed, Heading */
442
443
    // height step 1m. Range: -100m...+4500m
444
4
    t_val = tvb_get_bits16(tvb, bit_offset, 13, ENC_BIG_ENDIAN) - 100;
445
4
    proto_tree_add_int(sub_tree, hf_gsm_r_uus1_elda_height, tvb, curr_offset, 4, t_val);
446
4
    bit_offset += 13;
447
448
    // speed step 10 km/h
449
4
    t_val = tvb_get_bits8(tvb, bit_offset, 6) * 10;
450
4
    proto_tree_add_uint(sub_tree, hf_gsm_r_uus1_elda_speed, tvb, curr_offset, 4, t_val);
451
4
    bit_offset += 6;
452
453
    // heading step 10 deg
454
4
    t_val = tvb_get_bits8(tvb, bit_offset, 6) * 10;
455
4
    proto_tree_add_uint(sub_tree, hf_gsm_r_uus1_elda_heading, tvb, curr_offset, 4, t_val);
456
4
    bit_offset += 6;
457
458
4
    curr_offset += 4;
459
460
    /* Elapsed Time, Distance, Scale, Spare */
461
462
    // time step 1 second. Range: 0...2047
463
4
    t_val = tvb_get_bits16(tvb, bit_offset, 11, ENC_BIG_ENDIAN);
464
4
    proto_tree_add_uint(sub_tree, hf_gsm_r_uus1_elda_e_time, tvb, curr_offset, 4, t_val);
465
4
    bit_offset += 11;
466
467
    // distance step = 10 cm, 1 m or 10 m depending on the parameter Scale
468
4
    t_val = tvb_get_bits16(tvb, bit_offset, 14, ENC_BIG_ENDIAN);
469
4
    proto_tree_add_uint(sub_tree, hf_gsm_r_uus1_elda_distance, tvb, curr_offset, 4, t_val);
470
4
    bit_offset += 14;
471
472
    // scale
473
4
    t_val = tvb_get_bits8(tvb, bit_offset, 2);
474
4
    proto_tree_add_uint(sub_tree, hf_gsm_r_uus1_elda_scale, tvb, curr_offset, 4, t_val);
475
4
    bit_offset += 2;
476
477
    // spare
478
4
    t_val = tvb_get_bits8(tvb, bit_offset, 5);
479
4
    proto_tree_add_uint(sub_tree, hf_gsm_r_uus1_elda_spare, tvb, curr_offset, 4, t_val);
480
481
4
    return 16;
482
4
}
483
484
/*
485
 * 5.7 Notification DSD alarm condition
486
 *
487
 */
488
static uint16_t
489
de_gsm_r_uus1_dsd_alarm(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset)
490
6
{
491
6
    uint32_t  curr_offset;
492
6
    uint32_t  len;
493
6
    const char *loco_engine_number;
494
6
    proto_item *item;
495
6
    proto_tree *sub_tree;
496
497
6
    curr_offset = offset;
498
499
6
    len = tvb_get_uint8(tvb, offset+1);
500
501
6
    item = proto_tree_add_item(tree, hf_gsm_r_uus1_present_dsd_alarm, tvb, curr_offset, len+2, ENC_NA);
502
6
    sub_tree = proto_item_add_subtree(item, ett_gsm_r_uus1_present_dsd_alarm);
503
504
6
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_tag, tvb, curr_offset, 1, ENC_NA);
505
6
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_len, tvb, curr_offset+1, 1, ENC_NA);
506
6
    curr_offset += 2;
507
508
6
    loco_engine_number = tvb_bcd_dig_to_str(pinfo->pool, tvb, offset+2, len, NULL, false);
509
6
    proto_tree_add_string(sub_tree, hf_gsm_r_uus1_present_dsd_alarm_loco_number, tvb, curr_offset, len, loco_engine_number);
510
6
    proto_item_append_text(item, ": %s", loco_engine_number);
511
6
    curr_offset += len;
512
513
6
    return (curr_offset - offset);
514
6
}
515
516
517
/*
518
 * 5.8 Notification of a request to alert a controller
519
 *
520
 */
521
static uint16_t
522
de_gsm_r_uus1_alert_controller(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset)
523
1
{
524
1
    uint32_t  curr_offset;
525
1
    uint32_t  len;
526
1
    proto_item *item;
527
1
    proto_tree *sub_tree;
528
1
    char       *gref_str;
529
530
1
    curr_offset = offset;
531
532
1
    len = tvb_get_uint8(tvb, offset+1);
533
534
1
    item = proto_tree_add_item(tree, hf_gsm_r_uus1_alert_controller, tvb, curr_offset+2, len, ENC_NA);
535
1
    sub_tree = proto_item_add_subtree(item, ett_gsm_r_uus1_alert_controller);
536
537
1
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_tag, tvb, curr_offset, 1, ENC_NA);
538
1
    proto_tree_add_item(sub_tree, hf_gsm_r_uus1_elem_len, tvb, curr_offset+1, 1, ENC_NA);
539
1
    curr_offset += 2;
540
541
1
    proto_tree_add_item_ret_display_string(sub_tree, hf_gsm_r_uus1_alert_controller_gref, tvb, curr_offset, 4, ENC_BCD_DIGITS_0_9|ENC_LITTLE_ENDIAN, pinfo->pool, &gref_str);
542
1
    proto_item_append_text(item, ": %s", gref_str);
543
1
    curr_offset += 4;
544
545
1
    return (curr_offset - offset);
546
1
}
547
548
549
static int
550
dissect_gsm_r_uus1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
551
28
{
552
28
    uint8_t elem_tag;
553
28
    uint32_t  offset;
554
28
    uint32_t  len;
555
28
    proto_item   *gsm_r_uus1_item   = NULL;
556
28
    proto_tree   *gsm_r_uus1_tree   = NULL;
557
558
28
    offset = 0;
559
28
    len = tvb_captured_length(tvb);
560
561
28
    gsm_r_uus1_item =
562
28
        proto_tree_add_protocol_format(tree, proto_gsm_r_uus1, tvb, 0, len, "GSM-R User-to-User Signaling");
563
564
28
    gsm_r_uus1_tree = proto_item_add_subtree(gsm_r_uus1_item, ett_gsm_r_uus1);
565
566
74
    while (offset < len){
567
64
        elem_tag = tvb_get_uint8(tvb, offset);
568
64
        switch (elem_tag) {
569
19
        case 2:
570
28
        case 3:
571
28
            offset += de_gsm_r_uus1_chpc(tvb, gsm_r_uus1_tree, offset);
572
28
            break;
573
6
        case 5:
574
6
            offset += de_gsm_r_uus1_pfn(tvb, pinfo, gsm_r_uus1_tree, offset);
575
6
            break;
576
2
        case 6:
577
3
        case 7:
578
4
        case 8:
579
4
            offset += de_gsm_r_uus1_elda(tvb, gsm_r_uus1_tree, pinfo, offset);
580
4
            break;
581
3
        case 9:
582
3
            offset += de_gsm_r_uus1_epfn(tvb, gsm_r_uus1_tree, pinfo, offset);
583
3
            break;
584
8
        case 10:
585
8
            offset += de_gsm_r_uus1_text_str(tvb, gsm_r_uus1_tree, pinfo, offset);
586
8
            break;
587
6
        case 11:
588
6
             offset += de_gsm_r_uus1_dsd_alarm(tvb, gsm_r_uus1_tree, pinfo, offset);
589
6
            break;
590
1
        case 12:
591
1
            offset += de_gsm_r_uus1_alert_controller(tvb, gsm_r_uus1_tree, pinfo, offset);
592
1
            break;
593
8
        default:
594
8
            return offset;
595
64
        }
596
64
    }
597
598
10
    return offset;
599
28
}
600
601
/* heuristic dissector */
602
static bool
603
dissect_gsm_r_uus1_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
604
0
{
605
0
    if (dissect_gsm_r_uus1(tvb, pinfo, tree, data) > 0)
606
0
        return false;
607
608
0
    return true;
609
0
}
610
611
612
/* Register the protocol with Wireshark */
613
void
614
proto_register_gsm_r_uus1(void)
615
16
{
616
    /* Setup list of header fields */
617
618
16
    static hf_register_info hf[] = {
619
16
        { &hf_gsm_r_uus1_elem_tag,
620
16
          { "Element tag", "gsm-r-uus1.elem_tag",
621
16
            FT_UINT8, BASE_DEC, VALS(gsm_r_uus1_tags), 0x0,
622
16
            NULL, HFILL }
623
16
        },
624
16
        { &hf_gsm_r_uus1_elem_len,
625
16
          { "Length", "gsm-r-uus1.elem_len",
626
16
            FT_UINT8, BASE_DEC, NULL, 0x0,
627
16
            NULL, HFILL }
628
16
        },
629
16
        { &hf_gsm_r_uus1_pfn,
630
16
          { "Presentation of Functional Number (PFN)", "gsm-r-uus1.pfn",
631
16
            FT_NONE, BASE_NONE, NULL, 0x0,
632
16
            NULL, HFILL }
633
16
        },
634
16
        { &hf_gsm_r_uus1_pfn_digits,
635
16
          { "Digits", "gsm-r-uus1.pfn.digits",
636
16
            FT_STRING, BASE_NONE, NULL, 0x0,
637
16
            NULL, HFILL }
638
16
        },
639
16
        { &hf_gsm_r_uus1_chpc,
640
16
          { "Confirmation of High Priority Calls (CHPC)", "gsm-r-uus1.chpc",
641
16
            FT_NONE, BASE_NONE, NULL, 0x0,
642
16
            NULL, HFILL }
643
16
        },
644
16
        { &hf_gsm_r_uus1_chpc_t_dur,
645
16
          { "Duration of the call", "gsm-r-uus1.chpc.t_dur",
646
16
            FT_UINT24, BASE_DEC, NULL, 0x0,
647
16
            NULL, HFILL }
648
16
        },
649
16
        { &hf_gsm_r_uus1_chpc_t_rel,
650
16
          { "Interval between the end of the call and the transmission of the confirmation message", "gsm-r-uus1.chpc.t_rel",
651
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
652
16
            NULL, HFILL }
653
16
        },
654
16
        { &hf_gsm_r_uus1_chpc_pl_call,
655
16
          { "Priority level of the call", "gsm-r-uus1.chpc.pl_call",
656
16
            FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_r_uus1_chpc_priority_vals), 0x0,
657
16
            NULL, HFILL }
658
16
        },
659
16
        { &hf_gsm_r_uus1_chpc_cause,
660
16
          { "Reason for termination of the call", "gsm-r-uus1.chpc.cause",
661
16
            FT_UINT8, BASE_HEX, NULL, 0x0,
662
16
            NULL, HFILL }
663
16
        },
664
16
        { &hf_gsm_r_uus1_chpc_cause_power,
665
16
          { "Mobile was powered off when receiving (power fail)", "gsm-r-uus1.chpc.cause.power",
666
16
            FT_BOOLEAN, 8, NULL, 0x01,
667
16
            NULL, HFILL }
668
16
        },
669
16
        { &hf_gsm_r_uus1_chpc_cause_radio,
670
16
          { "Call was interrupted due to radio link error", "gsm-r-uus1.chpc.cause.radio",
671
16
            FT_BOOLEAN, 8, NULL, 0x02,
672
16
            NULL, HFILL }
673
16
        },
674
16
        { &hf_gsm_r_uus1_chpc_cause_reserved3,
675
16
          { "Reserved", "gsm-r-uus1.chpc.cause.reserved3",
676
16
            FT_BOOLEAN, 8, NULL, 0x04,
677
16
            NULL, HFILL }
678
16
        },
679
16
        { &hf_gsm_r_uus1_chpc_cause_reserved4,
680
16
          { "Reserved", "gsm-r-uus1.chpc.cause.reserved4",
681
16
            FT_BOOLEAN, 8, NULL, 0x08,
682
16
            NULL, HFILL }
683
16
        },
684
16
        { &hf_gsm_r_uus1_chpc_cause_user_command,
685
16
          { "Call was left on user command", "gsm-r-uus1.chpc.cause.user_command",
686
16
            FT_BOOLEAN, 8, NULL, 0x10,
687
16
            NULL, HFILL }
688
16
        },
689
16
        { &hf_gsm_r_uus1_chpc_cause_reserved6,
690
16
          { "Reserved", "gsm-r-uus1.chpc.cause.reserved6",
691
16
            FT_BOOLEAN, 8, NULL, 0x20,
692
16
            NULL, HFILL }
693
16
        },
694
16
        { &hf_gsm_r_uus1_chpc_cause_reserved7,
695
16
          { "Reserved", "gsm-r-uus1.chpc.cause.reserved7",
696
16
            FT_BOOLEAN, 8, NULL, 0x40,
697
16
            NULL, HFILL }
698
16
        },
699
16
        { &hf_gsm_r_uus1_chpc_cause_reserved8,
700
16
          { "Reserved", "gsm-r-uus1.chpc.cause.reserved8",
701
16
            FT_BOOLEAN, 8, NULL, 0x80,
702
16
            NULL, HFILL }
703
16
        },
704
16
        { &hf_gsm_r_uus1_chpc_gref,
705
16
          { "Group call reference", "gsm-r-uus1.chpc.gref",
706
16
            FT_STRING, BASE_NONE, NULL, 0x0,
707
16
            NULL, HFILL }
708
16
        },
709
16
        { &hf_gsm_r_uus1_chpc_ack_cause,
710
16
          { "ACK/CAUSE", "gsm-r-uus1.chpc.ack_cause",
711
16
            FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_r_uus1_chpc_ack_cause_vals), 0x0,
712
16
            NULL, HFILL }
713
16
        },
714
16
        { &hf_gsm_r_uus1_epfn,
715
16
          { "Enhanced presentation of functional number (ePFN)", "gsm-r-uus1.epfn",
716
16
            FT_BYTES, BASE_NONE, NULL, 0x0,
717
16
            NULL, HFILL }
718
16
        },
719
16
        { &hf_gsm_r_uus1_present_text_str,
720
16
          { "Presentation of text strings", "gsm-r-uus1.present_text_str",
721
16
            FT_BYTES, BASE_NONE, NULL, 0x0,
722
16
            NULL, HFILL }
723
16
        },
724
16
        { &hf_gsm_r_uus1_elda,
725
16
          { "Train position (eLDA)", "gsm-r-uus1.elda",
726
16
            FT_NONE, BASE_NONE, NULL, 0x0,
727
16
            NULL, HFILL }
728
16
        },
729
16
        { &hf_gsm_r_uus1_elda_lat,
730
16
          { "Latitude", "gsm-r-uus1.elda.lat",
731
16
            FT_NONE, BASE_NONE, NULL, 0x0,
732
16
            NULL, HFILL }
733
16
        },
734
16
        { &hf_gsm_r_uus1_elda_lat_deg,
735
16
          { "Degrees", "gsm-r-uus1.elda.lat.deg",
736
16
            FT_UINT32, BASE_DEC, NULL, 0xFE000000,
737
16
            NULL, HFILL }
738
16
        },
739
16
        { &hf_gsm_r_uus1_elda_lat_min,
740
16
          { "Minutes", "gsm-r-uus1.elda.lat.min",
741
16
            FT_UINT32, BASE_DEC, NULL, 0x01F80000,
742
16
            NULL, HFILL }
743
16
        },
744
16
        { &hf_gsm_r_uus1_elda_lat_sec,
745
16
          { "Seconds", "gsm-r-uus1.elda.lat.sec",
746
16
            FT_UINT32, BASE_DEC, NULL, 0x0007FFC0,
747
16
            NULL, HFILL }
748
16
        },
749
16
        { &hf_gsm_r_uus1_elda_lat_hem,
750
16
          { "Hemisphere", "gsm-r-uus1.elda.lat.hem",
751
16
            FT_BOOLEAN, 32, TFS(&gsm_r_uus1_elda_lat_hem), 0x00000020,
752
16
            NULL, HFILL }
753
16
        },
754
16
        { &hf_gsm_r_uus1_elda_long,
755
16
          { "Latitude", "gsm-r-uus1.elda.long",
756
16
            FT_NONE, BASE_NONE, NULL, 0x0,
757
16
            NULL, HFILL }
758
16
        },
759
16
        { &hf_gsm_r_uus1_elda_long_deg,
760
16
          { "Degrees", "gsm-r-uus1.elda.long.deg",
761
16
            FT_UINT32, BASE_DEC, NULL, 0x1FE00000,
762
16
            NULL, HFILL }
763
16
        },
764
16
        { &hf_gsm_r_uus1_elda_long_min,
765
16
          { "Minutes", "gsm-r-uus1.elda.long.min",
766
16
            FT_UINT32, BASE_DEC, NULL, 0x001F8000,
767
16
            NULL, HFILL }
768
16
        },
769
16
        { &hf_gsm_r_uus1_elda_long_sec,
770
16
          { "Seconds", "gsm-r-uus1.elda_long.sec",
771
16
            FT_UINT32, BASE_DEC, NULL, 0x00007FFC,
772
16
            NULL, HFILL }
773
16
        },
774
16
        { &hf_gsm_r_uus1_elda_long_hem,
775
16
          { "Hemisphere", "gsm-r-uus1.elda_long.hem",
776
16
            FT_BOOLEAN, 32, TFS(&gsm_r_uus1_elda_long_hem), 0x00000002,
777
16
            NULL, HFILL }
778
16
        },
779
16
        { &hf_gsm_r_uus1_elda_height,
780
16
          { "Height (m)", "gsm-r-uus1.elda.height",
781
16
            FT_INT32, BASE_DEC, NULL, 0x0,
782
16
            NULL, HFILL }
783
16
        },
784
16
        { &hf_gsm_r_uus1_elda_speed,
785
16
          { "Speed (km/h)", "gsm-r-uus1.elda.speed",
786
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
787
16
            NULL, HFILL }
788
16
        },
789
16
        { &hf_gsm_r_uus1_elda_heading,
790
16
          { "Heading (deg)", "gsm-r-uus1.elda.heading",
791
16
            FT_UINT8, BASE_DEC, NULL, 0x0,
792
16
            NULL, HFILL }
793
16
        },
794
16
        { &hf_gsm_r_uus1_elda_e_time,
795
16
          { "Elapsed Time (sec)", "gsm-r-uus1.elda.e_time",
796
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
797
16
            NULL, HFILL }
798
16
        },
799
16
        { &hf_gsm_r_uus1_elda_distance,
800
16
          { "Distance", "gsm-r-uus1.elda.distance",
801
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
802
16
            NULL, HFILL }
803
16
        },
804
16
        { &hf_gsm_r_uus1_elda_scale,
805
16
          { "Scale", "gsm-r-uus1.elda.scale",
806
16
            FT_UINT32, BASE_DEC, VALS(gsm_r_uus1_elda_scale_vals), 0x00,
807
16
            NULL, HFILL }
808
16
        },
809
16
        { &hf_gsm_r_uus1_elda_spare,
810
16
          { "Spare", "gsm-r-uus1.elda.spare",
811
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
812
16
            NULL, HFILL }
813
16
        },
814
16
        { &hf_gsm_r_uus1_present_dsd_alarm,
815
16
          { "Notification DSD alarm condition", "gsm-r-uus1.present_dsd_alarm",
816
16
            FT_NONE, BASE_NONE, NULL, 0x0,
817
16
            NULL, HFILL }
818
16
        },
819
16
        { &hf_gsm_r_uus1_present_dsd_alarm_loco_number,
820
16
          { "Locomotive engine number", "gsm-r-uus1.present_dsd_alarm.loco_number",
821
16
            FT_STRING, BASE_NONE, NULL, 0x0,
822
16
            NULL, HFILL }
823
16
        },
824
16
        { &hf_gsm_r_uus1_alert_controller,
825
16
          { "Notification of a request to alert a controller", "gsm-r-uus1.alert_controller",
826
16
            FT_NONE, BASE_NONE, NULL, 0x0,
827
16
            NULL, HFILL }
828
16
        },
829
16
        { &hf_gsm_r_uus1_alert_controller_gref,
830
16
          { "Group call reference", "gsm-r-uus1.alert_controller.gref",
831
16
            FT_STRING, BASE_NONE, NULL, 0x0,
832
16
            NULL, HFILL }
833
16
        },
834
16
    };
835
836
16
    static ei_register_info ei[] = {
837
16
        { &ei_gsm_r_uus1_not_implemented_yet, { "gsm-r-uus1.not_implemented_yet", PI_UNDECODED, PI_NOTE, "Not implemented yet", EXPFILL }},
838
16
    };
839
840
16
    expert_module_t* expert_gsm_r_uus1;
841
842
16
    static int *ett[] = {
843
16
        &ett_gsm_r_uus1,
844
16
        &ett_gsm_r_uus1_pfn,
845
16
        &ett_gsm_r_uus1_chpc,
846
16
        &ett_gsm_r_uus1_chpc_cause,
847
16
        &ett_gsm_r_uus1_epfn,
848
16
        &ett_gsm_r_uus1_present_text_str,
849
16
        &ett_gsm_r_uus1_elda,
850
16
        &ett_gsm_r_uus1_elda_lat,
851
16
        &ett_gsm_r_uus1_elda_long,
852
16
        &ett_gsm_r_uus1_present_dsd_alarm,
853
16
        &ett_gsm_r_uus1_alert_controller
854
16
    };
855
856
16
    module_t *gsm_r_uus1_module;
857
858
    /* Register the protocol name and description */
859
16
    proto_gsm_r_uus1 =
860
16
        proto_register_protocol("GSM-R User-to-User Signaling", "GSM-R", "gsm-r-uus1");
861
862
16
    proto_register_field_array(proto_gsm_r_uus1, hf, array_length(hf));
863
864
16
    proto_register_subtree_array(ett, array_length(ett));
865
866
16
    expert_gsm_r_uus1 = expert_register_protocol(proto_gsm_r_uus1);
867
16
    expert_register_field_array(expert_gsm_r_uus1, ei, array_length(ei));
868
869
    /* subdissector code */
870
16
    register_dissector("gsm-r-uus1", dissect_gsm_r_uus1, proto_gsm_r_uus1);
871
872
16
    gsm_r_uus1_module = prefs_register_protocol(proto_gsm_r_uus1, proto_reg_handoff_gsm_r_uus1);
873
16
    prefs_register_bool_preference(gsm_r_uus1_module, "dissect_q931_u2u",
874
16
        "Dissect Q.931 User-To-User information",
875
16
        "Dissect Q.931 User-To-User information",
876
16
        &q931_u2u);
877
16
    prefs_register_bool_preference(gsm_r_uus1_module, "dissect_gsm_a_u2u",
878
16
        "Dissect GSM-A User-To-User information",
879
16
        "Dissect GSM-A User-To-User information",
880
16
        &gsm_a_u2u);
881
16
}
882
883
void
884
proto_reg_handoff_gsm_r_uus1(void)
885
16
{
886
16
    dissector_handle_t gsm_r_uus1_handle;
887
888
16
    gsm_r_uus1_handle = find_dissector("gsm-r-uus1");
889
890
16
    if(q931_u2u){
891
0
        heur_dissector_add("q931_user", dissect_gsm_r_uus1_heur, "GSM-R over UUS1", "gsm_r_uus1", proto_gsm_r_uus1, HEURISTIC_ENABLE);
892
16
    } else {
893
16
        heur_dissector_delete("q931_user", dissect_gsm_r_uus1_heur, proto_gsm_r_uus1);
894
16
    }
895
896
897
16
    if(gsm_a_u2u){
898
16
        dissector_add_uint("gsm_a.dtap.u2u_prot_discr", 0, gsm_r_uus1_handle);
899
16
    } else {
900
0
        dissector_delete_uint("gsm_a.dtap.u2u_prot_discr", 0, gsm_r_uus1_handle);
901
0
    }
902
16
}
903
904
/*
905
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
906
 *
907
 * Local variables:
908
 * c-basic-offset: 4
909
 * tab-width: 8
910
 * indent-tabs-mode: nil
911
 * End:
912
 *
913
 * vi: set shiftwidth=4 tabstop=8 expandtab:
914
 * :indentSize=4:tabSize=8:noTabs=true:
915
 */