/* packet-manolito.c * Routines for Blubster/Piolet Manolito Protocol dissection * Copyright 2003-2004, Jeff Connelly * * Official home page: http://openlito.sourceforge.net/ * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include "config.h" #include #include void proto_register_manolito(void); void proto_reg_handoff_manolito(void); /* Initialize the protocol and registered fields */ static int proto_manolito = -1; static int hf_manolito_checksum = -1; static int hf_manolito_seqno = -1; static int hf_manolito_src = -1; static int hf_manolito_dest = -1; static int hf_manolito_options_short = -1; static int hf_manolito_options = -1; static int hf_manolito_string = -1; static int hf_manolito_integer = -1; /* Initialize the subtree pointers */ static gint ett_manolito = -1; static expert_field ei_manolito_type = EI_INIT; /* Code to actually dissect the packets */ static int dissect_manolito(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* dissector_data _U_) { unsigned int offset; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; proto_tree *manolito_tree; const char* packet_type = 0; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "MANOLITO"); ti = proto_tree_add_item(tree, proto_manolito, tvb, 0, -1, ENC_NA); manolito_tree = proto_item_add_subtree(ti, ett_manolito); /* MANOLITO packet header (network byte order) */ proto_tree_add_item(manolito_tree, hf_manolito_checksum, tvb, 0, 4, ENC_BIG_ENDIAN); proto_tree_add_item(manolito_tree, hf_manolito_seqno, tvb, 4, 4, ENC_BIG_ENDIAN); proto_tree_add_item(manolito_tree, hf_manolito_src, tvb, 8, 4, ENC_BIG_ENDIAN); proto_tree_add_item(manolito_tree, hf_manolito_dest, tvb, 12, 4, ENC_BIG_ENDIAN); if (tvb_reported_length(tvb) == 19) { packet_type = "Ping (truncated)"; proto_tree_add_item(manolito_tree, hf_manolito_options_short, tvb, 16, 3, ENC_BIG_ENDIAN); } else { proto_tree_add_item(manolito_tree, hf_manolito_options, tvb, 16, 4, ENC_BIG_ENDIAN); } if (tvb_reported_length(tvb) <= 20) /* no payload, just headers */ { col_set_str(pinfo->cinfo, COL_INFO, "Ping"); } else { offset = 20; /* fields start here */ /* fields format: 2-byte name, optional NULL, 1-byte lenlen, */ /* that many bytes(len or data), for NI,CN,VL is len, more */ /* (that many bytes) data follows; else is raw data. */ do { guint16 field_name; /* 16-bit field name */ guint8 dtype; /* data-type */ guint8 length; /* length */ guint8 *data; /* payload */ int start; /* field starting location */ char field_name_str[3]; /* printable name */ const char *longname; /* human-friendly field name */ start = offset; /* 2-byte field name */ field_name = tvb_get_ntohs(tvb, offset); offset += 2; /* Identify the packet based on existing fields */ /* Maybe using the options fields is a better idea...*/ if (field_name == 0x434b) /* CK */ packet_type = "Search Hit"; if (field_name == 0x4e43) /* NC */ packet_type = "User Information"; if (field_name == 0x464e) /* FN - if only field */ packet_type = "Search Query"; if (field_name == 0x4944) /* ID ?? search by CK? */ packet_type = "Search Query (by hash)"; if (field_name == 0x5054) /* PT */ packet_type = "Download Request"; if (field_name == 0x4d45) /* ME */ packet_type = "Chat"; if (tvb_reported_length(tvb) == 20) /* no fields */ packet_type = "Ping"; /* Find the long name of the field */ switch(field_name) { case 0x5346: longname = "Shared Files"; break; /* SF */ case 0x534b: longname = "Shared Kilobytes"; break; /* SK */ case 0x4e49: longname = "Network ID"; break; /* NI */ case 0x4e43: longname = "Num. Connections"; break; /* NC */ case 0x4356: longname = "Client Version"; break; /* CV */ case 0x564c: longname = "Velocity"; break; /* VL */ case 0x464e: longname = "Filename"; break; /* FN */ case 0x464c: longname = "File Length"; break; /* FL */ case 0x4252: longname = "Bit Rate"; break; /* BR */ case 0x4643: longname = "Frequency"; break; /* FC */ case 0x5354: longname = "???"; break; /* ST */ case 0x534c: longname = "Song Length (s)"; break; /* SL */ case 0x434b: longname = "Checksum"; break; /* CK */ case 0x4e4e: longname = "Nickname"; break; /* NN */ case 0x434e: longname = "Client Name"; break; /* CN */ case 0x5054: longname = "Port"; break; /* PT */ case 0x484e: longname = "???"; break; /* HN */ case 0x4d45: longname = "Message"; break; /* ME */ case 0x4944: longname = "Identification"; break; /* ID */ case 0x4144: longname = "???"; break; /* AD */ default: longname = "unknown"; break; } /* 1-byte data type */ #define MANOLITO_STRING 1 #define MANOLITO_INTEGER 0 dtype = tvb_get_guint8(tvb, offset); length = tvb_get_guint8(tvb, ++offset); /* * Get the payload. * * XXX - is the cast necessary? I think the * "usual arithmetic conversions" should * widen it past 8 bits, so there shouldn't * be an overflow. */ data = (guint8 *)wmem_alloc(wmem_packet_scope(), (guint)length + 1); tvb_memcpy(tvb, data, ++offset, length); offset += length; /* convert the 16-bit integer field name to a string */ /* XXX: changed this to use g_htons */ field_name_str[0] = g_htons(field_name) & 0x00ff; field_name_str[1] = (g_htons(field_name) & 0xff00) >> 8; field_name_str[2] = 0; if (dtype == MANOLITO_STRING) { data[length] = 0; proto_tree_add_string_format(manolito_tree, hf_manolito_string, tvb, start, offset - start, data, "%s (%s): %s", (char*)field_name_str, longname, data); } else if (dtype == MANOLITO_INTEGER) { int n = 0; /* integers can be up to 5 bytes */ switch(length) { case 5: n += data[4] << ((length - 5) * 8); case 4: n += data[3] << ((length - 4) * 8); case 3: n += data[2] << ((length - 3) * 8); case 2: n += data[1] << ((length - 2) * 8); case 1: n += data[0] << ((length - 1) * 8); } ti = proto_tree_add_uint_format(manolito_tree, hf_manolito_integer, tvb, start, 1, n, "%s (%s): %d", (char*)field_name_str, longname, n); proto_item_set_len(ti, offset - start); } else { proto_tree_add_expert_format(manolito_tree, pinfo, &ei_manolito_type, tvb, start, offset - start, "Unknown type %d", dtype); } } while(offset < tvb_reported_length(tvb)); } if (packet_type) { col_set_str(pinfo->cinfo, COL_INFO, packet_type); } return tvb_captured_length(tvb); } /* Register the protocol with Wireshark */ void proto_register_manolito(void) { /* Setup list of header fields See Section 1.6.1 for details*/ static hf_register_info hf[] = { { &hf_manolito_checksum, { "Checksum", "manolito.checksum", FT_UINT32, BASE_HEX, NULL, 0, "Checksum used for verifying integrity", HFILL } }, { &hf_manolito_seqno, { "Sequence Number", "manolito.seqno", FT_UINT32, BASE_HEX, NULL, 0, "Incremental sequence number", HFILL } }, { &hf_manolito_src, { "Forwarded IP Address", "manolito.src", FT_IPv4, BASE_NONE, NULL, 0, "Host packet was forwarded from (or 0)", HFILL } }, { &hf_manolito_dest, { "Destination IP Address","manolito.dest", FT_IPv4, BASE_NONE, NULL, 0, "Destination IPv4 address", HFILL } }, { &hf_manolito_options_short, { "Options", "manolito.options", FT_UINT24, BASE_HEX, NULL, 0, "Packet-dependent data", HFILL } }, { &hf_manolito_options, { "Options", "manolito.options", FT_UINT32, BASE_HEX, NULL, 0, "Packet-dependent data", HFILL } }, { &hf_manolito_string, { "String field", "manolito.string", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } }, { &hf_manolito_integer, { "Integer field", "manolito.integer", FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } }, }; static gint *ett[] = { &ett_manolito, }; static ei_register_info ei[] = { { &ei_manolito_type, { "manolito.type.unknown", PI_PROTOCOL, PI_WARN, "Unknown type", EXPFILL }}, }; expert_module_t* expert_manolito; proto_manolito = proto_register_protocol("Blubster/Piolet MANOLITO Protocol", "Manolito", "manolito"); proto_register_field_array(proto_manolito, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); expert_manolito = expert_register_protocol(proto_manolito); expert_register_field_array(expert_manolito, ei, array_length(ei)); } /* If this dissector uses sub-dissector registration add a registration routine. This format is required because a script is used to find these routines and create the code that calls these routines. */ void proto_reg_handoff_manolito(void) { dissector_handle_t manolito_handle; manolito_handle = create_dissector_handle(dissect_manolito, proto_manolito); dissector_add_uint("udp.port", 41170, manolito_handle); } /* * Editor modelines - http://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 8 * tab-width: 8 * indent-tabs-mode: t * End: * * vi: set shiftwidth=8 tabstop=8 noexpandtab: * :indentSize=8:tabSize=8:noTabs=false: */