2 * Routines for Host IP Configuration Protocol dissection
3 * Copyright 2021, Filip Kågesson <exfik@hms.se>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include <epan/packet.h>
15 #include <epan/expert.h>
16 #include <epan/strutil.h>
18 void proto_reg_handoff_hicp(void);
19 void proto_register_hicp(void);
21 static dissector_handle_t hicp_handle
;
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
;
47 static expert_field ei_hicp_error
;
51 #define HICP_PORT 3250
52 #define HICP_MIN_LENGTH 2
53 #define HICP_DELIMITER ";"
55 /* Values of the supported commands. */
56 #define HICP_MODULE_SCAN_COMMAND "Module scan"
57 #define HICP_CONFIG_COMMAND "Configure"
58 #define HICP_WINK_COMMAND "Wink"
60 /* Values of the supported parameters. */
61 #define HICP_PROTOCOL_VERSION "Protocol version"
62 #define HICP_FB_TYPE "FB type"
63 #define HICP_MODULE_VERSION "Module version"
64 #define HICP_MAC "MAC"
68 #define HICP_DHCP "DHCP"
69 #define HICP_PSWD_REQUIRED "PSWD"
71 #define HICP_DNS1 "DNS1"
72 #define HICP_DNS2 "DNS2"
73 #define HICP_EXT "EXT"
74 #define HICP_PSWD "Password"
75 #define HICP_NEW_PSWD "New Password"
76 #define HICP_NEW_MAC "New MAC"
77 #define HICP_RECONFIGURED "Reconfigured"
78 #define HICP_INVALID_PSWD "Invalid Password"
79 #define HICP_INVALID_CONFIG "Invalid Configuration"
81 #define HICP_EXECUTED "Executed"
84 dissect_hicp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
88 proto_tree
* hicp_tree
;
94 const char* parameters_ptr
= NULL
;
95 char** parameters
= NULL
;
96 char* parameter_value
= NULL
;
98 /* Check that the packet does not start with the header of Secure Host IP Configuration Protocol (SHICP). */
99 if ((tvb_get_uint16(tvb
, offset
, ENC_LITTLE_ENDIAN
) & 0xFFFE) == 0xABC0) {
103 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "HICP");
104 col_clear(pinfo
->cinfo
, COL_INFO
);
106 ti
= proto_tree_add_item(tree
, proto_hicp
, tvb
, offset
, -1, ENC_NA
);
108 hicp_tree
= proto_item_add_subtree(ti
, ett_hicp
);
110 parameters_ptr
= tvb_get_stringz_enc(pinfo
->pool
, tvb
, offset
, &lengthp
, ENC_ASCII
);
111 parameters
= wmem_strsplit(pinfo
->pool
, (const char*)parameters_ptr
, HICP_DELIMITER
, -1);
112 for (unsigned i
= 0; i
< g_strv_length(parameters
); i
++) {
113 if (g_strrstr(parameters
[i
], " = ") != NULL
) {
114 parameter_value
= &(g_strrstr(parameters
[i
], " = "))[3];
116 else if (g_strrstr(parameters
[i
], ": ") != NULL
) {
117 parameter_value
= &(g_strrstr(parameters
[i
], ": "))[2];
120 parameter_value
= "";
122 if (g_ascii_strncasecmp(parameters
[i
], HICP_MODULE_SCAN_COMMAND
, (size_t)strlen(HICP_MODULE_SCAN_COMMAND
)) == 0) {
123 proto_tree_add_string(hicp_tree
, hf_hicp_cmd
, tvb
, offset
, (int)strlen(parameters
[i
]), HICP_MODULE_SCAN_COMMAND
);
124 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "Request message, Command: %s", HICP_MODULE_SCAN_COMMAND
);
126 else if (g_ascii_strncasecmp(parameters
[i
], HICP_CONFIG_COMMAND
, (size_t)strlen(HICP_CONFIG_COMMAND
)) == 0) {
127 proto_tree_add_string(hicp_tree
, hf_hicp_cmd
, tvb
, offset
, (int)strlen(parameters
[i
]), HICP_CONFIG_COMMAND
);
128 proto_tree_add_string(hicp_tree
, hf_hicp_target
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
129 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "Request message, Command: %s", HICP_CONFIG_COMMAND
);
130 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Module MAC address: %s", parameter_value
);
132 else if (g_ascii_strncasecmp(parameters
[i
], HICP_WINK_COMMAND
, (size_t)strlen(HICP_WINK_COMMAND
)) == 0) {
133 proto_tree_add_string(hicp_tree
, hf_hicp_cmd
, tvb
, offset
, (int)strlen(parameters
[i
]), HICP_WINK_COMMAND
);
134 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "Request message, Command: %s", HICP_WINK_COMMAND
);
136 else if (g_ascii_strncasecmp(parameters
[i
], HICP_PROTOCOL_VERSION
, (size_t)strlen(HICP_PROTOCOL_VERSION
)) == 0) {
137 proto_tree_add_string(hicp_tree
, hf_hicp_cmd
, tvb
, offset
, (int)strlen(parameters
[i
]), HICP_MODULE_SCAN_COMMAND
);
138 proto_tree_add_string(hicp_tree
, hf_hicp_proto_version
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
139 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "Response message, Command: %s", HICP_MODULE_SCAN_COMMAND
);
141 else if (g_ascii_strncasecmp(parameters
[i
], HICP_FB_TYPE
, (size_t)strlen(HICP_FB_TYPE
)) == 0) {
142 proto_tree_add_string(hicp_tree
, hf_hicp_fb_type
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
144 else if (g_ascii_strncasecmp(parameters
[i
], HICP_MODULE_VERSION
, (size_t)strlen(HICP_MODULE_VERSION
)) == 0) {
145 proto_tree_add_string(hicp_tree
, hf_hicp_module_version
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
147 else if (g_ascii_strncasecmp(parameters
[i
], HICP_MAC
, (size_t)strlen(HICP_MAC
)) == 0) {
148 proto_tree_add_string(hicp_tree
, hf_hicp_mac
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
149 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Module MAC address: %s", parameter_value
);
151 else if (g_ascii_strncasecmp(parameters
[i
], HICP_IP
, (size_t)strlen(HICP_IP
)) == 0) {
152 proto_tree_add_string(hicp_tree
, hf_hicp_ip
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
154 else if (g_ascii_strncasecmp(parameters
[i
], HICP_SN
, (size_t)strlen(HICP_SN
)) == 0) {
155 proto_tree_add_string(hicp_tree
, hf_hicp_sn
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
157 else if (g_ascii_strncasecmp(parameters
[i
], HICP_GW
, (size_t)strlen(HICP_GW
)) == 0) {
158 proto_tree_add_string(hicp_tree
, hf_hicp_gw
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
160 else if (g_ascii_strncasecmp(parameters
[i
], HICP_DHCP
, (size_t)strlen(HICP_DHCP
)) == 0) {
161 proto_tree_add_string(hicp_tree
,
165 (int)strlen(parameters
[i
]),
166 g_ascii_strcasecmp(parameter_value
, "ON") == 0 ? "Enabled" : "Disabled");
168 else if (g_ascii_strncasecmp(parameters
[i
], HICP_PSWD_REQUIRED
, (size_t)strlen(HICP_PSWD_REQUIRED
)) == 0) {
169 proto_tree_add_string(hicp_tree
,
170 hf_hicp_pswd_required
,
173 (int)strlen(parameters
[i
]),
174 g_ascii_strcasecmp(parameter_value
, "ON") == 0 ? "Required" : "Not required");
176 else if (g_ascii_strncasecmp(parameters
[i
], HICP_HN
, (size_t)strlen(HICP_HN
)) == 0) {
177 proto_tree_add_string(hicp_tree
, hf_hicp_hn
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
179 else if (g_ascii_strncasecmp(parameters
[i
], HICP_DNS1
, (size_t)strlen(HICP_DNS1
)) == 0) {
180 proto_tree_add_string(hicp_tree
, hf_hicp_dns1
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
182 else if (g_ascii_strncasecmp(parameters
[i
], HICP_DNS2
, (size_t)strlen(HICP_DNS2
)) == 0) {
183 proto_tree_add_string(hicp_tree
, hf_hicp_dns2
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
185 else if (g_ascii_strncasecmp(parameters
[i
], HICP_EXT
, (size_t)strlen(HICP_EXT
)) == 0) {
186 ext_value
= g_ascii_strtod(parameter_value
, NULL
);
187 if (ext_value
== 1) {
188 parameter_value
= HICP_WINK_COMMAND
;
190 else if (ext_value
== 0) {
191 parameter_value
= "None";
193 proto_tree_add_string(hicp_tree
, hf_hicp_ext
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
195 else if (g_ascii_strncasecmp(parameters
[i
], HICP_PSWD
, (size_t)strlen(HICP_PSWD
)) == 0) {
196 proto_tree_add_string(hicp_tree
, hf_hicp_pswd
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
198 else if (g_ascii_strncasecmp(parameters
[i
], HICP_NEW_PSWD
, (size_t)strlen(HICP_NEW_PSWD
)) == 0) {
199 proto_tree_add_string(hicp_tree
, hf_hicp_new_pswd
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
201 else if (g_ascii_strncasecmp(parameters
[i
], HICP_NEW_MAC
, (size_t)strlen(HICP_NEW_MAC
)) == 0) {
202 proto_tree_add_string(hicp_tree
, hf_hicp_new_mac
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
204 else if (g_ascii_strncasecmp(parameters
[i
], HICP_RECONFIGURED
, (size_t)strlen(HICP_RECONFIGURED
)) == 0) {
205 proto_tree_add_string(hicp_tree
, hf_hicp_status
, tvb
, offset
, (int)strlen(parameters
[i
]), HICP_RECONFIGURED
);
206 proto_tree_add_string(hicp_tree
, hf_hicp_src
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
207 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "Respond message, Command: %s", HICP_CONFIG_COMMAND
);
208 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Module MAC address: %s", parameter_value
);
210 else if (g_ascii_strncasecmp(parameters
[i
], HICP_INVALID_PSWD
, (size_t)strlen(HICP_INVALID_PSWD
)) == 0) {
211 proto_tree_add_string(hicp_tree
, hf_hicp_src
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
212 error_pi
= proto_tree_add_string(hicp_tree
, hf_hicp_error
, tvb
, offset
, (int)strlen(parameters
[i
]), HICP_INVALID_PSWD
);
213 expert_add_info(pinfo
, error_pi
, &ei_hicp_error
);
214 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "Error: %s", HICP_INVALID_PSWD
);
215 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Command: %s, Module MAC address: %s", HICP_CONFIG_COMMAND
, parameter_value
);
217 else if (g_ascii_strncasecmp(parameters
[i
], HICP_INVALID_CONFIG
, (size_t)strlen(HICP_INVALID_CONFIG
)) == 0) {
218 proto_tree_add_string(hicp_tree
, hf_hicp_src
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
219 error_pi
= proto_tree_add_string(hicp_tree
, hf_hicp_error
, tvb
, offset
, (int)strlen(parameters
[i
]), HICP_INVALID_CONFIG
);
220 expert_add_info(pinfo
, error_pi
, &ei_hicp_error
);
221 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "Error: %s", HICP_INVALID_CONFIG
);
222 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Command: %s, Module MAC address: %s", HICP_CONFIG_COMMAND
, parameter_value
);
224 else if (g_ascii_strncasecmp(parameters
[i
], HICP_EXECUTED
, (size_t)strlen(HICP_EXECUTED
)) == 0) {
225 proto_tree_add_string(hicp_tree
, hf_hicp_status
, tvb
, offset
, (int)strlen(parameters
[i
]), HICP_EXECUTED
);
226 proto_tree_add_string(hicp_tree
, hf_hicp_src
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
227 col_prepend_fstr(pinfo
->cinfo
, COL_INFO
, "Respond message, Command: %s", HICP_WINK_COMMAND
);
228 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Module MAC address: %s", parameter_value
);
230 else if (g_ascii_strncasecmp(parameters
[i
], HICP_TO
, (size_t)strlen(HICP_TO
)) == 0) {
231 proto_tree_add_string(hicp_tree
, hf_hicp_target
, tvb
, offset
, (int)strlen(parameters
[i
]), parameter_value
);
232 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", Module MAC address: %s", parameter_value
);
234 offset
+= (unsigned)strlen(parameters
[i
]) + (unsigned)strlen(HICP_DELIMITER
);
237 return tvb_captured_length(tvb
);
241 proto_register_hicp(void)
243 expert_module_t
* expert_hicp
;
245 static hf_register_info hf
[] = {
247 { "Command", "hicp.cmd",
248 FT_STRINGZ
, BASE_NONE
,
252 { &hf_hicp_proto_version
,
253 { "Protocol version", "hicp.protoversion",
254 FT_STRINGZ
, BASE_NONE
,
259 { "Fieldbus type", "hicp.fbtype",
260 FT_STRINGZ
, BASE_NONE
,
264 { &hf_hicp_module_version
,
265 { "Module version", "hicp.moduleversion",
266 FT_STRINGZ
, BASE_NONE
,
271 { "MAC address", "hicp.mac",
272 FT_STRINGZ
, BASE_NONE
,
277 { "IP address", "hicp.ip",
278 FT_STRINGZ
, BASE_NONE
,
283 { "Subnet mask", "hicp.sn",
284 FT_STRINGZ
, BASE_NONE
,
289 { "Gateway address", "hicp.gw",
290 FT_STRINGZ
, BASE_NONE
,
295 { "DHCP", "hicp.dhcp",
296 FT_STRINGZ
, BASE_NONE
,
300 { &hf_hicp_pswd_required
,
301 { "Password", "hicp.pswdrequired",
302 FT_STRINGZ
, BASE_NONE
,
307 { "Hostname", "hicp.hn",
308 FT_STRINGZ
, BASE_NONE
,
313 { "Primary DNS address", "hicp.dns1",
314 FT_STRINGZ
, BASE_NONE
,
319 { "Secondary DNS", "hicp.dns2",
320 FT_STRINGZ
, BASE_NONE
,
325 { "Extended commands supported", "hicp.ext",
326 FT_STRINGZ
, BASE_NONE
,
331 { "Password", "hicp.pswd",
332 FT_STRINGZ
, BASE_NONE
,
337 { "New password", "hicp.newpswd",
338 FT_STRINGZ
, BASE_NONE
,
343 { "New MAC address", "hicp.newmac",
344 FT_STRINGZ
, BASE_NONE
,
349 { "Status", "hicp.status",
350 FT_STRINGZ
, BASE_NONE
,
355 { "Error", "hicp.error",
356 FT_STRINGZ
, BASE_NONE
,
361 { "Target", "hicp.target",
362 FT_STRINGZ
, BASE_NONE
,
367 { "Source", "hicp.src",
368 FT_STRINGZ
, BASE_NONE
,
374 static int *ett
[] = {
378 static ei_register_info ei
[] = {
380 { "hicp.error", PI_RESPONSE_CODE
, PI_NOTE
,
381 "Message contains an error message.", EXPFILL
}
385 proto_hicp
= proto_register_protocol("Host IP Configuration Protocol", "HICP", "hicp");
387 proto_register_field_array(proto_hicp
, hf
, array_length(hf
));
388 proto_register_subtree_array(ett
, array_length(ett
));
390 expert_hicp
= expert_register_protocol(proto_hicp
);
391 expert_register_field_array(expert_hicp
, ei
, array_length(ei
));
393 hicp_handle
= register_dissector("hicp", dissect_hicp
, proto_hicp
);
397 proto_reg_handoff_hicp(void)
399 dissector_add_uint("udp.port", HICP_PORT
, hicp_handle
);
403 * Editor modelines - https://www.wireshark.org/tools/modelines.html
408 * indent-tabs-mode: nil
411 * vi: set shiftwidth=4 tabstop=8 expandtab:
412 * :indentSize=4:tabSize=8:noTabs=true: