Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-igap.c
Line
Count
Source
1
/* packet-igap.c
2
 * Routines for IGMP/IGAP packet disassembly
3
 * 2003, Endoh Akria (see AUTHORS for email)
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/*
13
        IGAP "Internet Group membership Authentication Protocol"
14
        is defined in draft-hayashi-igap-03.txt.
15
16
        (Author's memo)
17
         Type  Subtype  Message                     Msize
18
        -----------------------------------------------------
19
         ----   0x02    User password               variable
20
         ----   0x03    ----                        00
21
         ----   0x04    Result of MD5 calculation   16
22
         0x41   0x23    Challenge value             ??
23
         0x41   0x24    Authentication result code   1
24
         0x41   0x25    Accounting status code       1
25
         ----   0x42    User password               variable
26
         ----   0x43    ----                        00
27
         ----   0x44    Result of MD5 calculation   16
28
29
*/
30
31
#include "config.h"
32
33
#include <epan/packet.h>
34
#include <epan/expert.h>
35
#include "packet-igmp.h"
36
37
void proto_register_igap(void);
38
void proto_reg_handoff_igap(void);
39
40
static dissector_handle_t igap_handle;
41
42
static int proto_igap;
43
static int hf_type;
44
static int hf_max_resp;
45
static int hf_checksum;
46
static int hf_checksum_status;
47
static int hf_maddr;
48
static int hf_version;
49
static int hf_subtype;
50
static int hf_challengeid;
51
static int hf_asize;
52
static int hf_msize;
53
static int hf_account;
54
55
/* Generated from convert_proto_tree_add_text.pl */
56
static int hf_igap_challenge;
57
static int hf_igap_user_password;
58
static int hf_igap_authentication_result;
59
static int hf_igap_result_of_md5_calculation;
60
static int hf_igap_accounting_status;
61
static int hf_igap_unknown_message;
62
63
static int ett_igap;
64
65
static expert_field ei_checksum;
66
67
static const value_string igap_types[] = {
68
    {IGMP_IGAP_JOIN,  "Membership Report (Join)"},
69
    {IGMP_IGAP_QUERY, "Membership Query"},
70
    {IGMP_IGAP_LEAVE, "Leave Group"},
71
    {0, NULL}
72
};
73
74
#define IGAP_VERSION_1 0x10
75
static const value_string igap_version[] = {
76
    {IGAP_VERSION_1, "1"},
77
    {0, NULL}
78
};
79
80
1
#define IGAP_SUBTYPE_PASSWORD_JOIN            0x02
81
#define IGAP_SUBTYPE_CHALLENGE_REQUEST_JOIN   0x03
82
1
#define IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN  0x04
83
#define IGAP_SUBTYPE_BASIC_QUERY              0x21
84
2
#define IGAP_SUBTYPE_CHALLENGE                0x23
85
1
#define IGAP_SUBTYPE_AUTH_MESSAGE             0x24
86
0
#define IGAP_SUBTYPE_ACCOUNTING_MESSAGE       0x25
87
#define IGAP_SUBTYPE_BASIC_LEAVE              0x41
88
3
#define IGAP_SUBTYPE_PASSWORD_LEAVE           0x42
89
#define IGAP_SUBTYPE_CHALLENGE_REQUEST_LEAVE  0x43
90
1
#define IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE 0x44
91
static const value_string igap_subtypes[] = {
92
    {IGAP_SUBTYPE_PASSWORD_JOIN,            "Password Mechanism Join (Password-Join)"},
93
    {IGAP_SUBTYPE_CHALLENGE_REQUEST_JOIN,   "Challenge-Response Mechanism Join Request (Challenge-Request-Join)"},
94
    {IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN,  "Challenge-Response Mechanism Join Response (Challenge-Response-Join)"},
95
    {IGAP_SUBTYPE_BASIC_QUERY,              "Basic Query"},
96
    {IGAP_SUBTYPE_CHALLENGE,                "Challenge-Response Mechanism Challenge (Challenge)"},
97
    {IGAP_SUBTYPE_AUTH_MESSAGE,             "Authentication Message"},
98
    {IGAP_SUBTYPE_ACCOUNTING_MESSAGE,       "Accounting Message"},
99
    {IGAP_SUBTYPE_BASIC_LEAVE,              "Basic Leave"},
100
    {IGAP_SUBTYPE_PASSWORD_LEAVE,           "Password Mechanism Leave (Password-Leave)"},
101
    {IGAP_SUBTYPE_CHALLENGE_REQUEST_LEAVE,  "Challenge-Response Mechanism Leave Challenge Request (Challenge-Request-Leave)"},
102
    {IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE, "Challenge-Response Mechanism Response (Challenge-Response-Leave)"},
103
    {0, NULL}
104
};
105
106
#define IGAP_AUTH_SUCCESS 0x11
107
#define IGAP_AUTH_FAIL    0x21
108
static const value_string igap_auth_result[] = {
109
    {IGAP_AUTH_SUCCESS, "Authentication success"},
110
    {IGAP_AUTH_FAIL,    "Authentication failure"},
111
    {0, NULL}
112
};
113
114
#define IGAP_ACCOUNT_START 0x11
115
#define IGAP_ACCOUNT_STOP  0x21
116
static const value_string igap_account_status[] = {
117
    {IGAP_ACCOUNT_START, "Accounting start"},
118
    {IGAP_ACCOUNT_STOP,  "Accounting stop"},
119
    {0, NULL}
120
};
121
122
25
#define ACCOUNT_SIZE    16
123
20
#define MESSAGE_SIZE    64
124
125
/* This function is only called from the IGMP dissector */
126
static int
127
dissect_igap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
128
11
{
129
11
    proto_tree *tree;
130
11
    proto_item *item;
131
11
    uint8_t type, tsecs, subtype, asize, msize;
132
11
    uint8_t authentication_result, accounting_status;
133
11
    unsigned offset = 0;
134
135
11
    item = proto_tree_add_item(parent_tree, proto_igap, tvb, offset, -1, ENC_NA);
136
11
    tree = proto_item_add_subtree(item, ett_igap);
137
138
11
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGAP");
139
11
    col_clear(pinfo->cinfo, COL_INFO);
140
141
11
    type = tvb_get_uint8(tvb, offset);
142
11
        col_add_str(pinfo->cinfo, COL_INFO,
143
11
                     val_to_str(pinfo->pool, type, igap_types, "Unknown Type: 0x%02x"));
144
11
    proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type);
145
11
    offset += 1;
146
147
11
    tsecs = tvb_get_uint8(tvb, offset);
148
11
    proto_tree_add_uint_format_value(tree, hf_max_resp, tvb, offset, 1, tsecs,
149
11
        "%.1f sec (0x%02x)", tsecs * 0.1, tsecs);
150
11
    offset += 1;
151
152
11
    igmp_checksum(tree, tvb, hf_checksum, hf_checksum_status, &ei_checksum, pinfo, 0);
153
11
    offset += 2;
154
155
11
    proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, ENC_BIG_ENDIAN);
156
11
    offset += 4;
157
158
11
    proto_tree_add_item(tree, hf_version, tvb, offset, 1, ENC_NA);
159
11
    offset += 1;
160
161
11
    subtype = tvb_get_uint8(tvb, offset);
162
11
    proto_tree_add_uint(tree, hf_subtype, tvb, offset, 1, subtype);
163
11
    offset += 2;
164
165
11
    proto_tree_add_item(tree, hf_challengeid, tvb, offset, 1, ENC_NA);
166
11
    offset += 1;
167
168
11
    asize = tvb_get_uint8(tvb, offset);
169
11
    proto_tree_add_uint(tree, hf_asize, tvb, offset, 1, asize);
170
11
    offset += 1;
171
172
11
    msize = tvb_get_uint8(tvb, offset);
173
11
    proto_tree_add_uint(tree, hf_msize, tvb, offset, 1, msize);
174
11
    offset += 3;
175
176
11
    if (asize > 0) {
177
8
        if (asize > ACCOUNT_SIZE) {
178
            /* Bogus account size.
179
               XXX - flag this? */
180
6
            asize = ACCOUNT_SIZE;
181
6
        }
182
        /* XXX - encoding? */
183
8
        proto_tree_add_item(tree, hf_account, tvb, offset, asize, ENC_ASCII);
184
8
    }
185
11
    offset += ACCOUNT_SIZE;
186
187
11
    if (msize > 0) {
188
9
        if (msize > MESSAGE_SIZE) {
189
            /* Bogus message size.
190
               XXX - flag this? */
191
5
            msize = MESSAGE_SIZE;
192
5
        }
193
9
        switch (subtype) {
194
1
        case IGAP_SUBTYPE_PASSWORD_JOIN:
195
3
        case IGAP_SUBTYPE_PASSWORD_LEAVE:
196
            /* Challenge field is user's password */
197
            /* XXX - encoding? */
198
3
            proto_tree_add_item(tree, hf_igap_user_password, tvb, offset, msize, ENC_ASCII);
199
3
            break;
200
1
        case IGAP_SUBTYPE_CHALLENGE_RESPONSE_JOIN:
201
1
        case IGAP_SUBTYPE_CHALLENGE_RESPONSE_LEAVE:
202
            /* Challenge field is the results of MD5 calculation */
203
1
            proto_tree_add_item(tree, hf_igap_result_of_md5_calculation, tvb, offset, msize, ENC_NA);
204
1
            break;
205
2
        case IGAP_SUBTYPE_CHALLENGE:
206
            /* Challenge field is the challenge value */
207
2
            proto_tree_add_item(tree, hf_igap_challenge, tvb, offset, msize, ENC_NA);
208
2
            break;
209
1
        case IGAP_SUBTYPE_AUTH_MESSAGE:
210
            /* Challenge field indicates the result of the authentication */
211
            /* XXX - what if the length isn't 1? */
212
1
            authentication_result = tvb_get_uint8(tvb, offset);
213
1
            proto_tree_add_uint(tree, hf_igap_authentication_result, tvb, offset, msize, authentication_result);
214
1
            break;
215
0
        case IGAP_SUBTYPE_ACCOUNTING_MESSAGE:
216
            /* Challenge field indicates the accounting status */
217
            /* XXX - what if the length isn't 1? */
218
0
            accounting_status = tvb_get_uint8(tvb, offset);
219
0
            proto_tree_add_uint(tree, hf_igap_accounting_status, tvb, offset, msize, accounting_status);
220
0
            break;
221
2
        default:
222
2
            proto_tree_add_item(tree, hf_igap_unknown_message, tvb, offset, msize, ENC_NA);
223
9
        }
224
9
    }
225
6
    offset += MESSAGE_SIZE;
226
227
6
    if (item) proto_item_set_len(item, offset);
228
6
    return offset;
229
11
}
230
231
232
void
233
proto_register_igap(void)
234
14
{
235
14
    static hf_register_info hf[] = {
236
14
        { &hf_type,
237
14
          { "Type", "igap.type",
238
14
            FT_UINT8, BASE_HEX, VALS(igap_types), 0,
239
14
            "IGAP Packet Type", HFILL }
240
14
        },
241
14
        { &hf_max_resp,
242
14
          { "Max Response Time", "igap.max_resp",
243
14
            FT_UINT8, BASE_DEC, NULL, 0,
244
14
            NULL, HFILL }
245
14
        },
246
14
        { &hf_checksum,
247
14
          { "Checksum", "igap.checksum",
248
14
            FT_UINT16, BASE_HEX, NULL, 0,
249
14
            NULL, HFILL }
250
14
        },
251
14
        { &hf_checksum_status,
252
14
          { "Checksum Status", "igap.checksum.status",
253
14
            FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
254
14
            NULL, HFILL }
255
14
        },
256
14
        { &hf_maddr,
257
14
          { "Multicast group address", "igap.maddr",
258
14
            FT_IPv4, BASE_NONE, NULL, 0,
259
14
            NULL, HFILL }
260
14
        },
261
14
        { &hf_version,
262
14
          { "Version", "igap.version",
263
14
            FT_UINT8, BASE_HEX, VALS(igap_version), 0,
264
14
            "IGAP protocol version", HFILL }
265
14
        },
266
14
        { &hf_subtype,
267
14
          { "Subtype", "igap.subtype",
268
14
            FT_UINT8, BASE_HEX, VALS(igap_subtypes), 0,
269
14
            NULL, HFILL }
270
14
        },
271
14
        { &hf_challengeid,
272
14
          { "Challenge ID", "igap.challengeid",
273
14
            FT_UINT8, BASE_HEX, NULL, 0,
274
14
            NULL, HFILL }
275
14
        },
276
14
        { &hf_asize,
277
14
          { "Account Size", "igap.asize",
278
14
            FT_UINT8, BASE_DEC, NULL, 0,
279
14
            "Length of the User Account field", HFILL }
280
14
        },
281
14
        { &hf_msize,
282
14
          { "Message Size", "igap.msize",
283
14
            FT_UINT8, BASE_DEC, NULL, 0,
284
14
            "Length of the Message field", HFILL }
285
14
        },
286
14
        { &hf_account,
287
14
          { "User Account", "igap.account",
288
14
            FT_STRING, BASE_NONE, NULL, 0,
289
14
            NULL, HFILL }
290
14
        },
291
292
        /* Generated from convert_proto_tree_add_text.pl */
293
14
        { &hf_igap_user_password,
294
14
          { "User password", "igap.user_password",
295
14
            FT_STRING, BASE_NONE, NULL, 0x0,
296
14
            NULL, HFILL }
297
14
        },
298
14
        { &hf_igap_result_of_md5_calculation,
299
14
          { "Result of MD5 calculation", "igap.result_of_md5_calculation",
300
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
301
14
            NULL, HFILL }
302
14
        },
303
14
        { &hf_igap_challenge,
304
14
          { "Challenge", "igap.challenge",
305
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
306
14
            NULL, HFILL }
307
14
        },
308
14
        { &hf_igap_authentication_result,
309
14
          { "Authentication result", "igap.authentication_result",
310
14
            FT_UINT8, BASE_HEX, VALS(igap_auth_result), 0x0,
311
14
            NULL, HFILL }
312
14
        },
313
14
        { &hf_igap_accounting_status,
314
14
          { "Accounting status", "igap.accounting_status",
315
14
            FT_UINT8, BASE_HEX, VALS(igap_account_status), 0x0,
316
14
            NULL, HFILL }
317
14
        },
318
14
        { &hf_igap_unknown_message,
319
14
          { "Unknown message", "igap.unknown_message",
320
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
321
14
            NULL, HFILL }
322
14
        },
323
14
    };
324
325
14
    static ei_register_info ei[] = {
326
14
        { &ei_checksum, { "igap.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
327
14
    };
328
329
14
    expert_module_t* expert_igap;
330
331
14
    static int *ett[] = {
332
14
        &ett_igap
333
14
    };
334
335
14
    proto_igap = proto_register_protocol("Internet Group membership Authentication Protocol", "IGAP", "igap");
336
14
    proto_register_field_array(proto_igap, hf, array_length(hf));
337
14
    proto_register_subtree_array(ett, array_length(ett));
338
14
    expert_igap = expert_register_protocol(proto_igap);
339
14
    expert_register_field_array(expert_igap, ei, array_length(ei));
340
341
14
    igap_handle = register_dissector("igap", dissect_igap, proto_igap);
342
14
}
343
344
void
345
proto_reg_handoff_igap(void)
346
14
{
347
14
    dissector_add_uint("igmp.type", IGMP_IGAP_JOIN, igap_handle);
348
14
    dissector_add_uint("igmp.type", IGMP_IGAP_QUERY, igap_handle);
349
14
    dissector_add_uint("igmp.type", IGMP_IGAP_LEAVE, igap_handle);
350
14
}
351
352
/*
353
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
354
 *
355
 * Local variables:
356
 * c-basic-offset: 4
357
 * tab-width: 8
358
 * indent-tabs-mode: nil
359
 * End:
360
 *
361
 * vi: set shiftwidth=4 tabstop=8 expandtab:
362
 * :indentSize=4:tabSize=8:noTabs=true:
363
 */