(on behalf of the PROFIBUS Nutzerorganisation e.V. Deutschland):
authorulfl <ulfl@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 20 Apr 2006 19:49:12 +0000 (19:49 +0000)
committerulfl <ulfl@f5534014-38df-0310-8fa8-9805f1628bb7>
Thu, 20 Apr 2006 19:49:12 +0000 (19:49 +0000)
add Precision Time Control Protocol dissector (PTCP)

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@17930 f5534014-38df-0310-8fa8-9805f1628bb7

plugins/profinet/ChangeLog
plugins/profinet/Makefile.am
plugins/profinet/Makefile.nmake
plugins/profinet/moduleinfo.h
plugins/profinet/packet-pn-ptcp.c [new file with mode: 0644]
plugins/profinet/profinet.c

index 7cfcdc919367292c142e6dc622f3b511a310e4fd..ea88df6040646f4f4643bdf0056e976157477604 100644 (file)
@@ -20,4 +20,9 @@ Version 0.1.1:
 
 Version 0.1.2:
 
-* PN-DCP: dissection of "DHCP/DHCP client identifier" suboption was added
\ No newline at end of file
+* PN-DCP: dissection of "DHCP/DHCP client identifier" suboption was added
+
+Version 0.2.0:
+
+* PN-PTCP: add whole new Precision Time Control Protocol dissector
+
index 7a162159ede05ad8a1c816262b7df4d2dcdee293..3f24e71d92d295bf3162748441d2ddc3c51f4b56 100644 (file)
@@ -27,7 +27,7 @@ INCLUDES = -I$(top_srcdir)
 plugindir = @plugindir@
 
 plugin_LTLIBRARIES = profinet.la
-profinet_la_SOURCES = profinet.c packet-dcerpc-pn-io.c packet-pn-dcp.c moduleinfo.h
+profinet_la_SOURCES = profinet.c packet-dcerpc-pn-io.c packet-pn-dcp.c packet-pn-ptcp.c moduleinfo.h
 profinet_la_LDFLAGS = -module -avoid-version
 profinet_la_LIBADD = @PLUGIN_LIBS@
 
index c6430a4ec5d9c13c2f4f3295ba904951cd0f6d5f..7c3b086449c036902b081f40a64033de2c11e375 100644 (file)
@@ -15,7 +15,7 @@ LDFLAGS = /NOLOGO /INCREMENTAL:no /MACHINE:I386 $(LOCAL_LDFLAGS)
 LINK_PLUGIN_WITH=..\..\epan\libethereal.lib
 CFLAGS=/DHAVE_WIN32_LIBETHEREAL_LIB /D_NEED_VAR_IMPORT_ $(CFLAGS)
 
-OBJECTS=profinet.obj packet-dcerpc-pn-io.obj packet-pn-dcp.obj
+OBJECTS=profinet.obj packet-dcerpc-pn-io.obj packet-pn-dcp.obj packet-pn-ptcp.obj
 
 profinet.dll profinet.exp profinet.lib : $(OBJECTS) $(LINK_PLUGIN_WITH)
        link -dll /out:profinet.dll $(LDFLAGS) $(OBJECTS) $(LINK_PLUGIN_WITH) \
index 336667db6bb06152235fbe767c4a8f35a8e7fe5d..2782ab2fa482a9e7dae60721e6a088a14d7da6ed 100644 (file)
@@ -13,5 +13,5 @@
 #endif
 
 /* Version number of package */
-#define VERSION "0.1.2"
+#define VERSION "0.2.0"
 
diff --git a/plugins/profinet/packet-pn-ptcp.c b/plugins/profinet/packet-pn-ptcp.c
new file mode 100644 (file)
index 0000000..f21794c
--- /dev/null
@@ -0,0 +1,1081 @@
+/* packet-pn-ptcp.c
+ * Routines for PN-PTCP (PROFINET Precision Time Clock Protocol) 
+ * packet dissection.
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+#include <epan/packet.h>
+#include <epan/dissectors/packet-dcerpc.h>
+#include <epan/oui.h>
+
+static int proto_pn_ptcp = -1;
+
+static int hf_pn_ptcp = -1;
+static int hf_pn_ptcp_data = -1;
+static int hf_pn_ptcp_header = -1;
+static int hf_pn_ptcp_block = -1;
+static int hf_pn_ptcp_block_tlvheader = -1;
+
+static int hf_pn_ptcp_res1 = -1;
+static int hf_pn_ptcp_res2 = -1;
+static int hf_pn_ptcp_delay10ns = -1;
+static int hf_pn_ptcp_seq_id = -1;
+static int hf_pn_ptcp_delay1ns = -1;
+static int hf_pn_ptcp_padding8 = -1;
+static int hf_pn_ptcp_padding16 = -1;
+static int hf_pn_ptcp_delay1ps = -1;
+
+static int hf_pn_ptcp_tl_length = -1;
+static int hf_pn_ptcp_tl_type = -1;
+
+static int hf_pn_ptcp_master_source_address = -1;
+static int hf_pn_ptcp_subdomain_uuid = -1;
+
+static int hf_pn_ptcp_request_source_address = -1;
+static int hf_pn_ptcp_request_port_id = -1;
+static int hf_pn_ptcp_sync_id = -1;
+
+static int hf_pn_ptcp_t2portrxdelay = -1;
+static int hf_pn_ptcp_t3porttxdelay = -1;
+
+static int hf_pn_ptcp_seconds = -1;
+static int hf_pn_ptcp_nanoseconds = -1;
+
+static int hf_pn_ptcp_flags = -1;
+static int hf_pn_ptcp_epochnumber = -1;
+static int hf_pn_ptcp_currentutcoffset = -1;
+
+static int hf_pn_ptcp_clock_uuid = -1;
+static int hf_pn_ptcp_clockstratum = -1;
+static int hf_pn_ptcp_clockvariance = -1;
+static int hf_pn_ptcp_clockrole = -1;
+
+static int hf_pn_ptcp_oui = -1;
+static int hf_pn_ptcp_unknown_subtype = -1;
+static int hf_pn_ptcp_profinet_subtype = -1;
+static int hf_pn_ptcp_irdata_uuid = -1;
+
+static gint ett_pn_ptcp = -1;
+static gint ett_pn_ptcp_header = -1;
+static gint ett_pn_ptcp_block = -1;
+static gint ett_pn_ptcp_block_header = -1;
+
+
+
+static const value_string pn_ptcp_block_type[] = {
+       { 0x00, "End" },
+       { 0x01, "Subdomain"},
+       { 0x02, "Time"},
+       { 0x03, "TimeExtension"},
+       { 0x04, "Master"},
+       { 0x05, "PortParameter"},
+       { 0x06, "DelayParameter"},
+    /*0x07 - 0x7E Reserved */
+       { 0x7F, "Organizationally Specific"},
+
+    { 0, NULL }
+};
+
+static const value_string pn_ptcp_clock_stratum_vals[] = {
+       { 0x00, "Force" },
+       { 0x01, "Primary"},
+       { 0x02, "Secondary"},
+       { 0x03, "TimingSignal"},
+       { 0x04, "NoTimingSignal"},
+    /*0x05 - 0xFE Reserved */
+       { 0xFF, "Default"},
+
+    { 0, NULL }
+};
+
+static const value_string pn_ptcp_clock_role_vals[] = {
+       { 0x00, "Reserved" },
+       { 0x01, "Primary PTCP-Master"},
+       { 0x02, "Secondary PTCP-Master"},
+    /*0x03 - 0xFF Reserved */
+
+    { 0, NULL }
+};
+
+static const value_string pn_ptcp_oui_vals[] = {
+       { OUI_PROFINET,         "PROFINET" },
+
+       { 0, NULL }
+};
+
+static const value_string pn_ptcp_profinet_subtype_vals[] = {
+       { 0x01, "RTData" },
+
+       { 0, NULL }
+};
+
+
+/* XXX - use include file instead for these helpers */
+extern int dissect_pn_uint8(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                  proto_tree *tree, int hfindex, guint8 *pdata);
+
+extern int dissect_pn_uint16(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                       proto_tree *tree, int hfindex, guint16 *pdata);
+
+extern int dissect_pn_uint32(tvbuff_t *tvb, gint offset, packet_info *pinfo,
+                       proto_tree *tree, int hfindex, guint32 *pdata);
+
+
+
+/* dissect an 8 bit unsigned integer */
+int
+dissect_pn_uint8(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+                  proto_tree *tree, int hfindex, guint8 *pdata)
+{
+    guint8 data;
+
+    data = tvb_get_guint8 (tvb, offset);
+    if (tree) {
+        proto_tree_add_uint(tree, hfindex, tvb, offset, 1, data);
+    }
+    if (pdata)
+        *pdata = data;
+    return offset + 1;
+}
+
+/* dissect a 16 bit unsigned integer */
+int
+dissect_pn_uint16(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+                       proto_tree *tree, int hfindex, guint16 *pdata)
+{
+    guint16 data;
+
+    data = tvb_get_ntohs (tvb, offset);
+
+    if (tree) {
+        proto_tree_add_uint(tree, hfindex, tvb, offset, 2, data);
+    }
+    if (pdata)
+        *pdata = data;
+    return offset + 2;
+}
+
+/* dissect a 32 bit unsigned integer */
+int
+dissect_pn_uint32(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+                       proto_tree *tree, int hfindex, guint32 *pdata)
+{
+    guint32 data;
+
+    data = tvb_get_ntohl (tvb, offset);
+
+    if (tree) {
+        proto_tree_add_uint(tree, hfindex, tvb, offset, 4, data);
+    }
+    if (pdata)
+        *pdata = data;
+    return offset+4;
+}
+
+/* dissect a 16 bit signed integer */
+int
+dissect_pn_int16(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
+                       proto_tree *tree, int hfindex, gint16 *pdata)
+{
+    gint16 data;
+
+    data = tvb_get_ntohs (tvb, offset);
+
+    if (tree) {
+        proto_tree_add_int(tree, hfindex, tvb, offset, 2, data);
+    }
+    if (pdata)
+        *pdata = data;
+    return offset + 2;
+}
+
+/* dissect a 24bit OUI (IEC organizational unique id) */
+int 
+dissect_pn_oid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+                    proto_tree *tree, int hfindex, guint32 *pdata)
+{
+    guint32 data;
+
+    data = tvb_get_ntoh24(tvb, offset);
+
+    if (tree) {
+        proto_tree_add_uint(tree, hfindex, tvb, offset, 3, data);
+    }
+    if (pdata)
+        *pdata = data;
+    return offset+3;
+}
+
+/* dissect a 6 byte MAC address */
+int 
+dissect_pn_mac(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+                    proto_tree *tree, int hfindex, guint8 *pdata)
+{
+    guint8 data[6];
+
+    tvb_memcpy(tvb, data, offset, 6);
+    if(tree)
+        proto_tree_add_ether(tree, hfindex, tvb, offset, 6, data);
+
+    if (pdata)
+        memcpy(pdata, data, 6);
+
+    return offset + 6;
+}
+
+/* dissect a 12 byte UUID address */
+int 
+dissect_pn_uuid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
+                    proto_tree *tree, int hfindex, e_uuid_t *uuid)
+{
+    guint8 drep[2] = { 0,0 };
+
+    offset = dissect_dcerpc_uuid_t(tvb, offset, pinfo, tree, drep,
+                    hfindex, uuid);
+
+    return offset;
+}
+
+
+
+
+static int
+dissect_PNPTCP_TLVHeader(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 *type, guint16 *length)
+{
+    guint16 tl_type;
+    guint16 tl_length;
+
+
+    /* Type */
+    dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_tl_type, &tl_type);
+    *type = tl_type >> 9;
+
+    /* Length */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_tl_length, &tl_length);
+    *length = tl_length & 0x1FF;
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_Subdomain(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+    guint8 mac[6];
+    e_uuid_t uuid;
+
+    /* MasterSourceAddress */
+    offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_ptcp_master_source_address, mac);
+
+    /* SubdomainUUID */
+    offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_subdomain_uuid, &uuid);
+
+       proto_item_append_text(item, ": MasterSource=%02x:%02x:%02x:%02x:%02x:%02x", 
+        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+    proto_item_append_text(item, ", Subdomain=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                                      uuid.Data1, uuid.Data2, uuid.Data3,
+                                      uuid.Data4[0], uuid.Data4[1],
+                                      uuid.Data4[2], uuid.Data4[3],
+                                      uuid.Data4[4], uuid.Data4[5],
+                                      uuid.Data4[6], uuid.Data4[7]);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_Time(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+    guint16 padding16;
+    guint32 Seconds;
+    guint32 NanoSeconds;
+
+
+    /* Padding16 */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_padding16, &padding16);
+
+    /* Seconds */
+    offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_seconds, &Seconds);
+
+    /* NanoSeconds */
+    offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_nanoseconds, &NanoSeconds);
+
+       proto_item_append_text(item, ": Seconds=%u NanoSeconds=%u", 
+        Seconds, NanoSeconds);
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+      col_append_fstr(pinfo->cinfo, COL_INFO, ", Time: %4us %09uns", Seconds, NanoSeconds);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_TimeExtension(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+    guint16 Flags;
+    guint16 EpochNumber;
+    guint16 CurrentUTCOffset;
+
+
+    /* Flags */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_flags, &Flags);
+
+    /* EpochNumber */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_epochnumber, &EpochNumber);
+
+    /* CurrentUTCOffset */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_currentutcoffset, &CurrentUTCOffset);
+
+       proto_item_append_text(item, ": Flags=0x%x, EpochNumber=%u, CurrentUTCOffset=%u", 
+        Flags, EpochNumber, CurrentUTCOffset);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_Master(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+    e_uuid_t uuid;
+    guint8 ClockStratum;
+    gint16 ClockVariance;
+    gint8 ClockRole;
+
+    /* ClockVariance */
+    offset = dissect_pn_int16(tvb, offset, pinfo, tree, hf_pn_ptcp_clockvariance, &ClockVariance);
+
+    /* ClockUUID */
+    offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_clock_uuid, &uuid);
+
+    /* ClockStratum */
+    offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_clockstratum, &ClockStratum);
+
+    /* ClockRole */
+    offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_clockrole, &ClockRole);
+
+    proto_item_append_text(item, ": ClockUUID=%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                                      uuid.Data1, uuid.Data2, uuid.Data3,
+                                      uuid.Data4[0], uuid.Data4[1],
+                                      uuid.Data4[2], uuid.Data4[3],
+                                      uuid.Data4[4], uuid.Data4[5],
+                                      uuid.Data4[6], uuid.Data4[7]);
+
+       proto_item_append_text(item, ", ClockStratum=%s, ClockVariance=%d", 
+        val_to_str(ClockStratum, pn_ptcp_clock_stratum_vals, "(Reserved: 0x%x)"), ClockVariance);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_PortParameter(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+    guint16 padding16;
+    guint32 t2portrxdelay;
+    guint32 t3porttxdelay;
+
+
+    /* Padding16 */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_ptcp_padding16, &padding16);
+
+    /* T2PortRxDelay */
+    offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_t2portrxdelay, &t2portrxdelay);
+
+    /* T3PortTxDelay */
+    offset = dissect_pn_uint32(tvb, offset, pinfo, tree, hf_pn_ptcp_t3porttxdelay, &t3porttxdelay);
+
+       proto_item_append_text(item, ": T2PortRxDelay=%uns, T3PortTxDelay=%uns", 
+        t2portrxdelay, t3porttxdelay);
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+      col_append_fstr(pinfo->cinfo, COL_INFO, ", T2Rx=%uns, T3Tx=%uns", 
+        t2portrxdelay, t3porttxdelay);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_DelayParameter(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+    guint8 mac[6];
+    guint8 requestportid;
+    guint8 syncid;
+
+
+    /* RequestSourceAddress */
+    offset = dissect_pn_mac(tvb, offset, pinfo, tree, hf_pn_ptcp_request_source_address, mac);
+
+    /* RequestPortID */
+    offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_request_port_id, &requestportid);
+
+    /* SyncID */
+    offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_sync_id, &syncid);
+
+    
+    proto_item_append_text(item, ": RequestSource=%02x:%02x:%02x:%02x:%02x:%02x", 
+        mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+    proto_item_append_text(item, ", RequestPortID=0x%02x, SyncID=0x%02x", 
+        requestportid, syncid);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_Option_PROFINET(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 length)
+{
+       guint8 subType;
+    guint8 padding8;
+    e_uuid_t uuid;
+
+    /* OUI already dissected! */
+
+    /* SubType */
+    offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_profinet_subtype, &subType);
+    length --;
+
+    switch(subType) {
+    case 1: /* RTData */
+        /* Padding8 */
+        offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_padding8, &padding8);
+
+        /* IRDataUUID */
+        offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_ptcp_irdata_uuid, &uuid);
+        break;
+    default:
+        proto_tree_add_string_format(tree, hf_pn_ptcp_data, tvb, offset, length, "data", 
+            "PROFINET Data: %d bytes", length);
+        break;
+    }
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_Option(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 length)
+{
+       guint32 oui;
+       guint8 subType;
+
+
+    /* verify remaining TLV length */
+       if (length < 4)
+       {
+        if (tree) {
+            proto_tree_add_string_format(tree, hf_pn_ptcp_data, tvb, offset, length, "data", 
+                "Length: %u (too short, must be >= 4)", length);
+        }
+               return (offset);
+       }
+
+       /* OUI (organizational unique id) */
+    offset = dissect_pn_oid(tvb, offset, pinfo,tree, hf_pn_ptcp_oui, &oui);
+    length -= 3;
+       
+       switch (oui)
+       {
+       case OUI_PROFINET:
+        offset = dissect_PNPTCP_Option_PROFINET(tvb, offset, pinfo, tree, item, length);
+               break;
+       default:
+        /* SubType */
+        offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_ptcp_unknown_subtype, &subType);
+        length --;
+        proto_tree_add_string_format(tree, hf_pn_ptcp_data, tvb, offset, length, "data", 
+            "Unknown OUI Data: %d bytes", length);
+       }
+       
+       return (offset);
+}
+
+
+static int
+dissect_PNPTCP_block(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, gboolean *end)
+{
+    guint16 type;
+    guint16 length;
+
+       proto_item *sub_item;
+       proto_tree *sub_tree;
+       proto_item *tlvheader_item;
+       proto_tree *tlvheader_tree;
+       guint32 u32SubStart;
+
+
+    *end = FALSE;
+
+    /* block subtree */
+    sub_item = proto_tree_add_item(tree, hf_pn_ptcp_block, tvb, offset, 0, FALSE);
+       sub_tree = proto_item_add_subtree(sub_item, ett_pn_ptcp_block);
+    u32SubStart = offset;
+
+    /* tlvheader subtree */
+    tlvheader_item = proto_tree_add_item(sub_tree, hf_pn_ptcp_block_tlvheader, tvb, offset, 2 /* len */, FALSE);
+       tlvheader_tree = proto_item_add_subtree(tlvheader_item, ett_pn_ptcp_block_header);
+
+    offset = dissect_PNPTCP_TLVHeader(tvb, offset, pinfo, tlvheader_tree, sub_item, &type, &length);
+
+       proto_item_append_text(sub_item, "%s", 
+        val_to_str(type, pn_ptcp_block_type, "Unknown"));
+
+       proto_item_append_text(tlvheader_item, ": Type=%s (%x), Length=%u", 
+        val_to_str(type, pn_ptcp_block_type, "Unknown"), type, length);
+
+    switch(type) {
+    case(0x00): /* End, no content */
+        *end = TRUE;
+        break;
+    case(0x01): /* Subdomain */
+        dissect_PNPTCP_Subdomain(tvb, offset, pinfo, sub_tree, sub_item);
+        break;
+    case(0x02): /* Time */
+        dissect_PNPTCP_Time(tvb, offset, pinfo, sub_tree, sub_item);
+        break;
+    case(0x03): /* TimeExtension */
+        dissect_PNPTCP_TimeExtension(tvb, offset, pinfo, sub_tree, sub_item);
+        break;
+    case(0x04): /* Master */
+        dissect_PNPTCP_Master(tvb, offset, pinfo, sub_tree, sub_item);
+        break;
+    case(0x05): /* PortParameter */
+        dissect_PNPTCP_PortParameter(tvb, offset, pinfo, sub_tree, sub_item);
+        break;
+    case(0x06): /* DelayParameter */
+        dissect_PNPTCP_DelayParameter(tvb, offset, pinfo, sub_tree, sub_item);
+        break;
+    case(0x7F): /* Organizational Specific */
+        dissect_PNPTCP_Option(tvb, offset, pinfo, sub_tree, sub_item, length);
+        break;
+    default:
+        proto_tree_add_string_format(sub_tree, hf_pn_ptcp_data, tvb, offset, length, "data", 
+            "PN-PTCP Unknown BlockType 0x%x, Data: %d bytes", type, length);
+    }
+    offset += length;
+
+       proto_item_set_len(sub_item, offset - u32SubStart);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_blocks(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+    gboolean end = FALSE;
+
+    /* as long as we have some bytes, try a new block */
+    while(!end) {
+        offset = dissect_PNPTCP_block(tvb, offset, pinfo, tree, item, &end);
+    }
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_Header(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, gboolean delay_valid)
+{
+       proto_item *header_item;
+       proto_tree *header_tree;
+    guint32 res_1;
+    guint32 res_2;
+    guint32 delay10ns;
+    guint16 seq_id;
+    guint8 delay1ns;
+    guint8 padding8;
+    guint16 padding16;
+    guint16 delay1ps;
+    guint64 delayns;
+    guint32 delayms;
+
+
+    header_item = proto_tree_add_item(tree, hf_pn_ptcp_header, tvb, offset, 20 /* len */, FALSE);
+       header_tree = proto_item_add_subtree(header_item, ett_pn_ptcp_header);
+
+    /* Reserved_1 */
+    offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_res1, &res_1);
+
+    /* Reserved_2 */
+    offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_res2, &res_2);
+
+    /* Delay10ns */
+    offset = dissect_pn_uint32(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay10ns, &delay10ns);
+
+    /* SequenceID */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_seq_id, &seq_id);
+
+    /* Delay1ns */
+    offset = dissect_pn_uint8(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ns, &delay1ns);
+
+    /* Padding8 */
+    offset = dissect_pn_uint8(tvb, offset, pinfo, header_tree, hf_pn_ptcp_padding8, &padding8);
+
+    /* Delay1ps */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_delay1ps, &delay1ps);
+
+    /* Padding16 */
+    offset = dissect_pn_uint16(tvb, offset, pinfo, header_tree, hf_pn_ptcp_padding16, &padding16);
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+      col_append_fstr(pinfo->cinfo, COL_INFO, "Seq=%3u", seq_id);
+    proto_item_append_text(item, ": Sequence=%u", seq_id);
+    proto_item_append_text(header_item, ": Sequence=%u", seq_id);
+
+    /* the delay field is meaningful only in specific PDU's */
+    if(delay_valid) {
+        delayns = ((guint64) delay10ns) * 10 + delay1ns;
+        delayms = (guint32) (delayns / (1000 * 1000));
+
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_fstr(pinfo->cinfo, COL_INFO, ", Delay=%11" PRIu64 "ns", 
+            delayns);
+          proto_item_append_text(item, ", Delay=%" PRIu64 "ns", delayns);
+
+        if(delayns != 0) {
+            proto_item_append_text(header_item, ", Delay=%" PRIu64 "ns (%u.%03u,%03u,%03u sec)", 
+                delayns, 
+                delayms / 1000,
+                delayms % 1000,
+                (delay10ns % (1000*100)) / 100, 
+                 delay10ns % 100 * 10 + delay1ns);
+        } else {
+            proto_item_append_text(header_item, ", Delay=%" PRIu64 "ns", 
+                delayns);
+        }
+    }
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_FollowUpPDU(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID)
+{
+
+    switch(u16FrameID) {
+    case(0xFF20):
+           proto_item_append_text(item, "%s", "FollowUp (Clock)");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "FollowUp (Clock), ");
+        break;
+    case(0xFF21):
+           proto_item_append_text(item, "%s", "FollowUp (Time)");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "FollowUp (Time) , ");
+        break;
+    default:
+           proto_item_append_text(item, "%s", "FollowUp");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "FollowUp, ");
+    }
+
+    /* dissect the header */
+    offset = dissect_PNPTCP_Header(tvb, offset, pinfo, tree, item, FALSE /* !delay_valid*/);
+    
+    /* dissect the PDU */
+    offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_RTASyncPDU(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID)
+{
+
+    switch(u16FrameID) {
+    case(0x0000):
+    case(0x0020):
+           proto_item_append_text(item, "%s", "RTASync (Clock)");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "RTASync  (Clock), ");
+    break;
+    case(0x0001):
+    case(0x0021):
+           proto_item_append_text(item, "%s", "RTASync (Time)");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "RTASync  (Time) , ");
+    break;
+    default:
+           proto_item_append_text(item, "%s", "RTASync");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "RTASync,  ");
+    }
+
+    /* dissect the header */
+    offset = dissect_PNPTCP_Header(tvb, offset, pinfo, tree, item, FALSE /* !delay_valid*/);
+    
+    /* dissect the PDU */
+    offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_RTCSyncPDU(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+      col_append_str(pinfo->cinfo, COL_INFO, "RTCSync,   ");
+
+       proto_item_append_text(item, "%s", "RTCSync");
+
+    /* dissect the header */
+    offset = dissect_PNPTCP_Header(tvb, offset, pinfo, tree, item, FALSE /* !delay_valid*/);
+    
+    /* dissect the PDU */
+    offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_AnnouncePDU(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, guint16 u16FrameID)
+{
+
+    switch(u16FrameID) {
+    case(0xFF00):
+           proto_item_append_text(item, "%s", "Announce (Clock)");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "Announce (Clock), ");
+    break;
+    case(0xFF01):
+           proto_item_append_text(item, "%s", "Announce (Time)");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "Announce (Time) , ");
+    break;
+    default:
+           proto_item_append_text(item, "%s", "Announce");
+        if (check_col(pinfo->cinfo, COL_INFO))
+          col_append_str(pinfo->cinfo, COL_INFO, "Announce,  ");
+    }
+
+    /* dissect the header */
+    offset = dissect_PNPTCP_Header(tvb, offset, pinfo, tree, item, FALSE /* !delay_valid*/);
+    
+    /* dissect the PDU */
+    offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_DelayReqPDU(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+      col_append_str(pinfo->cinfo, COL_INFO, "DelayReq,   ");
+
+       proto_item_append_text(item, "%s", "DelayReq");
+
+    /* dissect the header */
+    offset = dissect_PNPTCP_Header(tvb, offset, pinfo, tree, item, FALSE /* !delay_valid*/);
+    
+    /* dissect the PDU */
+    offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_DelayResPDU(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+      col_append_str(pinfo->cinfo, COL_INFO, "DelayRes,   ");
+
+       proto_item_append_text(item, "%s", "DelayRes");
+
+    /* dissect the header */
+    offset = dissect_PNPTCP_Header(tvb, offset, pinfo, tree, item, TRUE /* delay_valid*/);
+    
+    /* dissect the PDU */
+    offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item);
+
+    return offset;
+}
+
+
+static int
+dissect_PNPTCP_DelayFuResPDU(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
+{
+
+    if (check_col(pinfo->cinfo, COL_INFO))
+      col_append_str(pinfo->cinfo, COL_INFO, "DelayFuRes, ");
+
+       proto_item_append_text(item, "%s", "DelayFuRes");
+
+    /* dissect the header */
+    offset = dissect_PNPTCP_Header(tvb, offset, pinfo, tree, item, TRUE /* delay_valid*/);
+    
+    /* dissect the PDU */
+    offset = dissect_PNPTCP_blocks(tvb, offset, pinfo, tree, item);
+
+    return offset;
+}
+
+
+/* possibly dissect a PN-RT packet (frame ID must be in the appropriate range) */
+static gboolean
+dissect_PNPTCP_Data_heur(tvbuff_t *tvb, 
+       packet_info *pinfo, proto_tree *tree)
+{
+    guint16 u16FrameID;
+    proto_item *item = NULL;
+    proto_tree *ptcp_tree = NULL;
+    int offset = 0;
+       guint32 u32SubStart;
+
+
+    /* the tvb will NOT contain the frame_id here, so get it from our private data! */
+    u16FrameID = GPOINTER_TO_UINT(pinfo->private_data);
+
+       /* frame id must be in valid range (acyclic Real-Time, DCP) */
+    /* 0x0000 - 0x007F: RTASyncPDU */
+    /* 0x0080 - 0x00FF: RTCSyncPDU */
+    /* 0xFF00 - 0xFF1F: AnnouncePDU */
+    /* 0xFF20 - 0xFF3F: FollowUpPDU */
+    /* 0xFF40 - 0xFF5F: Delay...PDU */
+       if ( (u16FrameID > 0x0100 && u16FrameID < 0xFF00) || (u16FrameID > 0xFF5F) ) {
+        /* we are not interested in this packet */
+        return FALSE;
+    }
+
+       if (check_col(pinfo->cinfo, COL_PROTOCOL))
+           col_add_str(pinfo->cinfo, COL_PROTOCOL, "PN-PTCP");
+    if (check_col(pinfo->cinfo, COL_INFO))
+      col_add_str(pinfo->cinfo, COL_INFO, "");
+
+    /* subtree for PTCP */
+       item = proto_tree_add_protocol_format(tree, proto_pn_ptcp, tvb, 0, 0, "PROFINET PTCP, ");
+       ptcp_tree = proto_item_add_subtree(item, ett_pn_ptcp);
+    u32SubStart = offset;
+
+    switch(u16FrameID) {
+    /* range 1 (0x0000 - 0x007F) */
+    case(0x0000):
+    case(0x0001):
+        /* Send clock and phase synchronization */
+        offset = dissect_PNPTCP_RTASyncPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID);
+        break;
+        /* 0x0002 - 0x001F reserved */
+    case(0x0020):
+    case(0x0021):
+        /* Time synchronization */
+        offset = dissect_PNPTCP_RTASyncPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID);
+        break;
+        /* 0x0022 - 0x007F reserved */
+
+    /* range 2 (0x0080 - 0x00FF) */
+    case(0x0080):
+        /* class 3 synchronization */
+        offset = dissect_PNPTCP_RTCSyncPDU(tvb, offset, pinfo, ptcp_tree, item);
+        break;
+        /* 0x0081 - 0x00FF reserved */
+
+    /* range 7 (0xFF00 - 0xFF5F) */
+    case(0xff00):
+    case(0xff01):
+        offset = dissect_PNPTCP_AnnouncePDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID);
+        break;
+        /* 0xFF02 - 0xFF1F reserved */
+    case(0xff20):
+    case(0xff21):
+        offset = dissect_PNPTCP_FollowUpPDU(tvb, offset, pinfo, ptcp_tree, item, u16FrameID);
+        break;
+        /* 0xFF22 - 0xFF3F reserved */
+    case(0xff40):
+        offset = dissect_PNPTCP_DelayReqPDU(tvb, offset, pinfo, ptcp_tree, item);
+        break;
+    case(0xff41):
+        offset = dissect_PNPTCP_DelayResPDU(tvb, offset, pinfo, ptcp_tree, item);
+        break;
+    case(0xff42):
+        offset = dissect_PNPTCP_DelayFuResPDU(tvb, offset, pinfo, ptcp_tree, item);
+        break;
+    case(0xff43):
+        offset = dissect_PNPTCP_DelayResPDU(tvb, offset, pinfo, ptcp_tree, item);
+        break;
+        /* 0xFF44 - 0xFF5F reserved */
+    default:
+        proto_tree_add_string_format(ptcp_tree, hf_pn_ptcp_data, tvb, offset, tvb_length_remaining(tvb, offset), "data", 
+            "PN-PTCP Reserved FrameID 0x%04x, Data: %d bytes", u16FrameID, tvb_length_remaining(tvb, offset));
+               if (check_col(pinfo->cinfo, COL_INFO))
+                       col_append_fstr(pinfo->cinfo, COL_INFO, "Reserved FrameID 0x%04x", u16FrameID);
+
+               proto_item_append_text(item, "Reserved FrameID 0x%04x", u16FrameID);
+
+        offset += tvb_length_remaining(tvb, offset);
+    }
+
+       proto_item_set_len(item, offset - u32SubStart);
+
+    return TRUE;
+}
+
+
+void
+proto_register_pn_ptcp (void)
+{
+       static hf_register_info hf[] = {
+       { &hf_pn_ptcp,
+               { "PROFINET PTCP", "pn_ptcp", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
+    { &hf_pn_ptcp_data,
+        { "Undecoded Data", "pn_ptcp.data", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_header,
+        { "Header", "pn_ptcp.header", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_block,
+        { "", "pn_ptcp.block", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_block_tlvheader,
+        { "TLVHeader", "pn_ptcp.tlvheader", FT_NONE, BASE_NONE, NULL, 0x0, "", HFILL }},
+
+       { &hf_pn_ptcp_res1,
+               { "Reserved 1", "pn_ptcp.res1", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_res2,
+               { "Reserved 2", "pn_ptcp.res2", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_delay10ns,
+               { "Delay10ns", "pn_ptcp.delay10ns", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_seq_id,
+               { "SequenceID", "pn_ptcp.sequence_id", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_delay1ns,
+               { "Delay1ns", "pn_ptcp.delay1ns", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_padding8,
+               { "Padding", "pn_ptcp.padding8", FT_UINT8, BASE_HEX, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_padding16,
+               { "Padding", "pn_ptcp.padding16", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_delay1ps,
+               { "Delay1ps", "pn_ptcp.delay1ps", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+
+       { &hf_pn_ptcp_tl_length,
+        { "TypeLength.Length", "pn_ptcp.tl_length", FT_UINT16, BASE_DEC, 0x0, 0x1FF, "", HFILL }},
+       { &hf_pn_ptcp_tl_type, 
+        { "TypeLength.Type", "pn_ptcp.tl_type", FT_UINT16, BASE_DEC, 0x0, 0xFE00, "", HFILL }},
+
+       { &hf_pn_ptcp_master_source_address,
+        { "MasterSourceAddress", "pn_ptcp.master_source_address", FT_ETHER, BASE_HEX, 0x0, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_subdomain_uuid,
+        { "SubdomainUUID", "pn_ptcp.subdomain_uuid", FT_STRING, BASE_NONE, 0x0, 0x0, "", HFILL }},
+       
+    { &hf_pn_ptcp_request_source_address,
+        { "RequestSourceAddress", "pn_ptcp.request_source_address", FT_ETHER, BASE_HEX, 0x0, 0x0, "", HFILL }},
+    { &hf_pn_ptcp_request_port_id,
+        { "RequestPortID", "pn_ptcp.request_port_id", FT_UINT8, BASE_HEX, 0x0, 0x0, "", HFILL }},
+    { &hf_pn_ptcp_sync_id,
+        { "SyncID", "pn_ptcp.sync_id", FT_UINT8, BASE_HEX, 0x0, 0x0, "", HFILL }},
+
+       { &hf_pn_ptcp_t2portrxdelay,
+        { "T2PortRxDelay (ns)", "pn_ptcp.t2portrxdelay", FT_UINT32, BASE_DEC, 0x0, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_t3porttxdelay,
+        { "T3PortTxDelay (ns)", "pn_ptcp.t3porttxdelay", FT_UINT32, BASE_DEC, 0x0, 0x0, "", HFILL }},
+
+       { &hf_pn_ptcp_seconds,
+        { "Seconds", "pn_ptcp.seconds", FT_UINT32, BASE_DEC, 0x0, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_nanoseconds,
+        { "NanoSeconds", "pn_ptcp.nanoseconds", FT_UINT32, BASE_DEC, 0x0, 0x0, "", HFILL }},
+
+       { &hf_pn_ptcp_flags,
+        { "Flags", "pn_ptcp.flags", FT_UINT16, BASE_HEX, 0x0, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_epochnumber,
+        { "EpochNumber", "pn_ptcp.epochnumber", FT_UINT16, BASE_DEC, 0x0, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_currentutcoffset,
+        { "CurrentUTCOffset", "pn_ptcp.currentutcoffset", FT_UINT16, BASE_DEC, 0x0, 0x0, "", HFILL }},
+
+
+       { &hf_pn_ptcp_clock_uuid,
+        { "ClockUUID", "pn_ptcp.clock_uuid", FT_STRING, BASE_NONE, 0x0, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_clockstratum,
+        { "ClockStratum", "pn_ptcp.clockstratum", FT_UINT8, BASE_HEX, VALS(pn_ptcp_clock_stratum_vals), 0x0, "", HFILL }},
+       { &hf_pn_ptcp_clockvariance,
+        { "ClockVariance", "pn_ptcp.clockvariance", FT_INT16, BASE_DEC, 0x0, 0x0, "", HFILL }},
+       { &hf_pn_ptcp_clockrole,
+        { "ClockRole", "pn_ptcp.clockrole", FT_UINT8, BASE_HEX, VALS(pn_ptcp_clock_role_vals), 0x0, "", HFILL }},
+
+       { &hf_pn_ptcp_oui,
+               { "Organizationally Unique Identifier", "pn_ptcp.oui", FT_UINT24, BASE_HEX,
+               VALS(pn_ptcp_oui_vals), 0x0, "", HFILL }},
+       { &hf_pn_ptcp_profinet_subtype,
+               { "Subtype",    "pn_ptcp.subtype", FT_UINT8, BASE_HEX,
+               VALS(pn_ptcp_profinet_subtype_vals), 0x0, "PROFINET Subtype", HFILL }},
+       { &hf_pn_ptcp_unknown_subtype,
+               { "Subtype",    "pn_ptcp.subtype", FT_UINT8, BASE_HEX, 0x0, 0x0, "Unkown Subtype", HFILL }},
+        
+       { &hf_pn_ptcp_irdata_uuid,
+        { "IRDataUUID", "pn_ptcp.irdata_uuid", FT_STRING, BASE_NONE, 0x0, 0x0, "", HFILL }},
+       };
+
+       static gint *ett[] = {
+               &ett_pn_ptcp,
+               &ett_pn_ptcp_header,
+        &ett_pn_ptcp_block,
+        &ett_pn_ptcp_block_header
+    };
+       proto_pn_ptcp = proto_register_protocol ("PROFINET PTCP", "PN-PTCP", "pn_ptcp");
+       proto_register_field_array (proto_pn_ptcp, hf, array_length (hf));
+       proto_register_subtree_array (ett, array_length (ett));
+}
+
+void
+proto_reg_handoff_pn_ptcp (void)
+{
+    /* register ourself as an heuristic pn-rt payload dissector */
+       heur_dissector_add("pn_rt", dissect_PNPTCP_Data_heur, proto_pn_ptcp);
+}
index f8ca6da33061013e759c261cb23aecc644149d22..f3e6b806fa78e08c9f0971fe8d4247de1fc1e36e 100644 (file)
@@ -46,8 +46,8 @@ extern void proto_register_pn_io (void);
 extern void proto_reg_handoff_pn_io (void);
 extern void proto_register_pn_dcp (void);
 extern void proto_reg_handoff_pn_dcp (void);
-
-
+extern void proto_register_pn_ptcp (void);
+extern void proto_reg_handoff_pn_ptcp (void);
 
 /* Start the functions we need for the plugin stuff */
 
@@ -60,6 +60,7 @@ plugin_register(void)
   if (plugin_registered == FALSE) { /* execute protocol initialization only once */
     proto_register_pn_io();
     proto_register_pn_dcp();
+    proto_register_pn_ptcp();
          
        plugin_registered = TRUE;
   }
@@ -69,6 +70,7 @@ G_MODULE_EXPORT void
 plugin_reg_handoff(void){
   proto_reg_handoff_pn_io();
   proto_reg_handoff_pn_dcp();
+  proto_reg_handoff_pn_ptcp();
 }
 
 #endif