Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-hicp.c
Line
Count
Source
1
/* packet-hicp.c
2
 * Routines for Host IP Configuration Protocol dissection
3
 * Copyright 2021, Filip Kågesson <exfik@hms.se>
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
#include <config.h>
13
14
#include <epan/packet.h>
15
#include <epan/expert.h>
16
#include <epan/strutil.h>
17
18
void proto_reg_handoff_hicp(void);
19
void proto_register_hicp(void);
20
21
static dissector_handle_t hicp_handle;
22
23
/* Protocols and header fields. */
24
static int proto_hicp;
25
static int hf_hicp_cmd;
26
static int hf_hicp_proto_version;
27
static int hf_hicp_fb_type;
28
static int hf_hicp_module_version;
29
static int hf_hicp_mac;
30
static int hf_hicp_ip;
31
static int hf_hicp_sn;
32
static int hf_hicp_gw;
33
static int hf_hicp_dhcp;
34
static int hf_hicp_pswd_required;
35
static int hf_hicp_hn;
36
static int hf_hicp_dns1;
37
static int hf_hicp_dns2;
38
static int hf_hicp_ext;
39
static int hf_hicp_pswd;
40
static int hf_hicp_new_pswd;
41
static int hf_hicp_new_mac;
42
static int hf_hicp_status;
43
static int hf_hicp_error;
44
static int hf_hicp_target;
45
static int hf_hicp_src;
46
47
static expert_field ei_hicp_error;
48
49
static int ett_hicp;
50
51
15
#define HICP_PORT 3250
52
#define HICP_MIN_LENGTH 2
53
23
#define HICP_DELIMITER ";"
54
55
/* Values of the supported commands. */
56
28
#define HICP_MODULE_SCAN_COMMAND "Module scan"
57
28
#define HICP_CONFIG_COMMAND "Configure"
58
28
#define HICP_WINK_COMMAND "Wink"
59
60
/* Values of the supported parameters. */
61
28
#define HICP_PROTOCOL_VERSION "Protocol version"
62
28
#define HICP_FB_TYPE "FB type"
63
28
#define HICP_MODULE_VERSION "Module version"
64
28
#define HICP_MAC "MAC"
65
28
#define HICP_IP "IP"
66
28
#define HICP_SN "SN"
67
28
#define HICP_GW "GW"
68
28
#define HICP_DHCP "DHCP"
69
28
#define HICP_PSWD_REQUIRED "PSWD"
70
28
#define HICP_HN "HN"
71
28
#define HICP_DNS1 "DNS1"
72
28
#define HICP_DNS2 "DNS2"
73
28
#define HICP_EXT "EXT"
74
28
#define HICP_PSWD "Password"
75
28
#define HICP_NEW_PSWD "New Password"
76
28
#define HICP_NEW_MAC "New MAC"
77
28
#define HICP_RECONFIGURED "Reconfigured"
78
28
#define HICP_INVALID_PSWD "Invalid Password"
79
28
#define HICP_INVALID_CONFIG "Invalid Configuration"
80
28
#define HICP_TO "To"
81
28
#define HICP_EXECUTED "Executed"
82
83
static int
84
dissect_hicp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
85
9
{
86
9
    proto_item* ti;
87
9
    proto_item* error_pi;
88
9
    proto_tree* hicp_tree;
89
90
9
    unsigned offset = 0;
91
9
    unsigned lengthp = 0;
92
9
    double ext_value = 0;
93
94
9
    const char* parameters_ptr = NULL;
95
9
    char** parameters = NULL;
96
9
    char* parameter_value = NULL;
97
98
  /* Check that the packet does not start with the header of Secure Host IP Configuration Protocol (SHICP). */
99
9
    if ((tvb_get_uint16(tvb, offset, ENC_LITTLE_ENDIAN) & 0xFFFE) == 0xABC0) {
100
0
        return 0;
101
0
    }
102
103
9
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "HICP");
104
9
    col_clear(pinfo->cinfo, COL_INFO);
105
106
9
    ti = proto_tree_add_item(tree, proto_hicp, tvb, offset, -1, ENC_NA);
107
108
9
    hicp_tree = proto_item_add_subtree(ti, ett_hicp);
109
110
9
    parameters_ptr = (char*)tvb_get_stringz_enc(pinfo->pool, tvb, offset, &lengthp, ENC_ASCII);
111
9
    parameters = wmem_strsplit(pinfo->pool, (const char*)parameters_ptr, HICP_DELIMITER, -1);
112
23
    for (unsigned i = 0; i < g_strv_length(parameters); i++) {
113
14
        if (g_strrstr(parameters[i], " = ") != NULL) {
114
0
            parameter_value = &(g_strrstr(parameters[i], " = "))[3];
115
0
        }
116
14
        else if (g_strrstr(parameters[i], ": ") != NULL) {
117
0
            parameter_value = &(g_strrstr(parameters[i], ": "))[2];
118
0
        }
119
14
        else {
120
14
            parameter_value = "";
121
14
        }
122
14
        if (g_ascii_strncasecmp(parameters[i], HICP_MODULE_SCAN_COMMAND, (size_t)strlen(HICP_MODULE_SCAN_COMMAND)) == 0) {
123
0
            proto_tree_add_string(hicp_tree, hf_hicp_cmd, tvb, offset, (int)strlen(parameters[i]), HICP_MODULE_SCAN_COMMAND);
124
0
            col_prepend_fstr(pinfo->cinfo, COL_INFO, "Request message, Command: %s", HICP_MODULE_SCAN_COMMAND);
125
0
        }
126
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_CONFIG_COMMAND, (size_t)strlen(HICP_CONFIG_COMMAND)) == 0) {
127
0
            proto_tree_add_string(hicp_tree, hf_hicp_cmd, tvb, offset, (int)strlen(parameters[i]), HICP_CONFIG_COMMAND);
128
0
            proto_tree_add_string(hicp_tree, hf_hicp_target, tvb, offset, (int)strlen(parameters[i]), parameter_value);
129
0
            col_prepend_fstr(pinfo->cinfo, COL_INFO, "Request message, Command: %s", HICP_CONFIG_COMMAND);
130
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value);
131
0
        }
132
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_WINK_COMMAND, (size_t)strlen(HICP_WINK_COMMAND)) == 0) {
133
0
            proto_tree_add_string(hicp_tree, hf_hicp_cmd, tvb, offset, (int)strlen(parameters[i]), HICP_WINK_COMMAND);
134
0
            col_prepend_fstr(pinfo->cinfo, COL_INFO, "Request message, Command: %s", HICP_WINK_COMMAND);
135
0
        }
136
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_PROTOCOL_VERSION, (size_t)strlen(HICP_PROTOCOL_VERSION)) == 0) {
137
0
            proto_tree_add_string(hicp_tree, hf_hicp_cmd, tvb, offset, (int)strlen(parameters[i]), HICP_MODULE_SCAN_COMMAND);
138
0
            proto_tree_add_string(hicp_tree, hf_hicp_proto_version, tvb, offset, (int)strlen(parameters[i]), parameter_value);
139
0
            col_prepend_fstr(pinfo->cinfo, COL_INFO, "Response message, Command: %s", HICP_MODULE_SCAN_COMMAND);
140
0
        }
141
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_FB_TYPE, (size_t)strlen(HICP_FB_TYPE)) == 0) {
142
0
            proto_tree_add_string(hicp_tree, hf_hicp_fb_type, tvb, offset, (int)strlen(parameters[i]), parameter_value);
143
0
        }
144
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_MODULE_VERSION, (size_t)strlen(HICP_MODULE_VERSION)) == 0) {
145
0
            proto_tree_add_string(hicp_tree, hf_hicp_module_version, tvb, offset, (int)strlen(parameters[i]), parameter_value);
146
0
        }
147
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_MAC, (size_t)strlen(HICP_MAC)) == 0) {
148
0
            proto_tree_add_string(hicp_tree, hf_hicp_mac, tvb, offset, (int)strlen(parameters[i]), parameter_value);
149
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value);
150
0
        }
151
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_IP, (size_t)strlen(HICP_IP)) == 0) {
152
0
            proto_tree_add_string(hicp_tree, hf_hicp_ip, tvb, offset, (int)strlen(parameters[i]), parameter_value);
153
0
        }
154
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_SN, (size_t)strlen(HICP_SN)) == 0) {
155
0
            proto_tree_add_string(hicp_tree, hf_hicp_sn, tvb, offset, (int)strlen(parameters[i]), parameter_value);
156
0
        }
157
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_GW, (size_t)strlen(HICP_GW)) == 0) {
158
0
            proto_tree_add_string(hicp_tree, hf_hicp_gw, tvb, offset, (int)strlen(parameters[i]), parameter_value);
159
0
        }
160
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_DHCP, (size_t)strlen(HICP_DHCP)) == 0) {
161
0
            proto_tree_add_string(hicp_tree,
162
0
                hf_hicp_dhcp,
163
0
                tvb,
164
0
                offset,
165
0
                (int)strlen(parameters[i]),
166
0
                g_ascii_strcasecmp(parameter_value, "ON") == 0 ? "Enabled" : "Disabled");
167
0
        }
168
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_PSWD_REQUIRED, (size_t)strlen(HICP_PSWD_REQUIRED)) == 0) {
169
0
            proto_tree_add_string(hicp_tree,
170
0
                hf_hicp_pswd_required,
171
0
                tvb,
172
0
                offset,
173
0
                (int)strlen(parameters[i]),
174
0
                g_ascii_strcasecmp(parameter_value, "ON") == 0 ? "Required" : "Not required");
175
0
        }
176
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_HN, (size_t)strlen(HICP_HN)) == 0) {
177
0
            proto_tree_add_string(hicp_tree, hf_hicp_hn, tvb, offset, (int)strlen(parameters[i]), parameter_value);
178
0
        }
179
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_DNS1, (size_t)strlen(HICP_DNS1)) == 0) {
180
0
            proto_tree_add_string(hicp_tree, hf_hicp_dns1, tvb, offset, (int)strlen(parameters[i]), parameter_value);
181
0
        }
182
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_DNS2, (size_t)strlen(HICP_DNS2)) == 0) {
183
0
            proto_tree_add_string(hicp_tree, hf_hicp_dns2, tvb, offset, (int)strlen(parameters[i]), parameter_value);
184
0
        }
185
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_EXT, (size_t)strlen(HICP_EXT)) == 0) {
186
0
            ext_value = g_ascii_strtod(parameter_value, NULL);
187
0
            if (ext_value == 1) {
188
0
                parameter_value = HICP_WINK_COMMAND;
189
0
            }
190
0
            else if (ext_value == 0) {
191
0
                parameter_value = "None";
192
0
            }
193
0
            proto_tree_add_string(hicp_tree, hf_hicp_ext, tvb, offset, (int)strlen(parameters[i]), parameter_value);
194
0
        }
195
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_PSWD, (size_t)strlen(HICP_PSWD)) == 0) {
196
0
            proto_tree_add_string(hicp_tree, hf_hicp_pswd, tvb, offset, (int)strlen(parameters[i]), parameter_value);
197
0
        }
198
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_NEW_PSWD, (size_t)strlen(HICP_NEW_PSWD)) == 0) {
199
0
            proto_tree_add_string(hicp_tree, hf_hicp_new_pswd, tvb, offset, (int)strlen(parameters[i]), parameter_value);
200
0
        }
201
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_NEW_MAC, (size_t)strlen(HICP_NEW_MAC)) == 0) {
202
0
            proto_tree_add_string(hicp_tree, hf_hicp_new_mac, tvb, offset, (int)strlen(parameters[i]), parameter_value);
203
0
        }
204
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_RECONFIGURED, (size_t)strlen(HICP_RECONFIGURED)) == 0) {
205
0
            proto_tree_add_string(hicp_tree, hf_hicp_status, tvb, offset, (int)strlen(parameters[i]), HICP_RECONFIGURED);
206
0
            proto_tree_add_string(hicp_tree, hf_hicp_src, tvb, offset, (int)strlen(parameters[i]), parameter_value);
207
0
            col_prepend_fstr(pinfo->cinfo, COL_INFO, "Respond message, Command: %s", HICP_CONFIG_COMMAND);
208
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value);
209
0
        }
210
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_INVALID_PSWD, (size_t)strlen(HICP_INVALID_PSWD)) == 0) {
211
0
            proto_tree_add_string(hicp_tree, hf_hicp_src, tvb, offset, (int)strlen(parameters[i]), parameter_value);
212
0
            error_pi = proto_tree_add_string(hicp_tree, hf_hicp_error, tvb, offset, (int)strlen(parameters[i]), HICP_INVALID_PSWD);
213
0
            expert_add_info(pinfo, error_pi, &ei_hicp_error);
214
0
            col_prepend_fstr(pinfo->cinfo, COL_INFO, "Error: %s", HICP_INVALID_PSWD);
215
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: %s, Module MAC address: %s", HICP_CONFIG_COMMAND, parameter_value);
216
0
        }
217
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_INVALID_CONFIG, (size_t)strlen(HICP_INVALID_CONFIG)) == 0) {
218
0
            proto_tree_add_string(hicp_tree, hf_hicp_src, tvb, offset, (int)strlen(parameters[i]), parameter_value);
219
0
            error_pi = proto_tree_add_string(hicp_tree, hf_hicp_error, tvb, offset, (int)strlen(parameters[i]), HICP_INVALID_CONFIG);
220
0
            expert_add_info(pinfo, error_pi, &ei_hicp_error);
221
0
            col_prepend_fstr(pinfo->cinfo, COL_INFO, "Error: %s", HICP_INVALID_CONFIG);
222
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: %s, Module MAC address: %s", HICP_CONFIG_COMMAND, parameter_value);
223
0
        }
224
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_EXECUTED, (size_t)strlen(HICP_EXECUTED)) == 0) {
225
0
            proto_tree_add_string(hicp_tree, hf_hicp_status, tvb, offset, (int)strlen(parameters[i]), HICP_EXECUTED);
226
0
            proto_tree_add_string(hicp_tree, hf_hicp_src, tvb, offset, (int)strlen(parameters[i]), parameter_value);
227
0
            col_prepend_fstr(pinfo->cinfo, COL_INFO, "Respond message, Command: %s", HICP_WINK_COMMAND);
228
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value);
229
0
        }
230
14
        else if (g_ascii_strncasecmp(parameters[i], HICP_TO, (size_t)strlen(HICP_TO)) == 0) {
231
0
            proto_tree_add_string(hicp_tree, hf_hicp_target, tvb, offset, (int)strlen(parameters[i]), parameter_value);
232
0
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value);
233
0
        }
234
14
        offset += (unsigned)strlen(parameters[i]) + (unsigned)strlen(HICP_DELIMITER);
235
14
    }
236
237
9
    return tvb_captured_length(tvb);
238
9
}
239
240
void
241
proto_register_hicp(void)
242
15
{
243
15
    expert_module_t* expert_hicp;
244
245
15
    static hf_register_info hf[] = {
246
15
        { &hf_hicp_cmd,
247
15
          { "Command", "hicp.cmd",
248
15
            FT_STRINGZ, BASE_NONE,
249
15
            NULL, 0x0,
250
15
            NULL, HFILL }
251
15
        },
252
15
        { &hf_hicp_proto_version,
253
15
          { "Protocol version", "hicp.protoversion",
254
15
            FT_STRINGZ, BASE_NONE,
255
15
            NULL, 0x0,
256
15
            NULL, HFILL }
257
15
        },
258
15
        { &hf_hicp_fb_type,
259
15
          { "Fieldbus type", "hicp.fbtype",
260
15
            FT_STRINGZ, BASE_NONE,
261
15
            NULL, 0x0,
262
15
            NULL, HFILL }
263
15
        },
264
15
        { &hf_hicp_module_version,
265
15
          { "Module version", "hicp.moduleversion",
266
15
            FT_STRINGZ, BASE_NONE,
267
15
            NULL, 0x0,
268
15
            NULL, HFILL }
269
15
        },
270
15
        { &hf_hicp_mac,
271
15
          { "MAC address", "hicp.mac",
272
15
            FT_STRINGZ, BASE_NONE,
273
15
            NULL, 0x0,
274
15
            NULL, HFILL }
275
15
        },
276
15
        { &hf_hicp_ip,
277
15
          { "IP address", "hicp.ip",
278
15
            FT_STRINGZ, BASE_NONE,
279
15
            NULL, 0x0,
280
15
            NULL, HFILL }
281
15
        },
282
15
        { &hf_hicp_sn,
283
15
          { "Subnet mask", "hicp.sn",
284
15
            FT_STRINGZ, BASE_NONE,
285
15
            NULL, 0x0,
286
15
            NULL, HFILL }
287
15
        },
288
15
        { &hf_hicp_gw,
289
15
          { "Gateway address", "hicp.gw",
290
15
            FT_STRINGZ, BASE_NONE,
291
15
            NULL, 0x0,
292
15
            NULL, HFILL }
293
15
        },
294
15
        { &hf_hicp_dhcp,
295
15
          { "DHCP", "hicp.dhcp",
296
15
            FT_STRINGZ, BASE_NONE,
297
15
            NULL, 0x0,
298
15
            NULL, HFILL }
299
15
        },
300
15
        { &hf_hicp_pswd_required,
301
15
          { "Password", "hicp.pswdrequired",
302
15
            FT_STRINGZ, BASE_NONE,
303
15
            NULL, 0x0,
304
15
            NULL, HFILL }
305
15
        },
306
15
        { &hf_hicp_hn,
307
15
          { "Hostname", "hicp.hn",
308
15
            FT_STRINGZ, BASE_NONE,
309
15
            NULL, 0x0,
310
15
            NULL, HFILL }
311
15
        },
312
15
        { &hf_hicp_dns1,
313
15
          { "Primary DNS address", "hicp.dns1",
314
15
            FT_STRINGZ, BASE_NONE,
315
15
            NULL, 0x0,
316
15
            NULL, HFILL }
317
15
        },
318
15
        { &hf_hicp_dns2,
319
15
          { "Secondary DNS", "hicp.dns2",
320
15
            FT_STRINGZ, BASE_NONE,
321
15
            NULL, 0x0,
322
15
            NULL, HFILL }
323
15
        },
324
15
        { &hf_hicp_ext,
325
15
          { "Extended commands supported", "hicp.ext",
326
15
            FT_STRINGZ, BASE_NONE,
327
15
            NULL, 0x0,
328
15
            NULL, HFILL }
329
15
        },
330
15
        { &hf_hicp_pswd,
331
15
          { "Password", "hicp.pswd",
332
15
            FT_STRINGZ, BASE_NONE,
333
15
            NULL, 0x0,
334
15
            NULL, HFILL }
335
15
        },
336
15
        { &hf_hicp_new_pswd,
337
15
          { "New password", "hicp.newpswd",
338
15
            FT_STRINGZ, BASE_NONE,
339
15
            NULL, 0x0,
340
15
            NULL, HFILL }
341
15
        },
342
15
        { &hf_hicp_new_mac,
343
15
          { "New MAC address", "hicp.newmac",
344
15
            FT_STRINGZ, BASE_NONE,
345
15
            NULL, 0x0,
346
15
            NULL, HFILL }
347
15
        },
348
15
        { &hf_hicp_status,
349
15
          { "Status", "hicp.status",
350
15
            FT_STRINGZ, BASE_NONE,
351
15
            NULL, 0x0,
352
15
            NULL, HFILL }
353
15
        },
354
15
        { &hf_hicp_error,
355
15
          { "Error", "hicp.error",
356
15
            FT_STRINGZ, BASE_NONE,
357
15
            NULL, 0x0,
358
15
            NULL, HFILL }
359
15
        },
360
15
        { &hf_hicp_target,
361
15
          { "Target", "hicp.target",
362
15
            FT_STRINGZ, BASE_NONE,
363
15
            NULL, 0x0,
364
15
            NULL, HFILL }
365
15
        },
366
15
        { &hf_hicp_src,
367
15
          { "Source", "hicp.src",
368
15
            FT_STRINGZ, BASE_NONE,
369
15
            NULL, 0x0,
370
15
            NULL, HFILL }
371
15
        }
372
15
    };
373
374
15
    static int *ett[] = {
375
15
        &ett_hicp
376
15
    };
377
378
15
    static ei_register_info ei[] = {
379
15
        { &ei_hicp_error,
380
15
          { "hicp.error.expert", PI_RESPONSE_CODE, PI_NOTE,
381
15
            "Message contains an error message.", EXPFILL }
382
15
        }
383
15
    };
384
385
15
    proto_hicp = proto_register_protocol("Host IP Configuration Protocol", "HICP", "hicp");
386
387
15
    proto_register_field_array(proto_hicp, hf, array_length(hf));
388
15
    proto_register_subtree_array(ett, array_length(ett));
389
390
15
    expert_hicp = expert_register_protocol(proto_hicp);
391
15
    expert_register_field_array(expert_hicp, ei, array_length(ei));
392
393
15
    hicp_handle = register_dissector("hicp", dissect_hicp, proto_hicp);
394
15
}
395
396
void
397
proto_reg_handoff_hicp(void)
398
15
{
399
15
    dissector_add_uint("udp.port", HICP_PORT, hicp_handle);
400
15
}
401
402
/*
403
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
404
 *
405
 * Local variables:
406
 * c-basic-offset: 4
407
 * tab-width: 8
408
 * indent-tabs-mode: nil
409
 * End:
410
 *
411
 * vi: set shiftwidth=4 tabstop=8 expandtab:
412
 * :indentSize=4:tabSize=8:noTabs=true:
413
 */