/* packet-hicp.c * Routines for Host IP Configuration Protocol dissection * Copyright 2021, Filip Kågesson * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include void proto_reg_handoff_hicp(void); void proto_register_hicp(void); static dissector_handle_t hicp_handle; /* Protocols and header fields. */ static int proto_hicp = -1; static int hf_hicp_cmd = -1; static int hf_hicp_proto_version = -1; static int hf_hicp_fb_type = -1; static int hf_hicp_module_version = -1; static int hf_hicp_mac = -1; static int hf_hicp_ip = -1; static int hf_hicp_sn = -1; static int hf_hicp_gw = -1; static int hf_hicp_dhcp = -1; static int hf_hicp_pswd_required = -1; static int hf_hicp_hn = -1; static int hf_hicp_dns1 = -1; static int hf_hicp_dns2 = -1; static int hf_hicp_ext = -1; static int hf_hicp_pswd = -1; static int hf_hicp_new_pswd = -1; static int hf_hicp_new_mac = -1; static int hf_hicp_status = -1; static int hf_hicp_error = -1; static int hf_hicp_target = -1; static int hf_hicp_src = -1; static expert_field ei_hicp_error = EI_INIT; static gint ett_hicp = -1; #define HICP_PORT 3250 #define HICP_MIN_LENGTH 2 #define HICP_DELIMITER ";" /* Values of the supported commands. */ #define HICP_MODULE_SCAN_COMMAND "Module scan" #define HICP_CONFIG_COMMAND "Configure" #define HICP_WINK_COMMAND "Wink" /* Values of the supported parameters. */ #define HICP_PROTOCOL_VERSION "Protocol version" #define HICP_FB_TYPE "FB type" #define HICP_MODULE_VERSION "Module version" #define HICP_MAC "MAC" #define HICP_IP "IP" #define HICP_SN "SN" #define HICP_GW "GW" #define HICP_DHCP "DHCP" #define HICP_PSWD_REQUIRED "PSWD" #define HICP_HN "HN" #define HICP_DNS1 "DNS1" #define HICP_DNS2 "DNS2" #define HICP_EXT "EXT" #define HICP_PSWD "Password" #define HICP_NEW_PSWD "New Password" #define HICP_NEW_MAC "New MAC" #define HICP_RECONFIGURED "Reconfigured" #define HICP_INVALID_PSWD "Invalid Password" #define HICP_INVALID_CONFIG "Invalid Configuration" #define HICP_TO "To" #define HICP_EXECUTED "Executed" static int dissect_hicp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { proto_item* ti; proto_item* error_pi; proto_tree* hicp_tree; guint offset = 0; gint lengthp = 0; gdouble ext_value = 0; const char* parameters_ptr = NULL; gchar** parameters = NULL; gchar* parameter_value = NULL; /* Check that the packet does not start with the header of Secure Host IP Configuration Protocol (SHICP). */ if ((tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN) & 0xFFFE) == 0xABC0) { return 0; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "HICP"); col_clear(pinfo->cinfo, COL_INFO); ti = proto_tree_add_item(tree, proto_hicp, tvb, offset, -1, ENC_NA); hicp_tree = proto_item_add_subtree(ti, ett_hicp); parameters_ptr = tvb_get_stringz_enc(pinfo->pool, tvb, offset, &lengthp, ENC_ASCII); parameters = wmem_strsplit(pinfo->pool, (const gchar*)parameters_ptr, HICP_DELIMITER, -1); for (guint i = 0; i < g_strv_length(parameters); i++) { if (g_strrstr(parameters[i], " = ") != NULL) { parameter_value = &(g_strrstr(parameters[i], " = "))[3]; } else if (g_strrstr(parameters[i], ": ") != NULL) { parameter_value = &(g_strrstr(parameters[i], ": "))[2]; } else { parameter_value = ""; } if (g_ascii_strncasecmp(parameters[i], HICP_MODULE_SCAN_COMMAND, (gsize)strlen(HICP_MODULE_SCAN_COMMAND)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_cmd, tvb, offset, (gint)strlen(parameters[i]), HICP_MODULE_SCAN_COMMAND); col_prepend_fstr(pinfo->cinfo, COL_INFO, "Request message, Command: %s", HICP_MODULE_SCAN_COMMAND); } else if (g_ascii_strncasecmp(parameters[i], HICP_CONFIG_COMMAND, (gsize)strlen(HICP_CONFIG_COMMAND)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_cmd, tvb, offset, (gint)strlen(parameters[i]), HICP_CONFIG_COMMAND); proto_tree_add_string(hicp_tree, hf_hicp_target, tvb, offset, (gint)strlen(parameters[i]), parameter_value); col_prepend_fstr(pinfo->cinfo, COL_INFO, "Request message, Command: %s", HICP_CONFIG_COMMAND); col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_WINK_COMMAND, (gsize)strlen(HICP_WINK_COMMAND)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_cmd, tvb, offset, (gint)strlen(parameters[i]), HICP_WINK_COMMAND); col_prepend_fstr(pinfo->cinfo, COL_INFO, "Request message, Command: %s", HICP_WINK_COMMAND); } else if (g_ascii_strncasecmp(parameters[i], HICP_PROTOCOL_VERSION, (gsize)strlen(HICP_PROTOCOL_VERSION)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_cmd, tvb, offset, (gint)strlen(parameters[i]), HICP_MODULE_SCAN_COMMAND); proto_tree_add_string(hicp_tree, hf_hicp_proto_version, tvb, offset, (gint)strlen(parameters[i]), parameter_value); col_prepend_fstr(pinfo->cinfo, COL_INFO, "Response message, Command: %s", HICP_MODULE_SCAN_COMMAND); } else if (g_ascii_strncasecmp(parameters[i], HICP_FB_TYPE, (gsize)strlen(HICP_FB_TYPE)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_fb_type, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_MODULE_VERSION, (gsize)strlen(HICP_MODULE_VERSION)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_module_version, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_MAC, (gsize)strlen(HICP_MAC)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_mac, tvb, offset, (gint)strlen(parameters[i]), parameter_value); col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_IP, (gsize)strlen(HICP_IP)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_ip, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_SN, (gsize)strlen(HICP_SN)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_sn, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_GW, (gsize)strlen(HICP_GW)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_gw, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_DHCP, (gsize)strlen(HICP_DHCP)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_dhcp, tvb, offset, (gint)strlen(parameters[i]), g_ascii_strcasecmp(parameter_value, "ON") == 0 ? "Enabled" : "Disabled"); } else if (g_ascii_strncasecmp(parameters[i], HICP_PSWD_REQUIRED, (gsize)strlen(HICP_PSWD_REQUIRED)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_pswd_required, tvb, offset, (gint)strlen(parameters[i]), g_ascii_strcasecmp(parameter_value, "ON") == 0 ? "Required" : "Not required"); } else if (g_ascii_strncasecmp(parameters[i], HICP_HN, (gsize)strlen(HICP_HN)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_hn, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_DNS1, (gsize)strlen(HICP_DNS1)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_dns1, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_DNS2, (gsize)strlen(HICP_DNS2)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_dns2, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_EXT, (gsize)strlen(HICP_EXT)) == 0) { ext_value = g_ascii_strtod(parameter_value, NULL); if (ext_value == 1) { parameter_value = HICP_WINK_COMMAND; } else if (ext_value == 0) { parameter_value = "None"; } proto_tree_add_string(hicp_tree, hf_hicp_ext, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_PSWD, (gsize)strlen(HICP_PSWD)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_pswd, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_NEW_PSWD, (gsize)strlen(HICP_NEW_PSWD)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_new_pswd, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_NEW_MAC, (gsize)strlen(HICP_NEW_MAC)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_new_mac, tvb, offset, (gint)strlen(parameters[i]), parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_RECONFIGURED, (gsize)strlen(HICP_RECONFIGURED)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_status, tvb, offset, (gint)strlen(parameters[i]), HICP_RECONFIGURED); proto_tree_add_string(hicp_tree, hf_hicp_src, tvb, offset, (gint)strlen(parameters[i]), parameter_value); col_prepend_fstr(pinfo->cinfo, COL_INFO, "Respond message, Command: %s", HICP_CONFIG_COMMAND); col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_INVALID_PSWD, (gsize)strlen(HICP_INVALID_PSWD)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_src, tvb, offset, (gint)strlen(parameters[i]), parameter_value); error_pi = proto_tree_add_string(hicp_tree, hf_hicp_error, tvb, offset, (gint)strlen(parameters[i]), HICP_INVALID_PSWD); expert_add_info(pinfo, error_pi, &ei_hicp_error); col_prepend_fstr(pinfo->cinfo, COL_INFO, "Error: %s", HICP_INVALID_PSWD); col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: %s, Module MAC address: %s", HICP_CONFIG_COMMAND, parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_INVALID_CONFIG, (gsize)strlen(HICP_INVALID_CONFIG)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_src, tvb, offset, (gint)strlen(parameters[i]), parameter_value); error_pi = proto_tree_add_string(hicp_tree, hf_hicp_error, tvb, offset, (gint)strlen(parameters[i]), HICP_INVALID_CONFIG); expert_add_info(pinfo, error_pi, &ei_hicp_error); col_prepend_fstr(pinfo->cinfo, COL_INFO, "Error: %s", HICP_INVALID_CONFIG); col_append_fstr(pinfo->cinfo, COL_INFO, ", Command: %s, Module MAC address: %s", HICP_CONFIG_COMMAND, parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_EXECUTED, (gsize)strlen(HICP_EXECUTED)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_status, tvb, offset, (gint)strlen(parameters[i]), HICP_EXECUTED); proto_tree_add_string(hicp_tree, hf_hicp_src, tvb, offset, (gint)strlen(parameters[i]), parameter_value); col_prepend_fstr(pinfo->cinfo, COL_INFO, "Respond message, Command: %s", HICP_WINK_COMMAND); col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value); } else if (g_ascii_strncasecmp(parameters[i], HICP_TO, (gsize)strlen(HICP_TO)) == 0) { proto_tree_add_string(hicp_tree, hf_hicp_target, tvb, offset, (gint)strlen(parameters[i]), parameter_value); col_append_fstr(pinfo->cinfo, COL_INFO, ", Module MAC address: %s", parameter_value); } offset += (guint)strlen(parameters[i]) + (guint)strlen(HICP_DELIMITER); } return tvb_captured_length(tvb); } void proto_register_hicp(void) { expert_module_t* expert_hicp; static hf_register_info hf[] = { { &hf_hicp_cmd, { "Command", "hicp.cmd", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_proto_version, { "Protocol version", "hicp.protoversion", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_fb_type, { "Fieldbus type", "hicp.fbtype", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_module_version, { "Module version", "hicp.moduleversion", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_mac, { "MAC address", "hicp.mac", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_ip, { "IP address", "hicp.ip", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_sn, { "Subnet mask", "hicp.sn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_gw, { "Gateway address", "hicp.gw", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_dhcp, { "DHCP", "hicp.dhcp", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_pswd_required, { "Password", "hicp.pswdrequired", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_hn, { "Hostname", "hicp.hn", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_dns1, { "Primary DNS address", "hicp.dns1", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_dns2, { "Secondary DNS", "hicp.dns2", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_ext, { "Extended commands supported", "hicp.ext", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_pswd, { "Password", "hicp.pswd", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_new_pswd, { "New password", "hicp.newpswd", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_new_mac, { "New MAC address", "hicp.newmac", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_status, { "Status", "hicp.status", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_error, { "Error", "hicp.error", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_target, { "Target", "hicp.target", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } }, { &hf_hicp_src, { "Source", "hicp.src", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } } }; static gint *ett[] = { &ett_hicp }; static ei_register_info ei[] = { { &ei_hicp_error, { "hicp.error", PI_RESPONSE_CODE, PI_NOTE, "Message contains an error message.", EXPFILL } } }; proto_hicp = proto_register_protocol("Host IP Configuration Protocol", "HICP", "hicp"); proto_register_field_array(proto_hicp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); expert_hicp = expert_register_protocol(proto_hicp); expert_register_field_array(expert_hicp, ei, array_length(ei)); hicp_handle = register_dissector("hicp", dissect_hicp, proto_hicp); } void proto_reg_handoff_hicp(void) { dissector_add_uint("udp.port", HICP_PORT, hicp_handle); } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */