Coverage Report

Created: 2026-08-14 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/wiretap/mmodule.c
Line
Count
Source
1
/** @file
2
 *
3
 * Copyright 2025, Daniel Salloum <daniel.salloum@gmail.com>
4
 *
5
 * SPDX-License-Identifier: GPL-2.0-or-later
6
 *
7
 */
8
9
#include "config.h"
10
#define WS_LOG_DOMAIN "MModuleFile"
11
#include "mmodule.h"
12
13
#include "wtap_module.h"
14
#include "file_wrappers.h"
15
16
static int mmodule_file_type_subtype = -1;
17
static struct mmodule_phdr *mmodule;
18
19
void register_mmodule(void);
20
21
bool verify_checksum(FILE_T fh, int *err, char **err_info)
22
0
{
23
0
    uint32_t checksum=0, tmp;
24
25
0
    if (file_seek(fh, 0x00, SEEK_SET, err) == -1){
26
0
        return false;
27
0
    }
28
29
0
    while (wtap_read_bytes(fh, &tmp, 4, err, err_info)) {
30
0
        checksum += tmp;
31
0
    }
32
33
0
    if (file_seek(fh, 0x00, SEEK_SET, err) == -1){
34
0
        return false;
35
0
    }
36
37
0
    if (checksum == 0)
38
0
        return true;
39
40
0
    return false;
41
0
}
42
43
wtap_open_return_val mmodule_open(wtap *wth, int *err, char **err_info)
44
0
{
45
0
    uint32_t tmp;
46
47
    // Check if a file tag we recognize
48
0
    mmodule = g_new(struct mmodule_phdr, 1);
49
0
    if (file_seek(wth->fh, 0x00, SEEK_SET, err) < 0) {
50
0
        g_free(mmodule);
51
0
        return false;
52
0
    }
53
0
    if (!wtap_read_bytes_or_eof(wth->fh, &tmp, 4, err, err_info)) {
54
0
        g_free(mmodule);
55
0
        return false;
56
0
    }
57
0
    uint32_t tag = GUINT32_FROM_LE(tmp);
58
0
    if (tag > 10 || tag < 1) {
59
0
        g_free(mmodule);
60
0
        return WTAP_OPEN_NOT_MINE;
61
0
    }
62
63
    // Check if a version type we recognize
64
0
    if (file_seek(wth->fh, 0x10, SEEK_SET, err) < 0) {
65
0
        g_free(mmodule);
66
0
        return false;
67
0
    }
68
0
    if (!wtap_read_bytes_or_eof(wth->fh, &tmp, 4, err, err_info)) {
69
0
        g_free(mmodule);
70
0
        return false;
71
0
    }
72
0
    uint32_t vtype = GUINT32_FROM_LE(tmp);
73
0
    if (vtype > 3 || vtype < 1) {
74
0
        return WTAP_OPEN_NOT_MINE;
75
0
    }
76
77
    // Reported and actual lengths are not the same
78
0
    if (file_seek(wth->fh, 0x00, SEEK_END, err) == -1){
79
0
        g_free(mmodule);
80
0
        return false;
81
0
    }
82
0
    uint32_t file_len = (uint32_t) file_tell(wth->fh);
83
0
    if (file_seek(wth->fh, 0x20, SEEK_SET, err) == -1){
84
0
        g_free(mmodule);
85
0
        return false;
86
0
    }
87
0
    if (!wtap_read_bytes_or_eof(wth->fh, &tmp, 4, err, err_info)) {
88
0
        g_free(mmodule);
89
0
        return false;
90
0
    }
91
0
    uint32_t reported_len = GUINT32_FROM_LE(tmp);
92
0
    if (reported_len != file_len) {
93
0
        g_free(mmodule);
94
0
        return WTAP_OPEN_NOT_MINE;
95
0
    }
96
97
    // Confirm entire file checksum
98
0
    if (verify_checksum(wth->fh,err,err_info) == false) {
99
0
        g_free(mmodule);
100
0
        return WTAP_OPEN_NOT_MINE;
101
0
    }
102
103
0
    wth->file_type_subtype = mmodule_file_type_subtype;
104
0
    wth->file_encap = WTAP_ENCAP_MMODULE;
105
0
    wth->snapshot_length = 0;
106
0
    wth->file_tsprec = WTAP_TSPREC_SEC;
107
0
    wth->subtype_read = wtap_full_file_read;
108
0
    wth->subtype_seek_read = wtap_full_file_seek_read;
109
110
    // Explicitly set, in case code gets updated somewhere
111
0
    if (file_seek(wth->fh, 0, SEEK_SET, err) == -1) {
112
0
        g_free(mmodule);
113
0
        return WTAP_OPEN_ERROR;
114
0
    }
115
116
0
    return WTAP_OPEN_MINE;
117
0
}
118
119
static const struct supported_block_type mmodule_blocks_supported[] = {
120
    /*
121
     * We support packet blocks, with no comments or other options.
122
     */
123
    // Use this if we break it up into different packets
124
    //{ WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
125
    { WTAP_BLOCK_PACKET, ONE_BLOCK_SUPPORTED, NO_OPTIONS_SUPPORTED }
126
};
127
128
static const struct file_type_subtype_info mmodule_info = {
129
    "Bachmann M-Module file", // description
130
    "m_module", // name
131
    "m", // extension
132
    NULL, // extra extensions
133
    false, // seek required?
134
    BLOCKS_SUPPORTED(mmodule_blocks_supported), // num blocks and block_type
135
    NULL,  // write support?
136
    NULL,  // open write support ?
137
    NULL   // We're not a lua writer
138
};
139
140
void register_mmodule(void)
141
16
{
142
16
    mmodule_file_type_subtype = wtap_register_file_type_subtype(&mmodule_info);
143
144
    /*
145
     * Register name for backwards compatibility with the
146
     * wtap_filetypes table in Lua.
147
     */
148
16
    wtap_register_backwards_compatibility_lua_name("MMODULE",
149
16
                                                   mmodule_file_type_subtype);
150
16
}
151
152
/*
153
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
154
 *
155
 * Local variables:
156
 * c-basic-offset: 4
157
 * tab-width: 8
158
 * indent-tabs-mode: nil
159
 * End:
160
 *
161
 * vi: set shiftwidth=4 tabstop=8 expandtab:
162
 * :indentSize=4:tabSize=8:noTabs=true:
163
 */