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-egnos-ems.c
Line
Count
Source
1
/* packet-ems.c
2
 * EGNOS Message Server file format dissection.
3
 *
4
 * By Timo Warns <timo.warns@gmail.com>
5
 * Copyright 2023 Timo Warns
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@unicom.net>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 */
13
14
#include "config.h"
15
#include <epan/packet.h>
16
#include <errno.h>
17
#include <glib.h>
18
#include <proto.h>
19
#include <strutil.h>
20
#include <tvbuff.h>
21
#include <wiretap/wtap.h>
22
23
#include "packet-sbas_l1.h"
24
25
/*
26
 * Dissects EMS files with format as defined by the
27
 * "Multi-Band EGNOS File Format Description Document" (ESA-EGN-EPO-ICD-0031, Issue 1.4)
28
 */
29
30
/* Initialize the protocol and registered fields */
31
static int proto_ems;
32
33
static int hf_ems_prn;
34
static int hf_ems_year;
35
static int hf_ems_month;
36
static int hf_ems_day;
37
static int hf_ems_hour;
38
static int hf_ems_minute;
39
static int hf_ems_second;
40
static int hf_ems_svc_flag;
41
static int hf_ems_nof_bits;
42
static int hf_ems_nof;
43
static int hf_ems_mt;
44
45
static dissector_table_t ems_msg_dissector_table;
46
47
static int ett_ems;
48
49
static dissector_handle_t  ems_handle;
50
51
/* Dissect EMS data record */
52
0
static int dissect_ems(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) {
53
0
    GByteArray *bytes = g_byte_array_new();
54
55
0
    const char *nof_bits_hex_str;
56
0
    int nof_bits_hex_str_len;
57
0
    int nof_bits;
58
0
    int nof_hex_chars_len;
59
60
0
    const char *svc_flag;
61
62
0
    tvbuff_t *next_tvb = NULL;
63
64
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "EMS");
65
0
    col_clear(pinfo->cinfo, COL_INFO);
66
67
0
    proto_tree *ems_tree = proto_tree_add_subtree_format(tree, tvb, 0, 40, ett_ems, NULL, "EMS");
68
69
0
    proto_tree_add_item(ems_tree, hf_ems_prn,    tvb,  0, 3, ENC_ASCII);
70
0
    proto_tree_add_item(ems_tree, hf_ems_year,   tvb,  4, 2, ENC_ASCII);
71
0
    proto_tree_add_item(ems_tree, hf_ems_month,  tvb,  7, 2, ENC_ASCII);
72
0
    proto_tree_add_item(ems_tree, hf_ems_day,    tvb, 10, 2, ENC_ASCII);
73
0
    proto_tree_add_item(ems_tree, hf_ems_hour,   tvb, 13, 2, ENC_ASCII);
74
0
    proto_tree_add_item(ems_tree, hf_ems_minute, tvb, 16, 2, ENC_ASCII);
75
76
0
    gboolean is_l1 = tvb_get_uint8(tvb, 21) == ' ';
77
0
    if (is_l1) {
78
79
0
        svc_flag = EMS_L1_SVC_FLAG;
80
81
        // L1 message are always encoded as 64 hex chars
82
0
        nof_hex_chars_len = 64;
83
84
0
        proto_tree_add_item(ems_tree, hf_ems_second, tvb, 19, 2, ENC_ASCII);
85
86
        // Single digit MT?
87
0
        if (tvb_get_uint8(tvb, 23) == ' ') {
88
0
            proto_tree_add_item(ems_tree, hf_ems_mt, tvb, 22, 1, ENC_ASCII);
89
0
            proto_tree_add_bytes_item(ems_tree, hf_ems_nof, tvb, 24, nof_hex_chars_len, ENC_ASCII | ENC_STR_HEX | ENC_SEP_NONE, bytes, NULL, NULL);
90
0
        }
91
0
        else {
92
0
            proto_tree_add_item(ems_tree, hf_ems_mt, tvb, 22, 2, ENC_ASCII);
93
0
            proto_tree_add_bytes_item(ems_tree, hf_ems_nof, tvb, 25, nof_hex_chars_len, ENC_ASCII | ENC_STR_HEX | ENC_SEP_NONE, bytes, NULL, NULL);
94
0
        }
95
0
    }
96
0
    else { // L5 or non-standard message encoding
97
0
        proto_tree_add_item(ems_tree, hf_ems_second, tvb, 19, 9, ENC_ASCII);
98
0
        proto_tree_add_item_ret_string(ems_tree, hf_ems_svc_flag, tvb, 29, 2, ENC_ASCII, pinfo->pool, (const uint8_t **) &svc_flag);
99
0
        proto_tree_add_item_ret_string_and_length(ems_tree, hf_ems_nof_bits, tvb, 32, 4, ENC_ASCII, pinfo->pool, (const uint8_t**)&nof_bits_hex_str, &nof_bits_hex_str_len);
100
0
        proto_tree_add_item(ems_tree, hf_ems_mt, tvb, 37, 2, ENC_ASCII);
101
102
        // dissect NOF with a number of bits given by NOF bits
103
0
        if (nof_bits_hex_str && nof_bits_hex_str_len > 0) {
104
0
            errno = 0;
105
0
            nof_bits = (int) strtol(nof_bits_hex_str, NULL, 16);
106
107
0
            if (!errno) {
108
0
                nof_hex_chars_len = 2 * ((nof_bits / 8) + ((nof_bits % 8) ? 1 : 0));
109
0
                proto_tree_add_bytes_item(ems_tree, hf_ems_nof, tvb, 40, nof_hex_chars_len, ENC_ASCII | ENC_STR_HEX | ENC_SEP_NONE, bytes, NULL, NULL);
110
0
            }
111
0
        }
112
0
    }
113
114
0
    next_tvb = tvb_new_child_real_data(tvb, (uint8_t *)wmem_memdup(pinfo->pool, bytes->data, bytes->len), bytes->len, bytes->len);
115
0
    add_new_data_source(pinfo, next_tvb, "SBAS message");
116
117
0
    if (!dissector_try_string_with_data(ems_msg_dissector_table, svc_flag, next_tvb, pinfo, tree, true, NULL)) {
118
0
        call_data_dissector(next_tvb, pinfo, tree);
119
0
    }
120
121
0
    g_byte_array_free(bytes, true);
122
123
0
    return tvb_captured_length(tvb);
124
0
}
125
126
14
void proto_register_ems(void) {
127
128
14
    static hf_register_info hf[] = {
129
14
        {&hf_ems_prn,      {"PRN",             "ems.prn",      FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
130
14
        {&hf_ems_year,     {"Year",            "ems.year",     FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
131
14
        {&hf_ems_month,    {"Month",           "ems.month",    FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
132
14
        {&hf_ems_day,      {"Day",             "ems.day",      FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
133
14
        {&hf_ems_hour,     {"Hour",            "ems.hour",     FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
134
14
        {&hf_ems_minute,   {"Minute",          "ems.minute",   FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
135
14
        {&hf_ems_second,   {"Second",          "ems.second",   FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
136
14
        {&hf_ems_svc_flag, {"Service Flag",    "ems.svc_flag", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
137
14
        {&hf_ems_nof_bits, {"NOF Bits Number", "ems.nof_bits", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
138
14
        {&hf_ems_mt,       {"Message Type",    "ems.mt",       FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
139
14
        {&hf_ems_nof,      {"NOF",             "ems.nof",      FT_BYTES,  BASE_NONE, NULL, 0x0, NULL, HFILL }},
140
14
    };
141
142
14
    static int *ett[] = {
143
14
        &ett_ems,
144
14
    };
145
146
14
    proto_ems = proto_register_protocol("EGNOS Message Server file", "EMS", "ems");
147
14
    ems_handle = register_dissector("ems", dissect_ems, proto_ems);
148
149
14
    proto_register_field_array(proto_ems, hf, array_length(hf));
150
14
    proto_register_subtree_array(ett, array_length(ett));
151
152
14
    ems_msg_dissector_table = register_dissector_table("ems.svc_flag", "EMS Service Flag", proto_ems, FT_STRING, STRING_CASE_SENSITIVE);
153
14
}
154
155
14
void proto_reg_handoff_ems(void) {
156
14
    static bool initialized = false;
157
158
14
    if (!initialized) {
159
14
        dissector_add_uint("wtap_encap", WTAP_ENCAP_EMS, ems_handle);
160
14
    }
161
14
}