aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorJörg Mayer <jmayer@loplof.de>2007-03-04 11:48:07 +0000
committerJörg Mayer <jmayer@loplof.de>2007-03-04 11:48:07 +0000
commit379a3e53ec9ca2626b045857e19f92250edf08e0 (patch)
tree25b2da4d76fd50a306db44725a50be7a86cd9c3b /epan
parent4b4d4fed2a81dad9ee0c4ab2c96ffde03a54c676 (diff)
The beginnings of a TAPA dissector (Trapeze Access Point Access Protocol).
Admittedly not much, so if you have any ideas what the rest means or where I'm wrong please provide feedback. As tapa uses udp 5000 and ip protocol 4, I needed to add a hack for the ip part to properly dispatch betweeen ipip and tapa-tunnel (actually I was unable to turn the ipip dissector into a heuristic dissector :-) svn path=/trunk/; revision=20971
Diffstat (limited to 'epan')
-rw-r--r--epan/dissectors/Makefile.common1
-rw-r--r--epan/dissectors/packet-ip.c15
-rw-r--r--epan/dissectors/packet-tapa.c522
3 files changed, 537 insertions, 1 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index e4373e2905..bc181142cb 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -653,6 +653,7 @@ DISSECTOR_SRC = \
packet-t38.c \
packet-tacacs.c \
packet-tali.c \
+ packet-tapa.c \
packet-tcap.c \
packet-tcp.c \
packet-tds.c \
diff --git a/epan/dissectors/packet-ip.c b/epan/dissectors/packet-ip.c
index 203c4a9f3a..8cc390cb5c 100644
--- a/epan/dissectors/packet-ip.c
+++ b/epan/dissectors/packet-ip.c
@@ -153,6 +153,7 @@ static dissector_table_t ip_dissector_table;
static dissector_handle_t ip_handle;
static dissector_handle_t ipv6_handle;
static dissector_handle_t data_handle;
+static dissector_handle_t tapa_handle;
static int proto_icmp = -1;
static int hf_icmp_type = -1;
@@ -1441,6 +1442,17 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
goto end_of_ip;
}
+ /* XXX This is an ugly hack because I didn't manage to make the IPIP
+ * dissector a heuristic one [JMayer]
+ * The TAPA protocol also uses IP protocol number 4 but it isn't really
+ * IPIP, so try to detect it first and call it explicitly before calling
+ * the generic ip.proto dispatcher
+ */
+ if (nxt == IP_PROTO_IPIP &&
+ (tvb_get_guint8(next_tvb, 0) & 0xF0) != 40 &&
+ tvb_get_ntohs(next_tvb, 2) < 20) {
+ call_dissector(tapa_handle,next_tvb, pinfo, parent_tree);
+
/* Hand off to the next protocol.
XXX - setting the columns only after trying various dissectors means
@@ -1448,7 +1460,7 @@ dissect_ip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
even be labelled as an IP frame; ideally, if a frame being dissected
throws an exception, it'll be labelled as a mangled frame of the
type in question. */
- if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, parent_tree)) {
+ } else if (!dissector_try_port(ip_dissector_table, nxt, next_tvb, pinfo, parent_tree)) {
/* Unknown protocol */
if (update_col_info) {
if (check_col(pinfo->cinfo, COL_INFO))
@@ -2434,6 +2446,7 @@ proto_reg_handoff_ip(void)
data_handle = find_dissector("data");
ip_handle = find_dissector("ip");
+ tapa_handle = find_dissector("tapa");
dissector_add("ethertype", ETHERTYPE_IP, ip_handle);
dissector_add("ppp.protocol", PPP_IP, ip_handle);
dissector_add("ppp.protocol", ETHERTYPE_IP, ip_handle);
diff --git a/epan/dissectors/packet-tapa.c b/epan/dissectors/packet-tapa.c
new file mode 100644
index 0000000000..40d35b7297
--- /dev/null
+++ b/epan/dissectors/packet-tapa.c
@@ -0,0 +1,522 @@
+/* packet-3com-tapa.c
+ * Routines for the disassembly of the Trapeze TAPA protocol
+ *
+ * $Id$
+ *
+ * Copyright 2007 Joerg Mayer (see AUTHORS file)
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ TODO:
+
+Specs:
+
+ No specs available.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/emem.h>
+
+/* protocol handles */
+static int proto_tapa = -1;
+
+/* ett handles */
+static int ett_tapa_discover = -1;
+static int ett_tapa_discover_req = -1;
+static int ett_tapa_tunnel = -1;
+
+/* hf elements */
+static int hf_tapa_type = -1;
+static int hf_tapa_flags = -1;
+static int hf_tapa_length = -1;
+static int hf_tapa_unknown = -1;
+
+static int hf_tapa_req_type = -1;
+static int hf_tapa_req_pad = -1;
+static int hf_tapa_req_length = -1;
+static int hf_tapa_req_value = -1;
+
+static int hf_tapa_newtlv_type = -1;
+static int hf_tapa_newtlv_pad = -1;
+static int hf_tapa_newtlv_length = -1;
+static int hf_tapa_newtlv_valuetext = -1;
+static int hf_tapa_newtlv_valuehex = -1;
+
+static int hf_tapa_reply_switchip = -1;
+static int hf_tapa_reply_unused = -1;
+static int hf_tapa_reply_bias = -1;
+static int hf_tapa_reply_pad = -1;
+
+static int hf_tapa_tunnel_version = -1;
+static int hf_tapa_tunnel_remaining = -1;
+
+#define PROTO_SHORT_NAME "TAPA"
+#define PROTO_LONG_NAME "Trapeze Access Point Access Protocol"
+
+#define PORT_TAPA 5000
+
+typedef enum {
+ TAPA_TYPE_REQUEST = 0x01,
+ TAPA_TYPE_REPLY = 0x02,
+ TAPA_TYPE_REQUEST_NEW = 0x04,
+ TAPA_TYPE_REPLY_NEW = 0x05
+} tapa_type_t;
+
+static const value_string tapa_type_vals[] = {
+ { TAPA_TYPE_REQUEST, "Request" },
+ { TAPA_TYPE_REPLY, "Reply" },
+ { TAPA_TYPE_REQUEST_NEW, "NewRequest" },
+ { TAPA_TYPE_REPLY_NEW, "NewReply" },
+
+ { 0, NULL }
+};
+
+typedef enum {
+ TAPA_REQUEST_SERIAL = 0x01,
+ TAPA_REQUEST_MODEL = 0x02
+} tapa_request_t;
+
+static const value_string tapa_request_vals[] = {
+ { TAPA_REQUEST_SERIAL, "SerialNo" },
+ { TAPA_REQUEST_MODEL, "Model" },
+
+ { 0, NULL }
+};
+
+static const value_string tapa_unknown_vals[] = {
+
+ { 0, NULL }
+};
+
+static gboolean
+check_ascii(const guint8 *buffer, gint length)
+{
+ gint i;
+
+ for (i = 0; i < length; i++)
+ if (buffer[i] < 0x20 || buffer[i] >= 0x80)
+ return FALSE;
+ return TRUE;
+}
+
+static int
+dissect_tapa_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tapa_tree, guint32 offset, gint remaining)
+{
+ proto_tree_add_item(tapa_tree, hf_tapa_reply_switchip, tvb, offset, 4,
+ FALSE);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", Switch: %s",
+ ip_to_str(tvb_get_ptr(tvb, offset, 4)));
+
+ offset += 4;
+
+ proto_tree_add_item(tapa_tree, hf_tapa_reply_unused, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tapa_tree, hf_tapa_reply_bias, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ remaining -= 6;
+ proto_tree_add_item(tapa_tree, hf_tapa_reply_pad, tvb, offset, remaining,
+ FALSE);
+ offset += remaining;
+
+ return offset;
+}
+
+static int
+dissect_tapa_req(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tapa_tree, guint32 offset, gint remaining)
+{
+ proto_item *item;
+ proto_tree *tapa_item_tree;
+ guint8 item_type;
+ gint item_length;
+ gchar *item_text;
+ const gchar *item_type_text;
+
+ while (remaining > 0) {
+ item_type = tvb_get_guint8(tvb, offset);
+ item_type_text = val_to_str(item_type, tapa_request_vals, "%d");
+ item_length = tvb_get_ntohs(tvb, offset + 2);
+ item_text = tvb_format_text(tvb, offset + 4, item_length);
+
+ DISSECTOR_ASSERT(item_length > 0);
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s: %s",
+ item_type_text, item_text);
+
+ item = proto_tree_add_text(tapa_tree, tvb, offset, 4 + item_length,
+ "Type %d = %s, length %d, value %s",
+ item_type, item_type_text, item_length, item_text);
+
+ tapa_item_tree = proto_item_add_subtree(item, ett_tapa_discover_req);
+
+ proto_tree_add_item(tapa_item_tree, hf_tapa_req_type, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tapa_item_tree, hf_tapa_req_pad, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tapa_item_tree, hf_tapa_req_length, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+ proto_tree_add_item(tapa_item_tree, hf_tapa_req_value, tvb, offset, item_length,
+ FALSE);
+ offset += item_length;
+
+ remaining -= (item_length + 4);
+ }
+ return offset;
+}
+
+static int
+dissect_tapa_unknown_new_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tapa_tree, guint32 offset, gint remaining)
+{
+ proto_item *item;
+ proto_tree *tapa_item_tree;
+ guint8 item_type;
+ gint item_length;
+ const gchar *item_text;
+ const gchar *item_type_text;
+ gboolean is_ascii;
+
+ while (remaining > 0) {
+ item_type = tvb_get_guint8(tvb, offset);
+ item_type_text = val_to_str(item_type, tapa_unknown_vals, "%d");
+ item_length = tvb_get_ntohs(tvb, offset + 2) - 4;
+
+ DISSECTOR_ASSERT(item_length > 0);
+
+ is_ascii = check_ascii(tvb_get_ptr(tvb, offset + 4, item_length),
+ item_length);
+ if (is_ascii)
+ item_text = tvb_format_text(tvb, offset + 4, item_length);
+ else
+ item_text = "BINARY-DATA";
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", T=%d L=%d",
+ item_type, item_length);
+
+ item = proto_tree_add_text(tapa_tree, tvb, offset, 4 + item_length,
+ "Type %d, length %d, value %s",
+ item_type, item_length, item_text);
+
+ tapa_item_tree = proto_item_add_subtree(item, ett_tapa_discover_req);
+
+ proto_tree_add_item(tapa_item_tree, hf_tapa_newtlv_type, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tapa_item_tree, hf_tapa_newtlv_pad, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tapa_item_tree, hf_tapa_newtlv_length, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ if (is_ascii)
+ proto_tree_add_item(tapa_item_tree, hf_tapa_newtlv_valuetext,
+ tvb, offset, item_length, FALSE);
+ else
+ proto_tree_add_item(tapa_item_tree, hf_tapa_newtlv_valuehex,
+ tvb, offset, item_length, FALSE);
+ offset += item_length;
+
+ remaining -= (item_length + 4);
+ }
+ return offset;
+}
+
+static int
+dissect_tapa_discover(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *tapa_tree = NULL;
+ guint32 offset = 0;
+ guint8 packet_type;
+ guint remaining;
+
+ packet_type = tvb_get_guint8(tvb, 0);
+ remaining = tvb_get_ntohs(tvb, 2) - 4;
+
+ DISSECTOR_ASSERT(remaining > 4);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Discover - %s",
+ val_to_str(packet_type, tapa_type_vals, "Unknown (%d)"));
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_tapa, tvb, offset, -1,
+ FALSE);
+ tapa_tree = proto_item_add_subtree(ti, ett_tapa_discover);
+
+ proto_tree_add_item(tapa_tree, hf_tapa_type, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tapa_tree, hf_tapa_flags, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ proto_tree_add_item(tapa_tree, hf_tapa_length, tvb, offset, 2,
+ FALSE);
+ offset += 2;
+
+ switch (packet_type) {
+ case TAPA_TYPE_REQUEST:
+ offset = dissect_tapa_req(tvb, pinfo, tapa_tree, offset, remaining);
+ break;
+ case TAPA_TYPE_REPLY:
+ offset = dissect_tapa_reply(tvb, pinfo, tapa_tree, offset, remaining);
+ break;
+ case TAPA_TYPE_REQUEST_NEW:
+ case TAPA_TYPE_REPLY_NEW:
+ offset = dissect_tapa_unknown_new_tlv(tvb, pinfo, tapa_tree,
+ offset, remaining);
+ break;
+ default:
+ proto_tree_add_item(tapa_tree, hf_tapa_unknown, tvb, offset,
+ remaining, FALSE);
+ offset += 1;
+
+ break;
+ }
+ }
+ return offset;
+}
+
+static int
+dissect_tapa_tunnel(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ proto_item *ti;
+ proto_tree *tapa_tree = NULL;
+ guint32 offset = 0;
+ guint8 version;
+ guint remaining;
+
+ version = tvb_get_guint8(tvb, 0) & 0xF0;
+ remaining = tvb_reported_length(tvb);
+
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Tunnel");
+ /* col_add_fstr(pinfo->cinfo, COL_INFO, "Tunnel - %s",
+ * val_to_str(packet_type, tapa_type_vals, "Unknown (%d)"));
+ */
+
+ if (tree) {
+ ti = proto_tree_add_item(tree, proto_tapa, tvb, offset, -1,
+ FALSE);
+ tapa_tree = proto_item_add_subtree(ti, ett_tapa_tunnel);
+
+ proto_tree_add_item(tapa_tree, hf_tapa_tunnel_version, tvb, offset, 1,
+ FALSE);
+ offset += 1;
+
+ /* FIXME: This is just to help figuring out what the bytes mean */
+ proto_tree_add_item(tapa_tree, hf_tapa_tunnel_remaining, tvb, 0, remaining,
+ FALSE);
+ offset = remaining;
+
+ }
+ return offset;
+}
+
+static gboolean
+test_tapa_discover(tvbuff_t *tvb)
+{
+ /* Type(1 byte) <= 5, unknown(1 byte), length(2 bytes) */
+ if ( !tvb_bytes_exist(tvb, 0, 4) ||
+ tvb_get_guint8(tvb, 0) > 5 ||
+ tvb_get_guint8(tvb, 1) > 8 ||
+ tvb_get_ntohs(tvb, 2) > 1472) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+test_tapa_tunnel(tvbuff_t *tvb)
+{
+ /* If it isn't IPv4, it's TAPA. IPv4: Version(1 byte) = 4,
+ length(2 bytes) >= 20 */
+ if ( !tvb_bytes_exist(tvb, 0, 4) ||
+ (tvb_get_guint8(tvb, 0) & 0xF0) >= 0x40 ||
+ tvb_get_ntohs(tvb, 2) > 0) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+dissect_tapa_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (test_tapa_discover(tvb)) {
+ dissect_tapa_discover(tvb, pinfo, tree);
+ return TRUE;
+ } else if (test_tapa_tunnel(tvb)) {
+ dissect_tapa_tunnel(tvb, pinfo, tree);
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+static int
+dissect_tapa_static(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ if (test_tapa_discover(tvb)) {
+ return dissect_tapa_discover(tvb, pinfo, tree);
+ } else if (test_tapa_tunnel(tvb)) {
+ return dissect_tapa_tunnel(tvb, pinfo, tree);
+ } else
+ return 0;
+}
+
+void
+proto_register_tapa(void)
+{
+ static hf_register_info hf[] = {
+
+ /* TAPA discover header */
+ { &hf_tapa_type,
+ { "Type", "tapa.type", FT_UINT8, BASE_DEC, VALS(tapa_type_vals),
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_flags,
+ { "Flags", "tapa.flags", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_length,
+ { "Length", "tapa.length", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ /* TAPA discover request */
+ { &hf_tapa_req_type,
+ { "Req type", "tapa.req.type", FT_UINT8, BASE_DEC, VALS(tapa_request_vals),
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_req_pad,
+ { "Req padding", "tapa.req.pad", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_req_length,
+ { "Req length", "tapa.req.length", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_req_value,
+ { "Req value", "tapa.req.value", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+
+ /* TAPA discover reply */
+ { &hf_tapa_reply_switchip,
+ { "Switch Ip", "tapa.reply.switchip", FT_IPv4, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_reply_unused,
+ { "Reply unused ", "tapa.reply.unused", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_reply_bias,
+ { "Reply bias", "tapa.reply.bias", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_reply_pad,
+ { "Reply pad", "tapa.reply.pad", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+
+ /* TAPA discover new request/reply tlv */
+ { &hf_tapa_newtlv_type,
+ { "New tlv type", "tapa.newtlv.type", FT_UINT8, BASE_DEC, VALS(tapa_request_vals),
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_newtlv_pad,
+ { "New tlv padding", "tapa.newtlv.pad", FT_UINT8, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_newtlv_length,
+ { "New tlv length", "tapa.newtlv.length", FT_UINT16, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_newtlv_valuetext,
+ { "New tlv value", "tapa.newtlv.valuetext", FT_STRING, BASE_DEC, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_newtlv_valuehex,
+ { "New tlv value", "tapa.newtlv.valuehex", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+
+ /* TAPA discover unknown packet */
+ { &hf_tapa_unknown,
+ { "Tapa unknown packet", "tapa.unknown", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+
+ /* TAPA tunnel */
+ { &hf_tapa_tunnel_version,
+ { "Tapa tunnel version", "tapa.tunnel.version", FT_UINT8, BASE_HEX, NULL,
+ 0x0, "", HFILL }},
+
+ { &hf_tapa_tunnel_remaining,
+ { "Tapa tunnel all data", "tapa.tunnel.remaining", FT_BYTES, BASE_NONE, NULL,
+ 0x0, "", HFILL }},
+
+ };
+ static gint *ett[] = {
+ &ett_tapa_discover,
+ &ett_tapa_discover_req,
+ &ett_tapa_tunnel,
+ };
+
+ proto_tapa = proto_register_protocol(PROTO_LONG_NAME,
+ PROTO_SHORT_NAME, "tapa");
+ proto_register_field_array(proto_tapa, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+
+ register_dissector("tapa", dissect_tapa_static, proto_tapa);
+
+}
+
+void
+proto_reg_handoff_tapa(void)
+{
+ dissector_handle_t tapa_handle;
+
+ tapa_handle = new_create_dissector_handle(dissect_tapa_static, proto_tapa);
+ dissector_add("udp.port", PORT_TAPA, tapa_handle);
+
+ heur_dissector_add("udp", dissect_tapa_heur, proto_tapa);
+}
+