From Ishraq Ibne Ashraf: Tinkerforge protocol dissector
authorBill Meier <wmeier@newsguy.com>
Mon, 28 Oct 2013 20:07:58 +0000 (20:07 -0000)
committerBill Meier <wmeier@newsguy.com>
Mon, 28 Oct 2013 20:07:58 +0000 (20:07 -0000)
See: https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9324

From me:

1. Move certain global vars to local storage in dissect_tfp_common()

2. Declare all remaining global vars as static;

3. Fix some bugs:
    - base58_encode() needed to be called before call to col_add_fstr()
    - display of UID string in tree was being truncated to 4 characters

4. Cleanup whitespace: use consistent indentation (tabs); remove trailing whitespace;

5. Add editor modelines

svn path=/trunk/; revision=52931

AUTHORS
epan/CMakeLists.txt
epan/dissectors/Makefile.common
epan/dissectors/packet-tfp.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index f98dda7bc36bed61b1d0b48234fbb8cc3fdb5e9b..a2767767c442de65ee3e16fb081098354435ab25 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3533,6 +3533,10 @@ Allan W. Nielsen <anielsen[AT]vitesse.com> {
        Support for MACSEC ethertype/dissector
 }
 
+Ishraq Ibne Ashraf     <ishraq[AT]tinkerforge.com> {
+       tfp (Tinkerforge) dissector
+}
+
 
 and by:
 
index cf589c6bbde97448991ee562af23822bba13ede3..697666ff1ea9cc84c97a6d1bddc58944c811936c 100644 (file)
@@ -1200,6 +1200,7 @@ set(DISSECTOR_SRC
        dissectors/packet-telnet.c
        dissectors/packet-teredo.c
        dissectors/packet-text-media.c
+       dissectors/packet-tfp.c
        dissectors/packet-tftp.c
        dissectors/packet-time.c
        dissectors/packet-tipc.c
index 3cfa89feb223901774d7771ca9f9e8b146b37e68..c8c6ba5cb4d7c7d9f1ebf7a9aa11e50a0b0dbbe6 100644 (file)
@@ -1127,6 +1127,7 @@ DISSECTOR_SRC = \
        packet-telnet.c         \
        packet-teredo.c         \
        packet-text-media.c     \
+       packet-tfp.c            \
        packet-tftp.c           \
        packet-time.c           \
        packet-tipc.c           \
diff --git a/epan/dissectors/packet-tfp.c b/epan/dissectors/packet-tfp.c
new file mode 100644 (file)
index 0000000..fa8c00a
--- /dev/null
@@ -0,0 +1,443 @@
+/* packet-tfp.c
+ * Routines for Tinkerforge protocol packet disassembly
+ * By Ishraq Ibne Ashraf <ishraq@tinkerforge.com>
+ * Copyright 2013 Ishraq Ibne Ashraf
+ *
+ * $Id$
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/dissectors/packet-usb.h>
+
+/* defines */
+#define tfp_PORT 4223
+
+#define tfp_USB_VENDOR_ID  0x16D0
+#define tfp_USB_PRODUCT_ID 0x063D
+
+#define BASE58_MAX_STR_SIZE 13
+
+/* variables for creating the tree */
+static gint proto_tfp = -1;
+static gint ett_tfp = -1;
+
+/* header field variables */
+static gint hf_tfp_uid = -1;
+static gint hf_tfp_uid_numeric = -1;
+static gint hf_tfp_len = -1;
+static gint hf_tfp_fid = -1;
+static gint hf_tfp_seq = -1;
+static gint hf_tfp_r = -1;
+static gint hf_tfp_a = -1;
+static gint hf_tfp_oo = -1;
+static gint hf_tfp_e = -1;
+static gint hf_tfp_future_use = -1;
+static gint hf_tfp_payload = -1;
+
+/* bit and byte offsets for dissection */
+static const gint byte_offset_len         = 4;
+static const gint byte_offset_fid         = 5;
+static const gint byte_count_tfp_uid      = 4;
+static const gint byte_count_tfp_len      = 1;
+static const gint byte_count_tfp_fid      = 1;
+static const gint byte_count_tfp_flags    = 2;
+static const gint bit_count_tfp_seq       = 4;
+static const gint bit_count_tfp_r         = 1;
+static const gint bit_count_tfp_a         = 1;
+static const gint bit_count_tfp_oo        = 2;
+static const gint bit_count_tfp_e         = 2;
+static const gint bit_count_tfp_future_use = 6;
+
+/* base58 encoding variable */
+static const char BASE58_ALPHABET[] =
+       "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
+
+/* function for encoding a number to base58 string */
+static void
+base58_encode(guint32 value, char *str) {
+
+       guint32 mod;
+       gint    i = 0;
+       gint    k;
+       gchar   reverse_str[BASE58_MAX_STR_SIZE] = {'\0'};
+
+       while (value >= 58) {
+               mod = value % 58;
+               reverse_str[i] = BASE58_ALPHABET[mod];
+               value = value / 58;
+               ++i;
+       }
+
+       reverse_str[i] = BASE58_ALPHABET[value];
+
+       for (k = 0; k <= i; k++) {
+               str[k] = reverse_str[i - k];
+       }
+
+       for (; k < BASE58_MAX_STR_SIZE; k++) {
+               str[k] = '\0';
+       }
+}
+
+/* common dissector function for dissecting TFP payloads */
+static void
+dissect_tfp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
+
+       gint   byte_offset = 0;
+       gint   bit_offset  = 48;
+
+       guint8 hv_tfp_len;
+       guint8 hv_tfp_fid;
+       guint8 hv_tfp_seq;
+
+       gchar  tfp_uid_string[BASE58_MAX_STR_SIZE];
+
+       base58_encode(tvb_get_letohl(tvb, 0), &tfp_uid_string[0]);
+
+       hv_tfp_len = tvb_get_guint8(tvb, byte_offset_len);
+       hv_tfp_fid = tvb_get_guint8(tvb, byte_offset_fid);
+       hv_tfp_seq = tvb_get_bits8(tvb, bit_offset, bit_count_tfp_seq);
+
+       col_add_fstr(pinfo->cinfo, COL_INFO,
+                       "UID: %s, Len: %d, FID: %d, Seq: %d",
+                       &tfp_uid_string[0], hv_tfp_len, hv_tfp_fid, hv_tfp_seq);
+
+       /* call for details */
+       if (tree) {
+               proto_tree *tfp_tree;
+               proto_item *ti;
+
+               ti = proto_tree_add_protocol_format(tree, proto_tfp, tvb, 0, -1,
+                                                   "Tinkerforge Protocol, UID: %s, Len: %d, FID: %d, Seq: %d",
+                                                   &tfp_uid_string[0], hv_tfp_len, hv_tfp_fid, hv_tfp_seq);
+               tfp_tree = proto_item_add_subtree(ti, ett_tfp);
+
+               /* Use ...string_format_value() so we can show the complete generated string but specify */
+               /*  the field length as being just the 4 bytes from which the string is generated.       */
+               ti = proto_tree_add_string_format_value(tfp_tree,
+                                                       hf_tfp_uid,
+                                                       tvb, byte_offset, byte_count_tfp_uid,
+                                                       &tfp_uid_string[0], "%s", &tfp_uid_string[0]);
+               PROTO_ITEM_SET_GENERATED(ti);
+
+               proto_tree_add_item(tfp_tree,
+                                   hf_tfp_uid_numeric,
+                                   tvb,
+                                   byte_offset,
+                                   byte_count_tfp_uid,
+                                   ENC_LITTLE_ENDIAN);
+
+               byte_offset += byte_count_tfp_uid;
+
+               proto_tree_add_item(tfp_tree,
+                                   hf_tfp_len,
+                                   tvb,
+                                   byte_offset,
+                                   byte_count_tfp_len,
+                                   ENC_LITTLE_ENDIAN);
+
+               byte_offset += byte_count_tfp_len;
+
+               proto_tree_add_item(tfp_tree,
+                                   hf_tfp_fid,
+                                   tvb,
+                                   byte_offset,
+                                   byte_count_tfp_fid,
+                                   ENC_LITTLE_ENDIAN);
+
+               byte_offset += byte_count_tfp_fid;
+
+               proto_tree_add_bits_item(tfp_tree,
+                                        hf_tfp_seq,
+                                        tvb,
+                                        bit_offset,
+                                        bit_count_tfp_seq,
+                                        ENC_LITTLE_ENDIAN);
+
+               bit_offset += bit_count_tfp_seq;
+
+               proto_tree_add_bits_item(tfp_tree,
+                                        hf_tfp_r,
+                                        tvb,
+                                        bit_offset,
+                                        bit_count_tfp_r,
+                                        ENC_LITTLE_ENDIAN);
+
+               bit_offset += bit_count_tfp_r;
+
+               proto_tree_add_bits_item(tfp_tree,
+                                        hf_tfp_a,
+                                        tvb,
+                                        bit_offset,
+                                        bit_count_tfp_a,
+                                        ENC_LITTLE_ENDIAN);
+
+               bit_offset += bit_count_tfp_a;
+
+               proto_tree_add_bits_item(tfp_tree,
+                                        hf_tfp_oo,
+                                        tvb,
+                                        bit_offset,
+                                        bit_count_tfp_oo,
+                                        ENC_LITTLE_ENDIAN);
+
+               bit_offset += bit_count_tfp_oo;
+
+               proto_tree_add_bits_item(tfp_tree,
+                                        hf_tfp_e,
+                                        tvb,
+                                        bit_offset,
+                                        bit_count_tfp_e,
+                                        ENC_LITTLE_ENDIAN);
+
+               bit_offset += bit_count_tfp_e;
+
+               proto_tree_add_bits_item(tfp_tree,
+                                        hf_tfp_future_use,
+                                        tvb,
+                                        bit_offset,
+                                        bit_count_tfp_future_use,
+                                        ENC_LITTLE_ENDIAN);
+
+               bit_offset += bit_count_tfp_future_use;
+
+               if ((tvb_reported_length(tvb)) > 8) {
+
+                       byte_offset += byte_count_tfp_flags;
+
+                       proto_tree_add_item(tfp_tree,
+                                           hf_tfp_payload,
+                                           tvb,
+                                           byte_offset,
+                                           -1,
+                                           ENC_NA);
+               }
+       }
+}
+
+/* dissector function for dissecting TCP payloads */
+static void
+dissect_tfp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFP over TCP");
+       col_clear(pinfo->cinfo, COL_INFO);
+
+       dissect_tfp_common(tvb, pinfo, tree);
+}
+
+/* dissector function for dissecting USB payloads */
+static void
+dissect_tfp_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+       usb_conv_info_t *usb_conv_info;
+       usb_conv_info = (usb_conv_info_t *)pinfo->usb_conv_info;
+
+       if (usb_conv_info->deviceVendor == tfp_USB_VENDOR_ID) {
+               col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFP over USB");
+               if (usb_conv_info->deviceProduct == tfp_USB_PRODUCT_ID) {
+                       col_clear(pinfo->cinfo, COL_INFO);
+                       dissect_tfp_common(tvb, pinfo, tree);
+               }
+               else {
+                       /* ToDo? Display "Unknown Product" ?? */
+               }
+               return;
+       }
+       else {
+               return; /* Not tfp_USB_VENDOR_ID */
+       }
+}
+
+/* protocol register function */
+void
+proto_register_tfp(void)
+{
+       /* defining header formats */
+       static hf_register_info hf_tfp[] = {
+               { &hf_tfp_uid,
+                       { "UID (String)",
+                         "tfp.uid",
+                         FT_STRINGZ,
+                         BASE_NONE,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_uid_numeric,
+                       { "UID (Numeric)",
+                         "tfp.uid_numeric",
+                         FT_UINT32,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_len,
+                       { "Length",
+                         "tfp.len",
+                         FT_UINT8,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_fid,
+                       { "Function ID",
+                         "tfp.fid",
+                         FT_UINT8,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_seq,
+                       { "Sequence Number",
+                         "tfp.seq",
+                         FT_UINT8,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_r,
+                       { "Response Expected",
+                         "tfp.r",
+                         FT_UINT8,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_a,
+                       { "Authentication",
+                         "tfp.a",
+                         FT_UINT8,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_oo,
+                       { "Other Options",
+                         "tfp.oo",
+                         FT_UINT8,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_e,
+                       { "Error Code",
+                         "tfp.e",
+                         FT_UINT8,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_future_use,
+                       { "Future Use",
+                         "tfp.future_use",
+                         FT_UINT8,
+                         BASE_DEC,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               },
+               { &hf_tfp_payload,
+                       { "Payload",
+                         "tfp.payload",
+                         FT_BYTES,
+                         BASE_NONE,
+                         NULL,
+                         0x0,
+                         NULL,
+                         HFILL
+                       }
+               }
+       };
+
+       /* setup protocol subtree array */
+       static gint *ett[] = {
+               &ett_tfp
+       };
+
+       /* defining the protocol and its names */
+       proto_tfp = proto_register_protocol (
+               "Tinkerforge Protocol",
+               "TFP",
+               "tfp"
+       );
+
+       proto_register_field_array(proto_tfp, hf_tfp, array_length(hf_tfp));
+       proto_register_subtree_array(ett, array_length(ett));
+}
+
+/* handoff function */
+void
+proto_reg_handoff_tfp(void) {
+
+       static dissector_handle_t
+               tfp_handle_tcp,
+               tfp_handle_usb;
+
+       tfp_handle_tcp = create_dissector_handle(dissect_tfp_tcp, proto_tfp);
+       tfp_handle_usb = create_dissector_handle(dissect_tfp_usb, proto_tfp);
+
+       dissector_add_uint("tcp.port", tfp_PORT, tfp_handle_tcp);
+       dissector_add_uint("usb.bulk", IF_CLASS_VENDOR_SPECIFIC, tfp_handle_usb);
+}
+
+/*
+ * 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:
+ */